[renpy] 02/12: New upstream version 6.99.12+dfsg

Markus Koschany apo at moszumanska.debian.org
Wed Dec 21 14:34:35 UTC 2016


This is an automated email from the git hooks/post-receive script.

apo pushed a commit to branch master
in repository renpy.

commit 421d7cd964e25991176f07da30f5792385bdfdea
Author: Markus Koschany <apo at debian.org>
Date:   Wed Dec 21 12:20:47 2016 +0100

    New upstream version 6.99.12+dfsg
---
 doc/achievement.html                               |    5 +-
 doc/android-packaging.html                         |    5 +-
 doc/android.html                                   |    5 +-
 doc/atl.html                                       |    5 +-
 doc/audio.html                                     |    7 +-
 doc/build.html                                     |   19 +-
 doc/cds.html                                       |    5 +-
 doc/changelog.html                                 |  319 ++--
 doc/character_callbacks.html                       |    5 +-
 doc/chromeos.html                                  |    5 +-
 doc/color_class.html                               |    5 +-
 doc/conditional.html                               |    5 +-
 doc/config.html                                    |   24 +-
 doc/credits.html                                   |    5 +-
 doc/custom_text_tags.html                          |    5 +-
 doc/developer_tools.html                           |    5 +-
 doc/dialogue.html                                  |   34 +-
 doc/display_problems.html                          |    5 +-
 doc/displayables.html                              |   13 +-
 doc/displaying_images.html                         |    5 +-
 doc/distributor.html                               |    5 +-
 doc/drag_drop.html                                 |    5 +-
 doc/editor.html                                    |    5 +-
 doc/environment_variables.html                     |    5 +-
 doc/file_python.html                               |    5 +-
 doc/genindex.html                                  |   57 +-
 doc/gesture.html                                   |    5 +-
 doc/gui.html                                       |    5 +-
 doc/history.html                                   |    5 +-
 doc/iap.html                                       |    5 +-
 doc/incompatible.html                              |    5 +-
 doc/index.html                                     |    6 +-
 doc/input.html                                     |    5 +-
 doc/ios.html                                       |    5 +-
 doc/keymap.html                                    |    5 +-
 doc/label.html                                     |    5 +-
 doc/language_basics.html                           |    5 +-
 doc/license.html                                   |    5 +-
 doc/menus.html                                     |    5 +-
 doc/modes.html                                     |    5 +-
 doc/movie.html                                     |    5 +-
 doc/nvl_mode.html                                  |    5 +-
 doc/objects.inv                                    |  Bin 10618 -> 10760 bytes
 doc/other.html                                     |    5 +-
 doc/persistent.html                                |    5 +-
 doc/problems.html                                  |    5 +-
 doc/py-function-class-index.html                   |   30 +-
 doc/python.html                                    |    5 +-
 doc/quickstart.html                                |   24 +-
 doc/reserved.html                                  |    6 +-
 doc/rooms.html                                     |    9 +-
 doc/save_load_rollback.html                        |    5 +-
 doc/screen_actions.html                            |   57 +-
 doc/screen_optimization.html                       |    7 +-
 doc/screen_python.html                             |    5 +-
 doc/screen_special.html                            |    5 +-
 doc/screens.html                                   |   27 +-
 doc/search.html                                    |    5 +-
 doc/searchindex.js                                 |    2 +-
 doc/self_voicing.html                              |    5 +-
 doc/side_image.html                                |    5 +-
 doc/skins.html                                     |    7 +-
 doc/sprites.html                                   |    5 +-
 doc/statement_equivalents.html                     |    5 +-
 doc/std-style-property-index.html                  |    5 +-
 doc/std-transform-property-index.html              |    5 +-
 doc/std-var-index.html                             |   30 +-
 doc/store_variables.html                           |    5 +-
 doc/style.html                                     |    5 +-
 doc/style_properties.html                          |    5 +-
 doc/text.html                                      |    5 +-
 doc/thequestion.html                               |    5 +-
 doc/thequestion_nvl.html                           |    5 +-
 doc/trans_trans_python.html                        |    5 +-
 doc/transforms.html                                |    5 +-
 doc/transitions.html                               |    7 +-
 doc/{updater.html => translating_renpy.html}       |  282 +--
 doc/translation.html                               |    7 +-
 doc/udd.html                                       |    5 +-
 doc/updater.html                                   |    5 +-
 doc/voice.html                                     |    7 +-
 gui/game/gui.rpy                                   |   19 +-
 gui/game/options.rpy                               |    4 +-
 gui/game/screens.rpy                               |   72 +-
 gui/game/script.rpy                                |   26 +-
 gui/game/testcases.rpy                             |   14 +
 launcher/game/EasyDialogsWin.py                    |    3 +-
 launcher/game/about.rpy                            |    2 +-
 launcher/game/android.rpy                          |    4 +-
 launcher/game/archiver.rpy                         |    8 +-
 launcher/game/change_icon.py                       |   51 +-
 launcher/game/choose_directory.rpy                 |   22 +-
 launcher/game/choose_theme.rpy                     |    2 +-
 launcher/game/distribute.rpy                       |  339 +++-
 launcher/game/distribute_gui.rpy                   |    2 +-
 launcher/game/editor.rpy                           |    4 +-
 launcher/game/fonts/DroidSansFallback.ttf          |  Bin 0 -> 3939852 bytes
 launcher/game/fonts/MTLc3m.ttf                     |  Bin 0 -> 1924864 bytes
 launcher/game/fonts/NanumGothic.ttf                |  Bin 0 -> 2369696 bytes
 .../korean => fonts}/Naver Nanum Font License.txt  |    0
 launcher/game/fonts/Roboto-Light.ttf               |  Bin 0 -> 126792 bytes
 launcher/game/fonts/Roboto-Regular.ttf             |  Bin 0 -> 126072 bytes
 launcher/game/front_page.rpy                       |    2 +-
 launcher/game/gui7.rpy                             |   68 +-
 launcher/game/gui7/__init__.py                     |   15 +-
 launcher/game/gui7/code.py                         |  162 +-
 launcher/game/gui7/images.py                       |    2 +-
 launcher/game/interface.rpy                        |    2 +-
 launcher/game/ios.rpy                              |    2 +-
 launcher/game/itch.rpy                             |    4 +
 launcher/game/navigation.rpy                       |    2 +-
 launcher/game/new_project.rpy                      |    8 +-
 launcher/game/options.rpy                          |  215 +--
 launcher/game/package_formats.rpy                  |    1 +
 launcher/game/pefile.py                            |    9 +-
 launcher/game/preferences.rpy                      |    2 +-
 launcher/game/project.rpy                          |   86 +-
 launcher/game/style.rpy                            |  506 +++---
 launcher/game/testcases.rpy                        |  112 ++
 launcher/game/tl/arabic/about.rpy                  |   15 -
 launcher/game/tl/arabic/add_file.rpy               |   23 -
 launcher/game/tl/arabic/android.rpy                |  200 ---
 launcher/game/tl/arabic/choose_directory.rpy       |    7 -
 launcher/game/tl/arabic/choose_theme.rpy           |   43 -
 launcher/game/tl/arabic/common.rpy                 |  718 +++-----
 launcher/game/tl/arabic/developer.rpy              |  179 ++
 launcher/game/tl/arabic/distribute.rpy             |   52 -
 launcher/game/tl/arabic/distribute_gui.rpy         |   66 -
 launcher/game/tl/arabic/editor.rpy                 |   64 -
 launcher/game/tl/arabic/error.rpy                  |  179 ++
 launcher/game/tl/arabic/front_page.rpy             |  131 --
 launcher/game/tl/arabic/gui.rpy                    |  411 +++++
 launcher/game/tl/arabic/interface.rpy              |   90 -
 launcher/game/tl/arabic/ios.rpy                    |  100 --
 launcher/game/tl/arabic/launcher.rpy               | 1187 +++++++++++++
 launcher/game/tl/arabic/navigation.rpy             |   71 -
 launcher/game/tl/arabic/new_project.rpy            |   48 -
 launcher/game/tl/arabic/obsolete.rpy               |   27 +
 launcher/game/tl/arabic/options.rpy                |  195 +++
 launcher/game/tl/arabic/preferences.rpy            |   95 -
 launcher/game/tl/arabic/project.rpy                |   68 -
 launcher/game/tl/arabic/screens.rpy                |  643 +++++++
 launcher/game/tl/arabic/script.rpym                |   21 +
 launcher/game/tl/arabic/style.rpy                  |   20 +-
 launcher/game/tl/arabic/translations.rpy           |   38 -
 launcher/game/tl/arabic/updater.rpy                |  100 --
 launcher/game/tl/finnish/about.rpy                 |   14 -
 launcher/game/tl/finnish/add_file.rpy              |   23 -
 launcher/game/tl/finnish/android.rpy               |  171 --
 launcher/game/tl/finnish/choose_directory.rpy      |    7 -
 launcher/game/tl/finnish/choose_theme.rpy          |   43 -
 launcher/game/tl/finnish/common.rpy                |  642 ++-----
 launcher/game/tl/finnish/developer.rpy             |  179 ++
 launcher/game/tl/finnish/distribute.rpy            |   38 -
 launcher/game/tl/finnish/distribute_gui.rpy        |   67 -
 launcher/game/tl/finnish/editor.rpy                |   55 -
 launcher/game/tl/finnish/error.rpy                 |  179 ++
 launcher/game/tl/finnish/front_page.rpy            |  111 --
 launcher/game/tl/finnish/gui.rpy                   |  411 +++++
 launcher/game/tl/finnish/interface.rpy             |   83 -
 launcher/game/tl/finnish/ios.rpy                   |   98 --
 launcher/game/tl/finnish/launcher.rpy              | 1187 +++++++++++++
 launcher/game/tl/finnish/mobilebuild.rpy           |    7 -
 launcher/game/tl/finnish/navigation.rpy            |   66 -
 launcher/game/tl/finnish/new_project.rpy           |   35 -
 launcher/game/tl/finnish/obsolete.rpy              |   27 +
 launcher/game/tl/finnish/options.rpy               |  195 +++
 launcher/game/tl/finnish/preferences.rpy           |   85 -
 launcher/game/tl/finnish/project.rpy               |   54 -
 launcher/game/tl/finnish/screens.rpy               |  643 +++++++
 launcher/game/tl/finnish/style.rpy                 |    3 +-
 launcher/game/tl/finnish/translations.rpy          |   59 -
 launcher/game/tl/finnish/updater.rpy               |   94 -
 launcher/game/tl/french/about.rpy                  |   10 -
 launcher/game/tl/french/add_file.rpy               |   22 -
 launcher/game/tl/french/android.rpy                |  101 --
 launcher/game/tl/french/choose_theme.rpy           |   41 -
 launcher/game/tl/french/common.rpy                 |  468 ++---
 launcher/game/tl/french/developer.rpy              |  179 ++
 launcher/game/tl/french/distribute.rpy             |   37 -
 launcher/game/tl/french/distribute_gui.rpy         |   41 -
 launcher/game/tl/french/editor.rpy                 |   57 -
 launcher/game/tl/french/error.rpy                  |  179 ++
 launcher/game/tl/french/front_page.rpy             |   81 -
 launcher/game/tl/french/gui.rpy                    |  411 +++++
 launcher/game/tl/french/interface.rpy              |   85 -
 launcher/game/tl/french/launcher.rpy               | 1187 +++++++++++++
 launcher/game/tl/french/navigation.rpy             |   73 -
 launcher/game/tl/french/new_project.rpy            |   33 -
 launcher/game/tl/french/obsolete.rpy               |   27 +
 launcher/game/tl/french/options.rpy                |  195 +++
 launcher/game/tl/french/preferences.rpy            |   69 -
 launcher/game/tl/french/project.rpy                |   25 -
 launcher/game/tl/french/screens.rpy                |  643 +++++++
 launcher/game/tl/french/script.rpym                |   17 +
 launcher/game/tl/french/style.rpy                  |    5 +-
 launcher/game/tl/french/translations.rpy           |   33 -
 launcher/game/tl/french/updater.rpy                |   85 -
 launcher/game/tl/german/about.rpy                  |   13 -
 launcher/game/tl/german/add_file.rpy               |   21 -
 launcher/game/tl/german/android.rpy                |  160 --
 launcher/game/tl/german/choose_theme.rpy           |   41 -
 launcher/game/tl/german/common.rpy                 |  597 +++----
 launcher/game/tl/german/developer.rpy              |  179 ++
 launcher/game/tl/german/distribute.rpy             |   42 -
 launcher/game/tl/german/distribute_gui.rpy         |   45 -
 launcher/game/tl/german/editor.rpy                 |   56 -
 launcher/game/tl/german/error.rpy                  |  179 ++
 launcher/game/tl/german/front_page.rpy             |   26 -
 launcher/game/tl/german/gui.rpy                    |  411 +++++
 launcher/game/tl/german/interface.rpy              |   85 -
 launcher/game/tl/german/launcher.rpy               | 1187 +++++++++++++
 launcher/game/tl/german/navigation.rpy             |   69 -
 launcher/game/tl/german/new_project.rpy            |   38 -
 launcher/game/tl/german/obsolete.rpy               |   27 +
 launcher/game/tl/german/options.rpy                |  195 +++
 launcher/game/tl/german/preferences.rpy            |   57 -
 launcher/game/tl/german/project.rpy                |   54 -
 launcher/game/tl/german/screens.rpy                |  643 +++++++
 launcher/game/tl/german/script.rpym                |   17 +
 launcher/game/tl/german/strings.rpy                |  195 ---
 launcher/game/tl/german/translations.rpy           |   33 -
 launcher/game/tl/german/updater.rpy                |   94 -
 launcher/game/tl/greek/about.rpy                   |   15 -
 launcher/game/tl/greek/add_file.rpy                |   23 -
 launcher/game/tl/greek/android.rpy                 |  171 --
 launcher/game/tl/greek/choose_directory.rpy        |    7 -
 launcher/game/tl/greek/choose_theme.rpy            |   43 -
 launcher/game/tl/greek/common.rpy                  |  639 ++-----
 launcher/game/tl/greek/developer.rpy               |  179 ++
 launcher/game/tl/greek/distribute.rpy              |   39 -
 launcher/game/tl/greek/distribute_gui.rpy          |   67 -
 launcher/game/tl/greek/editor.rpy                  |   55 -
 launcher/game/tl/greek/error.rpy                   |  179 ++
 launcher/game/tl/greek/front_page.rpy              |  111 --
 launcher/game/tl/greek/gui.rpy                     |  411 +++++
 launcher/game/tl/greek/interface.rpy               |   83 -
 launcher/game/tl/greek/ios.rpy                     |   99 --
 launcher/game/tl/greek/launcher.rpy                | 1187 +++++++++++++
 launcher/game/tl/greek/mobilebuild.rpy             |    7 -
 launcher/game/tl/greek/navigation.rpy              |   67 -
 launcher/game/tl/greek/new_project.rpy             |   35 -
 launcher/game/tl/greek/obsolete.rpy                |   27 +
 launcher/game/tl/greek/options.rpy                 |  195 +++
 launcher/game/tl/greek/preferences.rpy             |   83 -
 launcher/game/tl/greek/project.rpy                 |   51 -
 launcher/game/tl/greek/screens.rpy                 |  643 +++++++
 launcher/game/tl/greek/style.rpy                   |    3 +-
 launcher/game/tl/greek/translations.rpy            |   58 -
 launcher/game/tl/greek/updater.rpy                 |   95 -
 launcher/game/tl/indonesian/about.rpy              |   15 -
 launcher/game/tl/indonesian/add_file.rpy           |   23 -
 launcher/game/tl/indonesian/android.rpy            |  204 ---
 launcher/game/tl/indonesian/choose_directory.rpy   |    7 -
 launcher/game/tl/indonesian/choose_theme.rpy       |   44 -
 launcher/game/tl/indonesian/common.rpy             |  872 ++--------
 launcher/game/tl/indonesian/consolecommand.rpy     |    7 -
 launcher/game/tl/indonesian/developer.rpy          |  179 ++
 launcher/game/tl/indonesian/distribute.rpy         |   49 -
 launcher/game/tl/indonesian/distribute_gui.rpy     |   73 -
 launcher/game/tl/indonesian/editor.rpy             |   62 -
 launcher/game/tl/indonesian/error.rpy              |  179 ++
 launcher/game/tl/indonesian/front_page.rpy         |  137 --
 launcher/game/tl/indonesian/gui.rpy                |  611 ++-----
 launcher/game/tl/indonesian/gui7.rpy               |   39 -
 launcher/game/tl/indonesian/interface.rpy          |   90 -
 launcher/game/tl/indonesian/ios.rpy                |   99 --
 launcher/game/tl/indonesian/itch.rpy               |   27 -
 launcher/game/tl/indonesian/launcher.rpy           | 1200 +++++++++++++
 launcher/game/tl/indonesian/navigation.rpy         |   71 -
 launcher/game/tl/indonesian/new_project.rpy        |   76 -
 launcher/game/tl/indonesian/obsolete.rpy           |   27 +
 launcher/game/tl/indonesian/options.rpy            |  122 +-
 launcher/game/tl/indonesian/preferences.rpy        |   92 -
 launcher/game/tl/indonesian/project.rpy            |   65 -
 launcher/game/tl/indonesian/screens.rpy            |  680 ++++++++
 launcher/game/tl/indonesian/script.rpy             |   31 -
 launcher/game/tl/indonesian/script.rpym            |   18 +
 launcher/game/tl/indonesian/style.rpy              |   18 +-
 launcher/game/tl/indonesian/translations.rpy       |  121 --
 launcher/game/tl/indonesian/updater.rpy            |   98 --
 launcher/game/tl/italian/about.rpy                 |    9 -
 launcher/game/tl/italian/add_file.rpy              |   21 -
 launcher/game/tl/italian/android.rpy               |  162 --
 launcher/game/tl/italian/choose_theme.rpy          |   37 -
 launcher/game/tl/italian/common.rpy                |  621 +++----
 launcher/game/tl/italian/developer.rpy             |  179 ++
 launcher/game/tl/italian/distribute.rpy            |   37 -
 launcher/game/tl/italian/distribute_gui.rpy        |   45 -
 launcher/game/tl/italian/editor.rpy                |   65 -
 launcher/game/tl/italian/error.rpy                 |  179 ++
 launcher/game/tl/italian/front_page.rpy            |   93 -
 launcher/game/tl/italian/gui.rpy                   |  411 +++++
 launcher/game/tl/italian/interface.rpy             |   93 -
 launcher/game/tl/italian/launcher.rpy              | 1187 +++++++++++++
 launcher/game/tl/italian/navigation.rpy            |   65 -
 launcher/game/tl/italian/new_project.rpy           |   33 -
 launcher/game/tl/italian/obsolete.rpy              |   27 +
 launcher/game/tl/italian/options.rpy               |  195 +++
 launcher/game/tl/italian/preferences.rpy           |   61 -
 launcher/game/tl/italian/project.rpy               |   53 -
 launcher/game/tl/italian/screens.rpy               |  643 +++++++
 launcher/game/tl/italian/script.rpym               |   18 +
 launcher/game/tl/italian/translations.rpy          |   33 -
 launcher/game/tl/italian/updater.rpy               |   93 -
 launcher/game/tl/japanese/MTLc3m-LICENSE           |   17 -
 launcher/game/tl/japanese/about.rpy                |   15 -
 launcher/game/tl/japanese/add_file.rpy             |   23 -
 launcher/game/tl/japanese/android.rpy              |  175 --
 launcher/game/tl/japanese/choose_directory.rpy     |    7 -
 launcher/game/tl/japanese/choose_theme.rpy         |   43 -
 launcher/game/tl/japanese/common.rpy               |  692 +++-----
 launcher/game/tl/japanese/developer.rpy            |  179 ++
 launcher/game/tl/japanese/distribute.rpy           |   42 -
 launcher/game/tl/japanese/distribute_gui.rpy       |   63 -
 launcher/game/tl/japanese/editor.rpy               |   58 -
 launcher/game/tl/japanese/error.rpy                |  179 ++
 launcher/game/tl/japanese/front_page.rpy           |  111 --
 launcher/game/tl/japanese/gui.rpy                  |  436 +++++
 launcher/game/tl/japanese/interface.rpy            |   83 -
 launcher/game/tl/japanese/ios.rpy                  |   99 --
 launcher/game/tl/japanese/launcher.rpy             | 1199 +++++++++++++
 launcher/game/tl/japanese/navigation.rpy           |   67 -
 launcher/game/tl/japanese/new_project.rpy          |   35 -
 launcher/game/tl/japanese/obsolete.rpy             |   27 +
 launcher/game/tl/japanese/options.rpy              |  196 +++
 launcher/game/tl/japanese/preferences.rpy          |   83 -
 launcher/game/tl/japanese/project.rpy              |   59 -
 launcher/game/tl/japanese/screens.rpy              |  661 +++++++
 launcher/game/tl/japanese/script.rpym              |   62 +
 launcher/game/tl/japanese/style.rpy                |   36 +-
 launcher/game/tl/japanese/translations.rpy         |   35 -
 launcher/game/tl/japanese/updater.rpy              |   95 -
 launcher/game/tl/korean/about.rpy                  |   15 -
 launcher/game/tl/korean/add_file.rpy               |   23 -
 launcher/game/tl/korean/android.rpy                |  173 --
 launcher/game/tl/korean/choose_directory.rpy       |    7 -
 launcher/game/tl/korean/choose_theme.rpy           |   43 -
 launcher/game/tl/korean/common.rpy                 |  666 +++----
 launcher/game/tl/korean/developer.rpy              |  179 ++
 launcher/game/tl/korean/distribute.rpy             |   39 -
 launcher/game/tl/korean/distribute_gui.rpy         |   65 -
 launcher/game/tl/korean/editor.rpy                 |   55 -
 launcher/game/tl/korean/error.rpy                  |  179 ++
 launcher/game/tl/korean/front_page.rpy             |  117 --
 launcher/game/tl/korean/gui.rpy                    |  411 +++++
 launcher/game/tl/korean/interface.rpy              |   79 -
 launcher/game/tl/korean/ios.rpy                    |   97 --
 launcher/game/tl/korean/launcher.rpy               | 1187 +++++++++++++
 launcher/game/tl/korean/navigation.rpy             |   67 -
 launcher/game/tl/korean/new_project.rpy            |   35 -
 launcher/game/tl/korean/obsolete.rpy               |   27 +
 launcher/game/tl/korean/options.rpy                |  195 +++
 launcher/game/tl/korean/preferences.rpy            |   85 -
 launcher/game/tl/korean/project.rpy                |   54 -
 launcher/game/tl/korean/screens.rpy                |  643 +++++++
 launcher/game/tl/korean/script.rpym                |   17 +
 launcher/game/tl/korean/style.rpy                  |   28 +-
 launcher/game/tl/korean/translations.rpy           |   35 -
 launcher/game/tl/korean/updater.rpy                |   95 -
 launcher/game/tl/piglatin/common.rpy               |  334 ++++
 launcher/game/tl/piglatin/developer.rpy            |  178 ++
 launcher/game/tl/piglatin/error.rpy                |  178 ++
 launcher/game/tl/piglatin/gui.rpy                  |  429 +++++
 launcher/game/tl/piglatin/launcher.rpy             | 1201 +++++++++++++
 launcher/game/tl/piglatin/obsolete.rpy             |   26 +
 launcher/game/tl/piglatin/options.rpy              |  194 +++
 launcher/game/tl/piglatin/screens.rpy              |  673 ++++++++
 launcher/game/tl/piglatin/script.rpym              |   33 +
 launcher/game/tl/piglatin/style.rpy                |    5 +
 launcher/game/tl/russian/about.rpy                 |    1 -
 launcher/game/tl/russian/add_file.rpy              |   23 -
 launcher/game/tl/russian/android.rpy               |  103 --
 launcher/game/tl/russian/choose_theme.rpy          |   43 -
 launcher/game/tl/russian/common.rpy                |  462 ++---
 launcher/game/tl/russian/developer.rpy             |  179 ++
 launcher/game/tl/russian/distribute.rpy            |   35 -
 launcher/game/tl/russian/distribute_gui.rpy        |   51 -
 launcher/game/tl/russian/editor.rpy                |   55 -
 launcher/game/tl/russian/error.rpy                 |  179 ++
 launcher/game/tl/russian/front_page.rpy            |  110 --
 launcher/game/tl/russian/gui.rpy                   |  411 +++++
 launcher/game/tl/russian/interface.rpy             |   83 -
 launcher/game/tl/russian/launcher.rpy              | 1187 +++++++++++++
 launcher/game/tl/russian/navigation.rpy            |   67 -
 launcher/game/tl/russian/new_project.rpy           |   31 -
 launcher/game/tl/russian/obsolete.rpy              |   27 +
 launcher/game/tl/russian/options.rpy               |  195 +++
 launcher/game/tl/russian/preferences.rpy           |   78 -
 launcher/game/tl/russian/project.rpy               |   27 -
 launcher/game/tl/russian/screens.rpy               |  643 +++++++
 launcher/game/tl/russian/script.rpym               |   17 +
 launcher/game/tl/russian/translations.rpy          |   35 -
 launcher/game/tl/russian/updater.rpy               |   87 -
 launcher/game/tl/simplified_chinese/about.rpy      |   11 -
 launcher/game/tl/simplified_chinese/add_file.rpy   |   23 -
 launcher/game/tl/simplified_chinese/android.rpy    |  155 --
 .../tl/simplified_chinese/choose_directory.rpy     |    7 -
 .../game/tl/simplified_chinese/choose_theme.rpy    |   43 -
 launcher/game/tl/simplified_chinese/common.rpy     |  321 +++-
 launcher/game/tl/simplified_chinese/developer.rpy  |  179 ++
 launcher/game/tl/simplified_chinese/distribute.rpy |   39 -
 .../game/tl/simplified_chinese/distribute_gui.rpy  |   63 -
 launcher/game/tl/simplified_chinese/editor.rpy     |   57 -
 launcher/game/tl/simplified_chinese/error.rpy      |  179 ++
 launcher/game/tl/simplified_chinese/front_page.rpy |   91 -
 launcher/game/tl/simplified_chinese/gui.rpy        |  411 +++++
 launcher/game/tl/simplified_chinese/interface.rpy  |   79 -
 launcher/game/tl/simplified_chinese/ios.rpy        |   91 -
 launcher/game/tl/simplified_chinese/launcher.rpy   | 1187 +++++++++++++
 launcher/game/tl/simplified_chinese/navigation.rpy |   67 -
 .../game/tl/simplified_chinese/new_project.rpy     |   35 -
 launcher/game/tl/simplified_chinese/obsolete.rpy   |   27 +
 launcher/game/tl/simplified_chinese/options.rpy    |  195 +++
 .../game/tl/simplified_chinese/preferences.rpy     |   79 -
 launcher/game/tl/simplified_chinese/project.rpy    |   51 -
 launcher/game/tl/simplified_chinese/screens.rpy    |  643 +++++++
 launcher/game/tl/simplified_chinese/script.rpym    |   37 +
 launcher/game/tl/simplified_chinese/style.rpy      |   38 +-
 .../game/tl/simplified_chinese/translations.rpy    |   35 -
 launcher/game/tl/simplified_chinese/updater.rpy    |   95 -
 launcher/game/tl/spanish/about.rpy                 |    9 -
 launcher/game/tl/spanish/add_file.rpy              |   21 -
 launcher/game/tl/spanish/android.rpy               |  174 --
 launcher/game/tl/spanish/choose_directory.rpy      |    6 -
 launcher/game/tl/spanish/choose_theme.rpy          |   37 -
 launcher/game/tl/spanish/common.rpy                |  692 +++-----
 launcher/game/tl/spanish/developer.rpy             |  179 ++
 launcher/game/tl/spanish/distribute.rpy            |   37 -
 launcher/game/tl/spanish/distribute_gui.rpy        |   62 -
 launcher/game/tl/spanish/editor.rpy                |   64 -
 launcher/game/tl/spanish/error.rpy                 |  179 ++
 launcher/game/tl/spanish/front_page.rpy            |  114 --
 launcher/game/tl/spanish/gui.rpy                   |  434 +++++
 launcher/game/tl/spanish/interface.rpy             |   93 -
 launcher/game/tl/spanish/ios.rpy                   |   98 --
 launcher/game/tl/spanish/launcher.rpy              | 1198 +++++++++++++
 launcher/game/tl/spanish/navigation.rpy            |   65 -
 launcher/game/tl/spanish/new_project.rpy           |   34 -
 launcher/game/tl/spanish/obsolete.rpy              |   27 +
 launcher/game/tl/spanish/options.rpy               |  198 +++
 launcher/game/tl/spanish/preferences.rpy           |   82 -
 launcher/game/tl/spanish/project.rpy               |   58 -
 launcher/game/tl/spanish/screens.rpy               |  662 +++++++
 launcher/game/tl/spanish/script.rpym               |   30 +
 launcher/game/tl/spanish/translations.rpy          |   33 -
 launcher/game/tl/spanish/updater.rpy               |   94 -
 .../traditional_chinese/DroidSansFallback-LICENSE  |   20 -
 launcher/game/tl/traditional_chinese/about.rpy     |   15 -
 launcher/game/tl/traditional_chinese/add_file.rpy  |   23 -
 launcher/game/tl/traditional_chinese/android.rpy   |  155 --
 .../tl/traditional_chinese/choose_directory.rpy    |    7 -
 .../game/tl/traditional_chinese/choose_theme.rpy   |   43 -
 launcher/game/tl/traditional_chinese/common.rpy    |  598 +++----
 launcher/game/tl/traditional_chinese/developer.rpy |  179 ++
 .../game/tl/traditional_chinese/distribute.rpy     |   39 -
 .../game/tl/traditional_chinese/distribute_gui.rpy |   63 -
 launcher/game/tl/traditional_chinese/editor.rpy    |   55 -
 launcher/game/tl/traditional_chinese/error.rpy     |  179 ++
 .../game/tl/traditional_chinese/front_page.rpy     |  115 --
 launcher/game/tl/traditional_chinese/gui.rpy       |  411 +++++
 launcher/game/tl/traditional_chinese/interface.rpy |   83 -
 launcher/game/tl/traditional_chinese/ios.rpy       |   99 --
 launcher/game/tl/traditional_chinese/launcher.rpy  | 1187 +++++++++++++
 .../game/tl/traditional_chinese/navigation.rpy     |   67 -
 .../game/tl/traditional_chinese/new_project.rpy    |   35 -
 launcher/game/tl/traditional_chinese/obsolete.rpy  |   27 +
 launcher/game/tl/traditional_chinese/options.rpy   |  195 +++
 .../game/tl/traditional_chinese/preferences.rpy    |   83 -
 launcher/game/tl/traditional_chinese/project.rpy   |   51 -
 launcher/game/tl/traditional_chinese/screens.rpy   |  643 +++++++
 launcher/game/tl/traditional_chinese/script.rpym   |   17 +
 launcher/game/tl/traditional_chinese/style.rpy     |   34 +-
 .../game/tl/traditional_chinese/translations.rpy   |   35 -
 launcher/game/tl/traditional_chinese/updater.rpy   |   95 -
 launcher/game/tl/vietnamese/about.rpy              |   15 -
 launcher/game/tl/vietnamese/add_file.rpy           |   23 -
 launcher/game/tl/vietnamese/android.rpy            |  171 --
 launcher/game/tl/vietnamese/choose_directory.rpy   |    7 -
 launcher/game/tl/vietnamese/choose_theme.rpy       |   43 -
 launcher/game/tl/vietnamese/common.rpy             |  668 +++----
 launcher/game/tl/vietnamese/developer.rpy          |  179 ++
 launcher/game/tl/vietnamese/distribute.rpy         |   39 -
 launcher/game/tl/vietnamese/distribute_gui.rpy     |   67 -
 launcher/game/tl/vietnamese/editor.rpy             |   52 -
 launcher/game/tl/vietnamese/error.rpy              |  179 ++
 launcher/game/tl/vietnamese/front_page.rpy         |  111 --
 launcher/game/tl/vietnamese/gui.rpy                |  411 +++++
 launcher/game/tl/vietnamese/interface.rpy          |   83 -
 launcher/game/tl/vietnamese/ios.rpy                |   99 --
 launcher/game/tl/vietnamese/launcher.rpy           | 1187 +++++++++++++
 launcher/game/tl/vietnamese/mobilebuild.rpy        |    7 -
 launcher/game/tl/vietnamese/navigation.rpy         |   67 -
 launcher/game/tl/vietnamese/new_project.rpy        |   35 -
 launcher/game/tl/vietnamese/obsolete.rpy           |   27 +
 launcher/game/tl/vietnamese/options.rpy            |  195 +++
 launcher/game/tl/vietnamese/preferences.rpy        |   83 -
 launcher/game/tl/vietnamese/project.rpy            |   51 -
 launcher/game/tl/vietnamese/screens.rpy            |  643 +++++++
 launcher/game/tl/vietnamese/translations.rpy       |   59 -
 launcher/game/tl/vietnamese/updater.rpy            |   79 -
 launcher/game/translations.rpy                     |   30 +-
 module/ffmedia.c                                   |   29 +-
 module/gen/renpy.angle.gldraw.c                    |   18 +-
 module/gen/renpy.display.render.c                  |   19 +-
 module/gen/renpy.gl.gldraw.c                       |   18 +-
 module/gen/renpy.style.c                           | 1151 ++++++++-----
 module/gen/renpy.text.textsupport.c                | 1817 ++++++++++++--------
 module/generate_linebreak.py                       |   25 +-
 module/generate_styles.py                          |  272 +--
 module/renpysound_core.c                           |    8 +
 module/setup.py                                    |   16 +-
 module/setuplib.py                                 |   38 +-
 renpy.py                                           |   21 +-
 renpy/__init__.py                                  |   54 +-
 renpy/add_from.py                                  |    4 +-
 renpy/angle/__init__.py                            |    1 -
 renpy/angle/gldraw.pyx                             |    2 +-
 renpy/arguments.py                                 |   23 +-
 renpy/ast.py                                       |   95 +-
 renpy/atl.py                                       |  169 +-
 renpy/audio/__init__.py                            |    1 -
 renpy/audio/androidhw.py                           |    9 +-
 renpy/audio/audio.py                               |   64 +-
 renpy/audio/ioshw.py                               |    9 +-
 renpy/audio/music.py                               |   18 +-
 renpy/audio/sound.py                               |   28 +-
 renpy/bootstrap.py                                 |   47 +-
 renpy/character.py                                 |  128 +-
 renpy/color.py                                     |    4 +-
 renpy/common/000window.rpy                         |   22 +
 renpy/common/00action_file.rpy                     |   39 +-
 renpy/common/00action_other.rpy                    |   17 +
 renpy/common/00build.rpy                           |   50 +-
 renpy/common/00console.rpy                         |    4 +-
 renpy/common/00gamemenu.rpy                        |    2 +-
 renpy/common/00gamepad.rpy                         |    4 +-
 renpy/common/00gui.rpy                             |   20 +-
 renpy/common/00iap.rpy                             |   20 +-
 renpy/common/00images.rpy                          |    2 +-
 renpy/common/00inputvalues.rpy                     |   14 +
 renpy/common/00keymap.rpy                          |   17 +-
 renpy/common/00layout.rpy                          |   20 +-
 renpy/common/00library.rpy                         |    9 +-
 renpy/common/00musicroom.rpy                       |   32 +-
 renpy/common/00placeholder.rpy                     |    4 +
 renpy/common/00start.rpy                           |    9 +-
 renpy/common/00stylepreferences.rpy                |   18 +-
 renpy/common/00updater.rpy                         |   16 +-
 renpy/common/00voice.rpy                           |    8 +-
 renpy/common/_developer/developer.rpym             |   30 +-
 renpy/common/_errorhandling.rpym                   |   11 +
 renpy/config.py                                    |   37 +-
 renpy/curry.py                                     |    6 +-
 renpy/defaultstore.py                              |   17 +-
 renpy/display/__init__.py                          |    1 +
 renpy/display/anim.py                              |   16 +-
 renpy/display/behavior.py                          |  136 +-
 renpy/display/controller.py                        |   28 +-
 renpy/display/core.py                              |  176 +-
 renpy/display/dragdrop.py                          |   11 +-
 renpy/display/emulator.py                          |    3 +
 renpy/display/error.py                             |   14 +-
 renpy/display/focus.py                             |   20 +-
 renpy/display/gesture.py                           |    2 +-
 renpy/display/im.py                                |   56 +-
 renpy/display/image.py                             |   58 +-
 renpy/display/imagelike.py                         |   19 +-
 renpy/display/imagemap.py                          |    3 +-
 renpy/display/joystick.py                          |    4 +-
 renpy/display/layout.py                            |  141 +-
 renpy/display/minigame.py                          |    1 -
 renpy/display/module.py                            |    9 +-
 renpy/display/motion.py                            |   22 +-
 renpy/display/movetransition.py                    |   30 +-
 renpy/display/particle.py                          |   16 +-
 renpy/display/pgrender.py                          |   11 +-
 renpy/display/predict.py                           |    6 +-
 renpy/display/presplash.py                         |    3 +-
 renpy/display/render.pyx                           |    2 +-
 renpy/display/scale.py                             |   15 +-
 renpy/display/screen.py                            |   44 +-
 renpy/display/swdraw.py                            |   23 +-
 renpy/display/transform.py                         |   54 +-
 renpy/display/transition.py                        |   73 +-
 renpy/display/tts.py                               |    9 +-
 renpy/display/video.py                             |   19 +-
 renpy/display/viewport.py                          |   32 +-
 renpy/dump.py                                      |    9 +-
 renpy/easy.py                                      |    7 +-
 renpy/editor.py                                    |   16 +-
 renpy/error.py                                     |   44 +-
 renpy/execution.py                                 |   58 +-
 renpy/exports.py                                   |  105 +-
 renpy/game.py                                      |   30 +-
 renpy/gl/gldraw.pyx                                |    2 +-
 renpy/lint.py                                      |   82 +-
 renpy/loader.py                                    |   49 +-
 renpy/loadsave.py                                  |   30 +-
 renpy/log.py                                       |   12 +-
 renpy/main.py                                      |   62 +-
 renpy/memory.py                                    |   21 +-
 renpy/minstore.py                                  |   20 +-
 renpy/object.py                                    |    9 +-
 renpy/parser.py                                    |  205 +--
 renpy/persistent.py                                |   31 +-
 renpy/preferences.py                               |    5 +-
 renpy/pyanalysis.py                                |   27 +-
 renpy/python.py                                    |  226 ++-
 renpy/savelocation.py                              |   37 +-
 renpy/screenlang.py                                |  263 +--
 renpy/script.py                                    |  136 +-
 renpy/scriptedit.py                                |   22 +-
 renpy/sl2/slast.py                                 |   38 +-
 renpy/sl2/sldisplayables.py                        |   14 +-
 renpy/sl2/slparser.py                              |   22 +-
 renpy/sl2/slproperties.py                          |  248 +--
 renpy/statements.py                                |    4 +-
 renpy/style.pyx                                    |   22 +-
 renpy/styledata/__init__.py                        |   27 +-
 renpy/styledata/styleutil.py                       |    6 +-
 renpy/substitutions.py                             |   17 +-
 renpy/test/testast.py                              |   11 +-
 renpy/test/testexecution.py                        |    6 +-
 renpy/test/testfocus.py                            |   10 +-
 renpy/test/testkey.py                              |    2 +
 renpy/test/testmouse.py                            |    7 +
 renpy/test/testparser.py                           |    3 +-
 renpy/text/extras.py                               |   47 +-
 renpy/text/font.py                                 |   68 +-
 renpy/text/text.py                                 |   57 +-
 renpy/text/textsupport.pyx                         |   27 +
 renpy/translation/__init__.py                      |   61 +-
 renpy/translation/dialogue.py                      |   10 +-
 renpy/translation/extract.py                       |   42 +-
 renpy/translation/generation.py                    |  373 ++--
 renpy/translation/merge.py                         |   11 +-
 renpy/translation/scanstrings.py                   |  223 +++
 renpy/ui.py                                        |  163 +-
 renpy/vc_version.py                                |    2 +-
 renpy/warp.py                                      |    3 +-
 templates/japanese/project.json                    |    2 +-
 templates/korean/project.json                      |    2 +-
 templates/simplified_chinese/project.json          |    2 +-
 templates/traditional_chinese/project.json         |    2 +-
 tutorial/dialogue.tab                              |  617 +++++++
 tutorial/dialogue.txt                              |  508 ++++++
 tutorial/game/demo_transitions.rpy                 |    2 +-
 tutorial/game/keywords.py                          |    2 +-
 tutorial/game/options.rpy                          |    6 +
 tutorial/game/screens.rpy                          |   12 +-
 tutorial/game/script.rpy                           |    2 +-
 tutorial/game/testcases.rpy                        |    2 +-
 tutorial/game/tl/None/common.rpym                  |  743 ++++++++
 tutorial/game/tl/piglatin/common.rpy               |  555 ++++++
 tutorial/game/tl/piglatin/demo_character.rpy       |  133 ++
 tutorial/game/tl/piglatin/demo_dynamic.rpy         |   19 +
 tutorial/game/tl/piglatin/demo_imageops.rpy        |  181 ++
 tutorial/game/tl/piglatin/demo_layers.rpy          |   67 +
 tutorial/game/tl/piglatin/demo_minigame.rpy        |  109 ++
 tutorial/game/tl/piglatin/demo_nvlmode.rpy         |  125 ++
 tutorial/game/tl/piglatin/demo_persistent.rpy      |   37 +
 tutorial/game/tl/piglatin/demo_text.rpy            |  187 ++
 tutorial/game/tl/piglatin/demo_transform.rpy       |   61 +
 tutorial/game/tl/piglatin/demo_transitions.rpy     |  575 +++++++
 tutorial/game/tl/piglatin/demo_ui.rpy              |  245 +++
 tutorial/game/tl/piglatin/screens.rpy              |  175 ++
 tutorial/game/tl/piglatin/script.rpy               |  151 ++
 tutorial/game/tl/piglatin/tutorial_atl.rpy         |  561 ++++++
 tutorial/game/tl/piglatin/tutorial_playing.rpy     |  169 ++
 tutorial/game/tl/piglatin/tutorial_quickstart.rpy  |  663 +++++++
 tutorial/game/tl/piglatin/tutorial_sprite.rpy      |   49 +
 tutorial/game/tl/piglatin/tutorial_video.rpy       |   43 +
 tutorial/game/tutorial_video.rpy                   |    2 +-
 674 files changed, 59122 insertions(+), 25590 deletions(-)

diff --git a/doc/achievement.html b/doc/achievement.html
index 68ed60c..45a7c8b 100644
--- a/doc/achievement.html
+++ b/doc/achievement.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/android-packaging.html b/doc/android-packaging.html
index d84d8a3..c46550e 100644
--- a/doc/android-packaging.html
+++ b/doc/android-packaging.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -49,7 +49,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -145,6 +145,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/android.html b/doc/android.html
index a2aef48..72d145e 100644
--- a/doc/android.html
+++ b/doc/android.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/atl.html b/doc/atl.html
index 114da78..37278f7 100644
--- a/doc/atl.html
+++ b/doc/atl.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/audio.html b/doc/audio.html
index 3335d39..925f826 100644
--- a/doc/audio.html
+++ b/doc/audio.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -310,7 +311,7 @@ begins playing. (This defaults to 0.0 seconds.)</dd>
 <dd>Specifies the position in the file at which the file ends playing.
 (This defaults to the full duration of the file.)</dd>
 <dt><code class="docutils literal"><span class="pre">loop</span></code></dt>
-<dd>Specifies the position in the file at which the second and laterr
+<dd>Specifies the position in the file at which the second and later
 play-throughs begin playing. (This defaults to the start time
 given by <code class="docutils literal"><span class="pre">from</span></code> if specified, or to the start of the file.)</dd>
 </dl>
diff --git a/doc/build.html b/doc/build.html
index 46b3edf..bf52c86 100644
--- a/doc/build.html
+++ b/doc/build.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -420,7 +421,7 @@ exist until after you're gone.</p>
 <h2>Build Functions<a class="headerlink" href="#build-functions" title="Permalink to this headline"> link</a></h2>
 <dl class="function">
 <dt id="build.archive">
-<code class="descclassname">build.</code><code class="descname">archive</code><span class="sig-paren">(</span><em>name</em>, <em>file_list='all'</em><span class="sig-paren">)</span><a class="headerlink" href="#build.archive" title="Permalink to this definition"> link</a></dt>
+<code class="descclassname">build.</code><code class="descname">archive</code><span class="sig-paren">(</span><em>name</em>, <em>file_list=u'all'</em><span class="sig-paren">)</span><a class="headerlink" href="#build.archive" title="Permalink to this definition"> link</a></dt>
 <dd><p>Declares the existence of an archive. If one or more files are
 classified with <cite>name</cite>, <cite>name</cite>.rpa is build as an archive. The
 archive is included in the named file lists.</p>
@@ -467,10 +468,18 @@ list of:</p>
 <dl class="docutils">
 <dt>zip</dt>
 <dd>A zip file.</dd>
-<dt>app-zip</dt>
-<dd>A zip file containing a macintosh application.</dd>
 <dt>tar.bz2</dt>
 <dd>A tar.bz2 file.</dd>
+<dt>directory</dt>
+<dd>A directory containing the files.</dd>
+<dt>dmg</dt>
+<dd>A Macintosh DMG containing the files.</dd>
+<dt>app-zip</dt>
+<dd>A zip file containing a macintosh application.</dd>
+<dt>app-directory</dt>
+<dd>A directory containing the mac app.</dd>
+<dt>app-dmg</dt>
+<dd>A macintosh drive image containing a dmg. (Mac only.)</dd>
 </dl>
 <p class="last">The empty string will not build any package formats (this
 makes dlc possible).</p>
diff --git a/doc/cds.html b/doc/cds.html
index 4f94a6f..b070d89 100644
--- a/doc/cds.html
+++ b/doc/cds.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/changelog.html b/doc/changelog.html
index b4b317d..0afd977 100644
--- a/doc/changelog.html
+++ b/doc/changelog.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -31,7 +31,7 @@
     <script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
     <link rel="top" title="Ren'Py Documentation" href="index.html" />
     <link rel="next" title="Incompatible Changes" href="incompatible.html" />
-    <link rel="prev" title="Skins" href="skins.html" />
+    <link rel="prev" title="Translating Ren'Py" href="translating_renpy.html" />
 <meta charset='utf-8'>
 <meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
 <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul class="current">
 <li class="toctree-l1 current"><a class="current reference internal" href="#">Full Changelog</a></li>
@@ -188,6 +189,13 @@
       <div class="col-md-3">
         <div id="sidebar" class="bs-sidenav" role="complementary"><ul>
 <li><a class="reference internal" href="#">Full Changelog</a><ul>
+<li><a class="reference internal" href="#ren-py-6-99-12">Ren'Py 6.99.12</a><ul>
+<li><a class="reference internal" href="#macintosh-support">Macintosh Support</a></li>
+<li><a class="reference internal" href="#translation-changes">Translation Changes</a></li>
+<li><a class="reference internal" href="#python-changes">Python Changes</a></li>
+<li><a class="reference internal" href="#other-changes-and-fixes">Other Changes and Fixes</a></li>
+</ul>
+</li>
 <li><a class="reference internal" href="#ren-py-6-99-11">Ren'Py 6.99.11</a><ul>
 <li><a class="reference internal" href="#new-in-game-gui">New In-Game GUI</a></li>
 <li><a class="reference internal" href="#improved-platform-support">Improved Platform Support</a></li>
@@ -208,7 +216,7 @@
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-9">Ren'Py 6.99.9</a><ul>
 <li><a class="reference internal" href="#bug-fixes">Bug Fixes</a></li>
-<li><a class="reference internal" href="#id5">Other</a></li>
+<li><a class="reference internal" href="#id1">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-8">Ren'Py 6.99.8</a><ul>
@@ -216,14 +224,14 @@
 <li><a class="reference internal" href="#easing-functions">Easing Functions</a></li>
 <li><a class="reference internal" href="#side-images">Side Images</a></li>
 <li><a class="reference internal" href="#pushmove-transitions">PushMove Transitions</a></li>
-<li><a class="reference internal" href="#id6">Other</a></li>
+<li><a class="reference internal" href="#id2">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-7">Ren'Py 6.99.7</a><ul>
 <li><a class="reference internal" href="#dynamic-images">Dynamic Images</a></li>
 <li><a class="reference internal" href="#define-improvements">Define Improvements</a></li>
 <li><a class="reference internal" href="#android-ios">Android/iOS</a></li>
-<li><a class="reference internal" href="#id7">Other</a></li>
+<li><a class="reference internal" href="#id3">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-6">Ren'Py 6.99.6</a><ul>
@@ -236,11 +244,11 @@
 <li><a class="reference internal" href="#ren-py-6-99-5">Ren'Py 6.99.5</a><ul>
 <li><a class="reference internal" href="#startup">Startup</a></li>
 <li><a class="reference internal" href="#ios">iOS</a></li>
-<li><a class="reference internal" href="#id8">Other Improvements</a></li>
+<li><a class="reference internal" href="#id4">Other Improvements</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-4">Ren'Py 6.99.4</a><ul>
-<li><a class="reference internal" href="#id9">Fixes</a></li>
+<li><a class="reference internal" href="#id5">Fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-99-3">Ren'Py 6.99.3</a></li>
@@ -255,11 +263,11 @@
 <li><a class="reference internal" href="#languages-and-translations">Languages and Translations</a></li>
 <li><a class="reference internal" href="#clipboard-voicing">Clipboard Voicing</a></li>
 <li><a class="reference internal" href="#custom-text-tags">Custom Text Tags</a></li>
-<li><a class="reference internal" href="#id10">Other Improvements</a></li>
+<li><a class="reference internal" href="#id6">Other Improvements</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-18-3">Ren'Py 6.18.3</a><ul>
-<li><a class="reference internal" href="#id11">Bug Fixes</a></li>
+<li><a class="reference internal" href="#id7">Bug Fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-18-2">Ren'Py 6.18.2</a></li>
@@ -272,43 +280,43 @@
 <li><a class="reference internal" href="#pixel-art">Pixel Art</a></li>
 <li><a class="reference internal" href="#voice-improvements">Voice Improvements</a></li>
 <li><a class="reference internal" href="#os-x-bug-workaround">OS X Bug Workaround</a></li>
-<li><a class="reference internal" href="#id12">Other</a></li>
-<li><a class="reference internal" href="#id13">Translations</a></li>
+<li><a class="reference internal" href="#id8">Other</a></li>
+<li><a class="reference internal" href="#id9">Translations</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-17-7">Ren'Py 6.17.7</a></li>
 <li><a class="reference internal" href="#ren-py-6-17-6">Ren'Py 6.17.6</a></li>
 <li><a class="reference internal" href="#ren-py-6-17-5">Ren'Py 6.17.5</a><ul>
-<li><a class="reference internal" href="#id14">Translations</a></li>
+<li><a class="reference internal" href="#id10">Translations</a></li>
 <li><a class="reference internal" href="#changes">Changes</a></li>
-<li><a class="reference internal" href="#id15">Fixes</a></li>
+<li><a class="reference internal" href="#id11">Fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-17-4">Ren'Py 6.17.4</a><ul>
 <li><a class="reference internal" href="#reloading">Reloading</a></li>
 <li><a class="reference internal" href="#android">Android</a></li>
-<li><a class="reference internal" href="#id16">Other</a></li>
+<li><a class="reference internal" href="#id12">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-17">Ren'Py 6.17</a><ul>
 <li><a class="reference internal" href="#styles">Styles</a></li>
 <li><a class="reference internal" href="#syntax-changes">Syntax Changes</a></li>
-<li><a class="reference internal" href="#id17">Translations</a></li>
-<li><a class="reference internal" href="#id18">Android</a></li>
+<li><a class="reference internal" href="#id13">Translations</a></li>
+<li><a class="reference internal" href="#id14">Android</a></li>
 <li><a class="reference internal" href="#new-and-changed-preferences">New and Changed Preferences</a></li>
-<li><a class="reference internal" href="#id19">Other</a></li>
+<li><a class="reference internal" href="#id15">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-16-2">Ren'Py 6.16.2</a></li>
 <li><a class="reference internal" href="#ren-py-6-16">Ren'Py 6.16</a><ul>
-<li><a class="reference internal" href="#id20">Android</a></li>
+<li><a class="reference internal" href="#id16">Android</a></li>
 <li><a class="reference internal" href="#save-load-and-persistent-improvements">Save, Load, and Persistent Improvements</a></li>
 <li><a class="reference internal" href="#voice">Voice</a></li>
 <li><a class="reference internal" href="#image-gallery-and-music-room">Image Gallery and Music Room</a></li>
 <li><a class="reference internal" href="#text-rendering">Text Rendering</a></li>
 <li><a class="reference internal" href="#japanese-language">Japanese Language</a></li>
 <li><a class="reference internal" href="#documentation">Documentation</a></li>
-<li><a class="reference internal" href="#id21">Other</a></li>
+<li><a class="reference internal" href="#id17">Other</a></li>
 <li><a class="reference internal" href="#bugfixes">Bugfixes</a></li>
 </ul>
 </li>
@@ -323,12 +331,12 @@
 <li><a class="reference internal" href="#console">Console</a></li>
 <li><a class="reference internal" href="#screen-parameters">Screen Parameters</a></li>
 <li><a class="reference internal" href="#replay-gallery">Replay Gallery</a></li>
-<li><a class="reference internal" href="#id22">Voice Improvements</a></li>
+<li><a class="reference internal" href="#id18">Voice Improvements</a></li>
 <li><a class="reference internal" href="#launcher-improvements">Launcher Improvements</a></li>
 <li><a class="reference internal" href="#macintosh-changes">Macintosh Changes</a></li>
 <li><a class="reference internal" href="#packaging-improvements">Packaging Improvements</a></li>
-<li><a class="reference internal" href="#id23">Other Changes</a></li>
-<li><a class="reference internal" href="#id24">Bugfixes</a></li>
+<li><a class="reference internal" href="#id19">Other Changes</a></li>
+<li><a class="reference internal" href="#id20">Bugfixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-14">Ren'Py 6.14</a><ul>
@@ -343,7 +351,7 @@
 <li><a class="reference internal" href="#file-actions-and-functions">File Actions and Functions</a></li>
 <li><a class="reference internal" href="#multiple-store-support">Multiple Store Support</a></li>
 <li><a class="reference internal" href="#platform-support-and-library-updates">Platform Support and Library Updates</a></li>
-<li><a class="reference internal" href="#id25">Other Changes</a></li>
+<li><a class="reference internal" href="#id21">Other Changes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-13-9">Ren'Py 6.13.9</a></li>
@@ -351,42 +359,42 @@
 <li><a class="reference internal" href="#ren-py-6-13">Ren'Py 6.13</a><ul>
 <li><a class="reference internal" href="#text-rewrite">Text Rewrite</a></li>
 <li><a class="reference internal" href="#directx-support">DirectX Support</a></li>
-<li><a class="reference internal" href="#id26">Other Changes</a></li>
+<li><a class="reference internal" href="#id22">Other Changes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-12-2">Ren'Py 6.12.2</a></li>
 <li><a class="reference internal" href="#ren-py-6-12-1">Ren'Py 6.12.1</a><ul>
 <li><a class="reference internal" href="#image-attributes">Image Attributes</a></li>
 <li><a class="reference internal" href="#error-handling">Error Handling</a></li>
-<li><a class="reference internal" href="#id27">Other</a></li>
+<li><a class="reference internal" href="#id23">Other</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-12-0">Ren'Py 6.12.0</a><ul>
-<li><a class="reference internal" href="#id28">Android Support</a></li>
+<li><a class="reference internal" href="#id24">Android Support</a></li>
 <li><a class="reference internal" href="#new-widgets-and-displayables">New Widgets and Displayables</a></li>
-<li><a class="reference internal" href="#id29">Image Prediction</a></li>
+<li><a class="reference internal" href="#id25">Image Prediction</a></li>
 <li><a class="reference internal" href="#screens">Screens</a></li>
-<li><a class="reference internal" href="#id30">Other Improvements</a></li>
-<li><a class="reference internal" href="#id31">Bug Fixes</a></li>
+<li><a class="reference internal" href="#id26">Other Improvements</a></li>
+<li><a class="reference internal" href="#id27">Bug Fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-11-2">Ren'Py 6.11.2</a><ul>
 <li><a class="reference internal" href="#new-features">New Features</a></li>
 <li><a class="reference internal" href="#software-update">Software Update</a></li>
 <li><a class="reference internal" href="#behavior-changes">Behavior Changes</a></li>
-<li><a class="reference internal" href="#id32">Bug fixes</a></li>
+<li><a class="reference internal" href="#id28">Bug fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-11-1">Ren'Py 6.11.1</a><ul>
-<li><a class="reference internal" href="#id33">New Features</a></li>
-<li><a class="reference internal" href="#id34">Fixes</a></li>
+<li><a class="reference internal" href="#id29">New Features</a></li>
+<li><a class="reference internal" href="#id30">Fixes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#ren-py-6-11-0">Ren'Py 6.11.0</a><ul>
 <li><a class="reference internal" href="#opengl-support">OpenGL Support</a></li>
 <li><a class="reference internal" href="#screens-and-screen-language">Screens and Screen Language</a></li>
-<li><a class="reference internal" href="#id35">Transform Changes</a></li>
-<li><a class="reference internal" href="#id36">Other Changes</a></li>
+<li><a class="reference internal" href="#id31">Transform Changes</a></li>
+<li><a class="reference internal" href="#id32">Other Changes</a></li>
 </ul>
 </li>
 <li><a class="reference internal" href="#older-changelogs">Older Changelogs</a></li>
@@ -400,6 +408,103 @@
       
   <div class="section" id="full-changelog">
 <h1>Full Changelog<a class="headerlink" href="#full-changelog" title="Permalink to this headline"> link</a></h1>
+<div class="section" id="ren-py-6-99-12">
+<span id="renpy-6-99-12"></span><h2>Ren'Py 6.99.12<a class="headerlink" href="#ren-py-6-99-12" title="Permalink to this headline"> link</a></h2>
+<div class="section" id="macintosh-support">
+<h3>Macintosh Support<a class="headerlink" href="#macintosh-support" title="Permalink to this headline"> link</a></h3>
+<p>This release includes a number of changes to support macOS Sierra. These
+include:</p>
+<ul class="simple">
+<li>The Macintosh application produced by Ren'Py is now read-only by default.
+Save files will be placed in a system-global directory, while screenshots
+will be written to the Desktop.</li>
+<li>The organization of the Mac application has been changed to allow the
+application to be code-signed.</li>
+<li>When run on a Macintosh with Xcode installed and the <code class="xref std std-var docutils literal"><span class="pre">build.mac_identity</span></code>
+variable set properly, Ren'Py will use the codesign tool to sign the package
+before archiving it.</li>
+<li>When run on a Macintosh, Ren'Py will create a .dmg file containing the
+application. When Xcode is installed and <code class="xref std std-var docutils literal"><span class="pre">build.mac_identity</span></code> is set,
+the package will be signed.</li>
+</ul>
+<p>The result of this is that, when a creator has a Macintosh computer and a
+(free) Developer ID Application certificate, it is possible to create
+distribute downloadable Ren'Py games that satisfy Gatekeeper and Gatekeeper
+Path Randomization.</p>
+<p>Since it is no longer possible to make a single distribution that runs on all
+desktop platforms, the all (Windows, Mac, and Linux) package type has been
+removed. It's been replace with a pc package type that supports Windows and
+Linux, and the existing mac type that supports macOS. (There is a new steam
+package type to help with app store bundles, but that's not recommended for
+distribution to end users, since it won't work with macOS Sierra.)</p>
+<p>The launcher has been modified so it can launch games created using older
+versions of Ren'Py, even under Sierra. This can be done by placing the game
+inside the Ren'Py directory, starting Ren'Py, choosing the game in the
+launcher, and choosing "Launch Project".</p>
+</div>
+<div class="section" id="translation-changes">
+<h3>Translation Changes<a class="headerlink" href="#translation-changes" title="Permalink to this headline"> link</a></h3>
+<p>Support generating projects in non-English languages has been
+improved. When a new project is created, it includes translations of the
+interface strings into the project's language, allowing the translation
+of text presented to the player by Ren'Py.</p>
+<p>There is now a single place for translating Ren'Py - translating
+the launcher also now translates the comments of a generated game. The process
+of translating Ren'Py (the launcher and the GUI) is now documented
+on the <a class="reference internal" href="translating_renpy.html#translating-renpy"><span class="std std-ref">Translating Ren'py</span></a> page. This page also
+suggests a logical order in which strings should be translated.</p>
+<p>Functions have been added for selecting an alternate font, changing defines
+(such a text size), and copying files into a generated project, based on the
+translation.</p>
+<p>Translate python blocks are now executed before regular style statements
+(translate style statements are executed after both). This change was
+intended for and documented 6.99.11, but the implementation was flawed,
+so a corrected implementation is used now.</p>
+</div>
+<div class="section" id="python-changes">
+<h3>Python Changes<a class="headerlink" href="#python-changes" title="Permalink to this headline"> link</a></h3>
+<p>Ren'Py will now compile Python code as if:</p>
+<div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">absolute_imports</span><span class="p">,</span> <span class="n">print_function</span><span class="p">,</span> <span class="n">unicode_literals</span>
+</pre></div>
+</div>
+<p>was true. If compilation fails, it will then re-compile the code without these
+settings. This is intended to allow new code to be written that will be
+compatible with a future Python 3-based Ren'Py.</p>
+<p>This should have minimal impact to existing code. The one case where it could
+be a problem is if a character string is used to encode binary data, in
+which case a binary string (b"string") should be explictly used.</p>
+</div>
+<div class="section" id="other-changes-and-fixes">
+<h3>Other Changes and Fixes<a class="headerlink" href="#other-changes-and-fixes" title="Permalink to this headline"> link</a></h3>
+<p>Dynamic images are now copied before a transition occurs. This makes it
+possible to use dynamic variables and the with statement together, to
+transition from one value of the variable to another.</p>
+<p>Ren'Py now supports the WEBP image format.</p>
+<p>This version of Ren'Py includes fixes to support the interactive director
+tool.</p>
+<p>The iOS app store is queried for the price of available in-app purchases
+when the game starts. This allows the price of such purchases to be
+presented without the game blocking.</p>
+<p>The dialog window that is presented when accessing the iOS app store can
+now be translated.</p>
+<p>It is now possible to pass positional arguments to a game menu screen via
+ShowMenu.</p>
+<p>An issue introduced in 6.99.11 that could cause ATL Transforms to repeat has
+been fixed.</p>
+<p>A regression with first_fit that caused it to not work has been rectified.</p>
+<p>An issue that cause ongoing sound playback to skip while a new sound sample
+was loaded has been eliminated.</p>
+<p>Support for the itch.io butler tool on Windows has been fixed.</p>
+<p>Hiding the interface no longer stops voice playback.</p>
+<p>The new <a class="reference internal" href="screen_actions.html#DisableAllInputValues" title="DisableAllInputValues"><code class="xref py py-func docutils literal"><span class="pre">DisableAllInputValues()</span></code></a> action can disable input values all at
+once.</p>
+<p>The mousewheel property of viewports and vpgrids supports a new value,
+"change". When this value is given, the viewport only consumes mouse events
+when the event would change the viewport. The motivating use of this is a
+history window that dismisses when it reaches the bottom.</p>
+<p>Namespaces may now contain dots in their names.</p>
+</div>
+</div>
 <div class="section" id="ren-py-6-99-11">
 <span id="renpy-6-99-11"></span><h2>Ren'Py 6.99.11<a class="headerlink" href="#ren-py-6-99-11" title="Permalink to this headline"> link</a></h2>
 <div class="section" id="new-in-game-gui">
@@ -461,7 +566,7 @@ the Android Runtime for Chrome tool.</p>
 </div>
 <div class="section" id="style-prefix-support">
 <h3>Style Prefix Support<a class="headerlink" href="#style-prefix-support" title="Permalink to this headline"> link</a></h3>
-<p>Ren'Py now supports the use of a <a href="#id37"><span class="problematic" id="id38">prefix_</span></a> substitution with style properties.
+<p>Ren'Py now supports the use of a <a href="#id33"><span class="problematic" id="id34">prefix_</span></a> substitution with style properties.
 Where previously, one was required to write:</p>
 <div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="k">style</span> <span class="k">button</span><span class="p">:</span>
     <span class="na">insensitive_background</span> <span class="s2">"insensitive_button.png"</span>
@@ -473,7 +578,7 @@ Where previously, one was required to write:</p>
 </div>
 <p>one can now write:</p>
 <div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="k">style</span> <span class="k">button</span><span class="p">:</span>
-    <span class="na">background</span> <span class="s2">"[prefix_]button.png"</span>
+    <span class="na">background</span> <span class="s2">"[prefix\_]button.png"</span>
 </pre></div>
 </div>
 <p>This searches through prefixes in a manner similar to the way styles do.
@@ -495,7 +600,7 @@ axis to fit all child displayables.</p>
 <p>Buttons and Windows now fully respect the <a class="reference internal" href="style_properties.html#style-property-xmaximum"><code class="xref std std-propref docutils literal"><span class="pre">xmaximum</span></code></a> and
 <a class="reference internal" href="style_properties.html#style-property-ymaximum"><code class="xref std std-propref docutils literal"><span class="pre">ymaximum</span></code></a> style properties.</p>
 <p>There is now a <a class="reference internal" href="style_properties.html#style-property-offset"><code class="xref std std-propref docutils literal"><span class="pre">offset</span></code></a> style property, which sets the
-<a class="reference internal" href="style_properties.html#style-property-xoffset"><code class="xref std std-propref docutils literal"><span class="pre">xoffset</span></code></a> and <a href="#id1"><span class="problematic" id="id2">:propfref:`yoffset`</span></a> properties to the first and
+<a class="reference internal" href="style_properties.html#style-property-xoffset"><code class="xref std std-propref docutils literal"><span class="pre">xoffset</span></code></a> and <a class="reference internal" href="style_properties.html#style-property-yoffset"><code class="xref std std-propref docutils literal"><span class="pre">yoffset</span></code></a> properties to the first and
 second components of a tuple.</p>
 </div>
 <div class="section" id="translate-and-style-statement-order-changes">
@@ -521,7 +626,7 @@ is the current language. (If not None.)</li>
 </ol>
 <p>Ren'Py can be made to return to the old behavior (in which only <code class="docutils literal"><span class="pre">translate</span></code>
 <cite>language</cite> <code class="docutils literal"><span class="pre">style</span></code>, <code class="docutils literal"><span class="pre">translate</span></code> <cite>language</cite> <code class="docutils literal"><span class="pre">python</span></code>, and callbacks
-are executed) by setti</p>
+are executed) by setting <a class="reference internal" href="config.html#var-config.new_translate_order"><code class="xref std std-var docutils literal"><span class="pre">config.new_translate_order</span></code></a> to False.</p>
 </div>
 <div class="section" id="local-labels">
 <h3>Local Labels<a class="headerlink" href="#local-labels" title="Permalink to this headline"> link</a></h3>
@@ -582,7 +687,7 @@ Ren'Py keywords. For example, "define menu = nvl_menu" now works.</p>
 <p>A <a class="reference internal" href="displayables.html#Frame" title="Frame"><code class="xref py py-func docutils literal"><span class="pre">Frame()</span></code></a> can now be given a <a class="reference internal" href="displayables.html#Borders" title="Borders"><code class="xref py py-func docutils literal"><span class="pre">Borders()</span></code></a> object, that
 encapsulates the borders of a Frame into a single object. Borders
 objects also have a padding field that can be passed into the new
-<a href="#id3"><span class="problematic" id="id4">:properf:`padding`</span></a> style property.</p>
+<a class="reference internal" href="style_properties.html#style-property-padding"><code class="xref std std-propref docutils literal"><span class="pre">padding</span></code></a> style property.</p>
 <p>Buttons, textbuttons, imagebuttons, and hotspots now take
 <cite>selected</cite> and <cite>sensitive</cite> properties that directly control if the
 button is selected or sensitive.</p>
@@ -611,6 +716,12 @@ to run once a load has been completed.</p>
 platform-specific choice of text-to-speech voice to use.</p>
 <p><a class="reference internal" href="config.html#var-config.quit_action"><code class="xref std std-var docutils literal"><span class="pre">config.quit_action</span></code></a> now defaults to <code class="docutils literal"><span class="pre">Quit()</span></code>, which will display
 the quit prompt over the in-game interface.</p>
+<p>The <a class="reference internal" href="config.html#var-config.afm_voice_delay"><code class="xref std std-var docutils literal"><span class="pre">config.afm_voice_delay</span></code></a> has been added, and allows a pause to
+occur after the voice finishes in auto-forward mode, before advancing the
+text.</p>
+<p>The new "video sprites" <a class="reference internal" href="screen_actions.html#Preference" title="Preference"><code class="xref py py-func docutils literal"><span class="pre">Preference()</span></code></a> makes it possible to disable
+video sprites (and use fallback images) on hardware too slow to support
+them.</p>
 <p>The progress indicator now can be accessed using the F2 key, in addition to
 the shift-alt-P binding. The latter binding has been fixed to work reliably
 on PC platforms.</p>
@@ -723,8 +834,8 @@ the wrong side on the Microsoft Windows platform when system-wide DPI
 scaling is enabled.</p>
 <p>The Drag.snap animation has been fixed.</p>
 </div>
-<div class="section" id="id5">
-<h3>Other<a class="headerlink" href="#id5" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id1">
+<h3>Other<a class="headerlink" href="#id1" title="Permalink to this headline"> link</a></h3>
 <p>The new <a class="reference internal" href="config.html#var-config.speaking_attribute"><code class="xref std std-var docutils literal"><span class="pre">config.speaking_attribute</span></code></a> variable can be used to
 automatically apply an attribute to an image when a character
 starts speaking, and to remove that attribute when the</p>
@@ -802,8 +913,8 @@ in the case where the character changes and the case where it stays the same.</p
 <p>A new type of transition - <a class="reference internal" href="transitions.html#PushMove" title="PushMove"><code class="xref py py-func docutils literal"><span class="pre">PushMove()</span></code></a> - has been added to Ren'Py, along
 with the <a class="reference internal" href="transitions.html#var-pushright"><code class="xref std std-var docutils literal"><span class="pre">pushright</span></code></a> (or pushleft, pushtop, pushbottom)</p>
 </div>
-<div class="section" id="id6">
-<h3>Other<a class="headerlink" href="#id6" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id2">
+<h3>Other<a class="headerlink" href="#id2" title="Permalink to this headline"> link</a></h3>
 <p>Fixed a major bug where Ren'Py would put an extra space at the end of each
 text block. This could change the layout of text (and hence other portions of
 the interface.) The fix reverts the change that added the space, causing it
@@ -899,8 +1010,8 @@ iOS app losing focus.</p>
 <p>To help apps comply with an Apple policy on the purchase of money cheats,
 consumable in-app purchases have been added for iOS only.</p>
 </div>
-<div class="section" id="id7">
-<h3>Other<a class="headerlink" href="#id7" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id3">
+<h3>Other<a class="headerlink" href="#id3" title="Permalink to this headline"> link</a></h3>
 <p>Unknown gamepads can be calibrated from the shift+G menu.</p>
 <p>The new <a class="reference internal" href="config.html#var-config.replace_text"><code class="xref std std-var docutils literal"><span class="pre">config.replace_text</span></code></a> callback makes it possible to replace
 text with other text. For example, one can replace multiple dashes with
@@ -1032,8 +1143,8 @@ with iOS 8, and makes it possible to keep the launchscreen displayed until
 Ren'Py fully starts. As a result, support for the ios-presplash image is no
 longer necessary, and has been dropped.</p>
 </div>
-<div class="section" id="id8">
-<h3>Other Improvements<a class="headerlink" href="#id8" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id4">
+<h3>Other Improvements<a class="headerlink" href="#id4" title="Permalink to this headline"> link</a></h3>
 <p>A Simplified Chinese translation of the template game has been added, and
 the Korean and Arabic translations have been updated.</p>
 <p>ATL has had an update event added. This event is called in rare (but possible)
@@ -1088,8 +1199,8 @@ package verification process.</p>
 Android device.</p>
 <p>The launcher now checks that the version of rapt and renios match the version
 of Ren'Py proper.</p>
-<div class="section" id="id9">
-<h3>Fixes<a class="headerlink" href="#id9" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id5">
+<h3>Fixes<a class="headerlink" href="#id5" title="Permalink to this headline"> link</a></h3>
 <p>Fixed a performance problem caused by failing to release the Global Interpreter
 Lock while waiting for event input. This could cause problems running various
 background threads, like the image preloader and autosave.</p>
@@ -1261,8 +1372,8 @@ or applies multiple existing text tags to text.</p>
 <p>The previously-existing form of custom text tag has been renamed to
 style text tag, and is still supported.</p>
 </div>
-<div class="section" id="id10">
-<h3>Other Improvements<a class="headerlink" href="#id10" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id6">
+<h3>Other Improvements<a class="headerlink" href="#id6" title="Permalink to this headline"> link</a></h3>
 <p>A high-level achievement API has been added to Ren'Py.</p>
 <p>Ren'Py now includes support for recognizing touch gestures on Android and
 iOS.</p>
@@ -1304,8 +1415,8 @@ determines if an update is available.</p>
 thread, and restarts the interaction when that thread finishes.</p>
 <p>While in self-voicing mode, the {w} and {p} tags are ignored.</p>
 <p>The Traditional Chinese and Russian translations have been updated.</p>
-<div class="section" id="id11">
-<h3>Bug Fixes<a class="headerlink" href="#id11" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id7">
+<h3>Bug Fixes<a class="headerlink" href="#id7" title="Permalink to this headline"> link</a></h3>
 <p>Fixed a regression that could cause hiding transforms to skip time.</p>
 <p>Fixed a bug that would cause the screen language if statement to show
 children from blocks with a false condition, if those child blocks were
@@ -1476,8 +1587,8 @@ channel can be emphasized over music and other sounds,</p>
 <p>To workaround a bug in Mac OS X 10.9, Ren'Py will now always open on the
 the primary monitor of a Macintosh.</p>
 </div>
-<div class="section" id="id12">
-<h3>Other<a class="headerlink" href="#id12" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id8">
+<h3>Other<a class="headerlink" href="#id8" title="Permalink to this headline"> link</a></h3>
 <p>With some limitations, non-ASCII characters can now be used as character
 names. Since Python code does not allow non-ASCII identifiers, such character
 names must be defined by the define statement, and used outside Python code.</p>
@@ -1503,8 +1614,8 @@ save occurs, making them far more useful for debugging pickling problems.</p>
 <p>When show_ arguments are past to an <code class="xref py py-func docutils literal"><span class="pre">NVLCharacter()</span></code>, the show_ prefix
 is stripped and those arguments are passed to the <code class="docutils literal"><span class="pre">nvl</span></code> screen.</p>
 </div>
-<div class="section" id="id13">
-<h3>Translations<a class="headerlink" href="#id13" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id9">
+<h3>Translations<a class="headerlink" href="#id9" title="Permalink to this headline"> link</a></h3>
 <p>This release add an Italian translation of the launcher and template game,
 contributed by Oshi-Shinobu.</p>
 <p>This release adds a Portuguese translation of the template game, contributed
@@ -1541,8 +1652,8 @@ launcher from starting on certain Mac OS X computers.</p>
 </div>
 <div class="section" id="ren-py-6-17-5">
 <h2>Ren'Py 6.17.5<a class="headerlink" href="#ren-py-6-17-5" title="Permalink to this headline"> link</a></h2>
-<div class="section" id="id14">
-<h3>Translations<a class="headerlink" href="#id14" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id10">
+<h3>Translations<a class="headerlink" href="#id10" title="Permalink to this headline"> link</a></h3>
 <p>This release features an Arabic translation of the launcher and template
 game, contributed by Renoa.</p>
 <p>The Japanese and Spanish translations have been updated.</p>
@@ -1566,8 +1677,8 @@ slow down time.</p>
 <a class="reference internal" href="config.html#var-config.autoreload"><code class="xref std std-var docutils literal"><span class="pre">config.autoreload</span></code></a> to True, then pressing shift+R to toggle
 automatic reloading.</p>
 </div>
-<div class="section" id="id15">
-<h3>Fixes<a class="headerlink" href="#id15" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id11">
+<h3>Fixes<a class="headerlink" href="#id11" title="Permalink to this headline"> link</a></h3>
 <p>A regression in 6.17.4 caused a major memory leak on shift+R. This has
 been fixed. Several other problems with shift+R have also been fixed.</p>
 <p>An issue preventing transitions from working properly inside a restarted
@@ -1594,8 +1705,8 @@ is detected, the "firetv" screen variant is selected. To support pushi
 to this device, Ren'Py now supports connecting to Android devices via the
 Remote ADB protocol.</p>
 </div>
-<div class="section" id="id16">
-<h3>Other<a class="headerlink" href="#id16" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id12">
+<h3>Other<a class="headerlink" href="#id12" title="Permalink to this headline"> link</a></h3>
 <p>Fixed a problem that occurred when an interaction containing a MoveTransition
 was restarted.</p>
 <p>Added support for imagemaps that are larger than the screen. This allows an
@@ -1674,13 +1785,13 @@ other statements. It's now possible to write "init 1 image = ...",
 </li>
 </ul>
 </div>
-<div class="section" id="id17">
-<h3>Translations<a class="headerlink" href="#id17" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id13">
+<h3>Translations<a class="headerlink" href="#id13" title="Permalink to this headline"> link</a></h3>
 <p>This release adds French and Russian template games and translations
 of the launcher.</p>
 </div>
-<div class="section" id="id18">
-<h3>Android<a class="headerlink" href="#id18" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id14">
+<h3>Android<a class="headerlink" href="#id14" title="Permalink to this headline"> link</a></h3>
 <p>It is no longer necessary to download RAPT (the Ren'Py Android Packaging Tool)
 separately from Ren'Py. As of this release, RAPT will be downloaded by the
 Ren'Py launcher when an Android build is requested, and will be updated
@@ -1709,8 +1820,8 @@ both can be added by interested developers.</p>
 Ren'Py to its prior windowed size.</li>
 </ul>
 </div>
-<div class="section" id="id19">
-<h3>Other<a class="headerlink" href="#id19" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id15">
+<h3>Other<a class="headerlink" href="#id15" title="Permalink to this headline"> link</a></h3>
 <p><a class="reference internal" href="screen_actions.html#ShowMenu" title="ShowMenu"><code class="xref py py-func docutils literal"><span class="pre">ShowMenu()</span></code></a> can now pass arguments to the screen it displays.</p>
 <p>The input displayable now takes a pixel_width property, that limits
 the size of the input field it a certain number of pixels.</p>
@@ -1746,8 +1857,8 @@ retrieves the mouse position if a mouse is supported.</p>
 </div>
 <div class="section" id="ren-py-6-16">
 <h2>Ren'Py 6.16<a class="headerlink" href="#ren-py-6-16" title="Permalink to this headline"> link</a></h2>
-<div class="section" id="id20">
-<h3>Android<a class="headerlink" href="#id20" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id16">
+<h3>Android<a class="headerlink" href="#id16" title="Permalink to this headline"> link</a></h3>
 <p>Android support has now been integrated into the Ren'Py launcher. While
 for size reasons RAPT is still a separate download, once RAPT has been
 placed inside the Ren'Py directory, the launcher will allow you to:</p>
@@ -1873,8 +1984,8 @@ added or migrated from the old wiki-based documentation.</p>
 </ul>
 <p>Many other documentation pages have been improved and edited.</p>
 </div>
-<div class="section" id="id21">
-<h3>Other<a class="headerlink" href="#id21" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id17">
+<h3>Other<a class="headerlink" href="#id17" title="Permalink to this headline"> link</a></h3>
 <p>The default quick menu now includes rollback and fast skip
 functionality. (This functionality is contained in the template screens.rpy,
 and may need to be copied into your game.)</p>
@@ -2045,8 +2156,8 @@ but saving and loading is disabled.</p>
 <p>The <a class="reference internal" href="rooms.html#Replay" title="Replay"><code class="xref py py-func docutils literal"><span class="pre">Replay()</span></code></a> action begins a replay. The <a class="reference internal" href="rooms.html#renpy.end_replay" title="renpy.end_replay"><code class="xref py py-func docutils literal"><span class="pre">renpy.end_replay()</span></code></a> ends a
 replay if one is in progress, and is ignored otherwise.</p>
 </div>
-<div class="section" id="id22">
-<h3>Voice Improvements<a class="headerlink" href="#id22" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id18">
+<h3>Voice Improvements<a class="headerlink" href="#id18" title="Permalink to this headline"> link</a></h3>
 <p>There have been several improvements to the voice playback system. The new
 <a class="reference internal" href="config.html#var-config.voice_filename_format"><code class="xref std std-var docutils literal"><span class="pre">config.voice_filename_format</span></code></a> variable makes it possible to use only
 part of the filename in a voice statement. The new voice_tag parameter to
@@ -2087,8 +2198,8 @@ of the library are shared between the desktop builds.</p>
 <p>A running Ren'Py process on Linux will now be named after the game, rather
 than having python as a name.</p>
 </div>
-<div class="section" id="id23">
-<h3>Other Changes<a class="headerlink" href="#id23" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id19">
+<h3>Other Changes<a class="headerlink" href="#id19" title="Permalink to this headline"> link</a></h3>
 <ul class="simple">
 <li><a class="reference internal" href="screens.html#sl-viewport"><span class="std std-ref">Viewports</span></a> now support edge scrolling, which scrolls
 the viewport when the mouse is within a a configurable distance of the
@@ -2122,8 +2233,8 @@ transitions that are used upon entering and exiting yes/no prompts.</li>
 <li>The python decimal module is now included in the default builds of Ren'Py.</li>
 </ul>
 </div>
-<div class="section" id="id24">
-<h3>Bugfixes<a class="headerlink" href="#id24" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id20">
+<h3>Bugfixes<a class="headerlink" href="#id20" title="Permalink to this headline"> link</a></h3>
 <p>Among others, the following bugs were fixed:</p>
 <ul class="simple">
 <li><a class="reference external" href="https://github.com/renpy/renpy/issues/37">github bug37</a>: A crash with LiveTile when sizes were not integers.</li>
@@ -2341,8 +2452,8 @@ some Linux systems.</li>
 detection enabled.</li>
 </ul>
 </div>
-<div class="section" id="id25">
-<h3>Other Changes<a class="headerlink" href="#id25" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id21">
+<h3>Other Changes<a class="headerlink" href="#id21" title="Permalink to this headline"> link</a></h3>
 <ul>
 <li><p class="first">The <a class="reference internal" href="statement_equivalents.html#renpy.call" title="renpy.call"><code class="xref py py-func docutils literal"><span class="pre">renpy.call()</span></code></a> function allows - with major and important caveats -
 a call to a Ren'Py label to begin from inside python code. Such a call
@@ -2515,8 +2626,8 @@ to update the graphics drivers.</p>
 OpenGL are incapable of rendering Ren'Py games. Screen-scaling in the
 software renderer has been replaced by a simpler but slower version.</p>
 </div>
-<div class="section" id="id26">
-<h3>Other Changes<a class="headerlink" href="#id26" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id22">
+<h3>Other Changes<a class="headerlink" href="#id22" title="Permalink to this headline"> link</a></h3>
 <ul>
 <li><p class="first">Ren'Py now includes a <a class="reference internal" href="style.html#style-preferences"><span class="std std-ref">style preference</span></a> system.
 This system allows styles to be changed after the init phase has finished.
@@ -2686,8 +2797,8 @@ situation:</p>
 and line number to open that line in the editor.</p>
 <p>The framework is used to handle exceptions and parse errors.</p>
 </div>
-<div class="section" id="id27">
-<h3>Other<a class="headerlink" href="#id27" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id23">
+<h3>Other<a class="headerlink" href="#id23" title="Permalink to this headline"> link</a></h3>
 <p>When in OpenGL mode, Ren'Py now remembers the window size between  sessions.
 (This can be disabled using <a class="reference internal" href="config.html#var-config.save_physical_size"><code class="xref std std-var docutils literal"><span class="pre">config.save_physical_size</span></code></a>, and it  may
 make sense to do so if your game is using the pre-screen preferences system.)
@@ -2733,8 +2844,8 @@ for tracking this down.)</li>
 </div>
 <div class="section" id="ren-py-6-12-0">
 <h2>Ren'Py 6.12.0<a class="headerlink" href="#ren-py-6-12-0" title="Permalink to this headline"> link</a></h2>
-<div class="section" id="id28">
-<h3>Android Support<a class="headerlink" href="#id28" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id24">
+<h3>Android Support<a class="headerlink" href="#id24" title="Permalink to this headline"> link</a></h3>
 <p>Ren'Py now supports the Android platform. This includes support for a large
 fraction of Ren'Py's functionality, although we were unable to add support
 for imagedissolves and movie playback. It should be possible to package a
@@ -2775,8 +2886,8 @@ can support:</p>
 <li>Drag-to-reorder systems.</li>
 </ul>
 </div>
-<div class="section" id="id29">
-<h3>Image Prediction<a class="headerlink" href="#id29" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id25">
+<h3>Image Prediction<a class="headerlink" href="#id25" title="Permalink to this headline"> link</a></h3>
 <p>Ren'Py is now better at predicting image usage. Along with predicting images
 used by normal gameplay, it now attempts to predict images that are used by
 screens one click away from the user. For example, during normal gameplay, it
@@ -2823,8 +2934,8 @@ imagebuttons.</p>
 <p>The <a class="reference internal" href="screen_actions.html#FilePageName" title="FilePageName"><code class="xref py py-func docutils literal"><span class="pre">FilePageName()</span></code></a> and <a class="reference internal" href="screen_actions.html#FileSlotName" title="FileSlotName"><code class="xref py py-func docutils literal"><span class="pre">FileSlotName()</span></code></a> functions make it easier to
 name slots</p>
 </div>
-<div class="section" id="id30">
-<h3>Other Improvements<a class="headerlink" href="#id30" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id26">
+<h3>Other Improvements<a class="headerlink" href="#id26" title="Permalink to this headline"> link</a></h3>
 <p>Ren'Py 6.12 includes a number of other improvements:</p>
 <ul class="simple">
 <li>We've continued writing the new manual. Notably, we have rewritten the
@@ -2841,8 +2952,8 @@ log other subsystems.</li>
 that filename mismatches on Linux should no longer be a problem.</li>
 </ul>
 </div>
-<div class="section" id="id31">
-<h3>Bug Fixes<a class="headerlink" href="#id31" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id27">
+<h3>Bug Fixes<a class="headerlink" href="#id27" title="Permalink to this headline"> link</a></h3>
 <ul class="simple">
 <li><a class="reference external" href="https://bugs.launchpad.net/renpy/+bug/680266">launchpad bug 680266</a> - Ensures that dynamic displayables update before
 Transforms that use them.</li>
@@ -2880,8 +2991,8 @@ and only activate when the button is focused.</p>
 changed their order. This may lead to differences in behavior from the old
 version, where the ordering was undefined.</p>
 </div>
-<div class="section" id="id32">
-<h3>Bug fixes<a class="headerlink" href="#id32" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id28">
+<h3>Bug fixes<a class="headerlink" href="#id28" title="Permalink to this headline"> link</a></h3>
 <p>Fixed <a class="reference external" href="https://bugs.launchpad.net/renpy/+bug/647686">launchpad bug 647686</a>, a regression that prevented sounds from looping
 properly.</p>
 <p>Fixed <a class="reference external" href="https://bugs.launchpad.net/renpy/+bug/661983">launchpad bug 661983</a>, which caused insensitive hotspots to default to the
@@ -2898,8 +3009,8 @@ scaled using OpenGL scaling.</p>
 </div>
 <div class="section" id="ren-py-6-11-1">
 <h2>Ren'Py 6.11.1<a class="headerlink" href="#ren-py-6-11-1" title="Permalink to this headline"> link</a></h2>
-<div class="section" id="id33">
-<h3>New Features<a class="headerlink" href="#id33" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id29">
+<h3>New Features<a class="headerlink" href="#id29" title="Permalink to this headline"> link</a></h3>
 <p>Add the <a class="reference internal" href="displayables.html#AlphaBlend" title="AlphaBlend"><code class="xref py py-func docutils literal"><span class="pre">AlphaBlend()</span></code></a> displayable and the <a class="reference internal" href="transitions.html#AlphaDissolve" title="AlphaDissolve"><code class="xref py py-func docutils literal"><span class="pre">AlphaDissolve()</span></code></a>
 transition. These take two displayables, and use the alpha channel of a third
 displayable to blend them together. (The third displayable is often an
@@ -2931,8 +3042,8 @@ web servers.</p>
 update to the latest pre-release. Hitting shift+U at the launcher's main
 screen will cause Ren'Py to be updated.</p>
 </div>
-<div class="section" id="id34">
-<h3>Fixes<a class="headerlink" href="#id34" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id30">
+<h3>Fixes<a class="headerlink" href="#id30" title="Permalink to this headline"> link</a></h3>
 <p><a class="reference internal" href="transitions.html#MoveTransition" title="MoveTransition"><code class="xref py py-func docutils literal"><span class="pre">MoveTransition()</span></code></a> now respects the xoffset and yoffset parameters.</p>
 <p>Fixed several bugs with screen-language imagemaps.</p>
 <p>Fixed a bug (#626303) that was caused by an incorrect texture unit check.
@@ -2984,8 +3095,8 @@ game from the main menu, without extensive Python code.</p>
 form of Actions and BarValues. This makes it possible to pick and choose
 functionality, and add it to screens as is deemed necessary.</p>
 </div>
-<div class="section" id="id35">
-<h3>Transform Changes<a class="headerlink" href="#id35" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id31">
+<h3>Transform Changes<a class="headerlink" href="#id31" title="Permalink to this headline"> link</a></h3>
 <ul>
 <li><p class="first">If a transform does not define one of the position properties
 <a class="reference internal" href="style_properties.html#style-property-xpos"><code class="xref std std-propref docutils literal"><span class="pre">xpos</span></code></a>, <a class="reference internal" href="style_properties.html#style-property-ypos"><code class="xref std std-propref docutils literal"><span class="pre">ypos</span></code></a>, <a class="reference internal" href="style_properties.html#style-property-xanchor"><code class="xref std std-propref docutils literal"><span class= [...]
@@ -3016,8 +3127,8 @@ result be (50, 100) in size.</p>
 </li>
 </ul>
 </div>
-<div class="section" id="id36">
-<h3>Other Changes<a class="headerlink" href="#id36" title="Permalink to this headline"> link</a></h3>
+<div class="section" id="id32">
+<h3>Other Changes<a class="headerlink" href="#id32" title="Permalink to this headline"> link</a></h3>
 <ul>
 <li><p class="first">The Ren'Py documentation is in the process of being rewritten. This
 changelog is now being maintained as part of the Ren'Py documentation.</p>
diff --git a/doc/character_callbacks.html b/doc/character_callbacks.html
index 47a5f14..3a1c8e7 100644
--- a/doc/character_callbacks.html
+++ b/doc/character_callbacks.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/chromeos.html b/doc/chromeos.html
index 7b49d7f..c76dba9 100644
--- a/doc/chromeos.html
+++ b/doc/chromeos.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/color_class.html b/doc/color_class.html
index bb30a79..c088c3b 100644
--- a/doc/color_class.html
+++ b/doc/color_class.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/conditional.html b/doc/conditional.html
index d34672c..8175414 100644
--- a/doc/conditional.html
+++ b/doc/conditional.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/config.html b/doc/config.html
index 699db75..7f0669f 100644
--- a/doc/config.html
+++ b/doc/config.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -903,7 +904,7 @@ library include "default", "say", "with", "me
 should always be present, as it is used when a more specific key
 is absent.</p>
 <p>Each value in the dictionary should be a list of (<cite>image</cite>,
-<cite>xoffset</cite>, <cite>offset</cite>) tuples, representing frames.</p>
+<cite>xoffset</cite>, <cite>yoffset</cite>) tuples, representing frames.</p>
 <dl class="docutils">
 <dt><cite>image</cite></dt>
 <dd>The mouse cursor image.</dd>
@@ -913,7 +914,7 @@ cursor.</dd>
 <dt><cite>yoffset</cite></dt>
 <dd>The offset of the hotspot pixel from the top of the cursor.</dd>
 </dl>
-<p>The frames are played back at 20hz, and the animation loops after
+<p>The frames are played back at 20Hz, and the animation loops after
 all frames have been shown.</p>
 </dd></dl>
 
@@ -944,7 +945,7 @@ use ui functions to add displayables to the overlay layer.</p>
 <dt id="var-config.overlay_screens">
 define <code class="descname">config.overlay_screens</code> = [ ... ]<a class="headerlink" href="#var-config.overlay_screens" title="Permalink to this definition"> link</a></dt>
 <dd><p>A list of screens that are displayed when the overlay is enabled,
-and hidden when the overlay is supressed. (The screens are shown
+and hidden when the overlay is suppressed. (The screens are shown
 on the screens layer, not the overlay layer.)</p>
 </dd></dl>
 
@@ -1055,7 +1056,7 @@ tag is not found here, <code class="xref std std-var docutils literal"><span cla
 define <code class="descname">config.tag_transform</code> = { }<a class="headerlink" href="#var-config.tag_transform" title="Permalink to this definition"> link</a></dt>
 <dd><p>A dictionary mapping image tag strings to transforms or lists of
 transforms. When an image is newly-shown without an at clause,
-the image's tag is looked up in ths dictionary to find a transform
+the image's tag is looked up in this dictionary to find a transform
 or list of transforms to use.</p>
 </dd></dl>
 
@@ -1147,7 +1148,7 @@ define <code class="descname">config.adjust_view_size</code> = None<a class="hea
 <dd><p>If not None, this should be a function taking two arguments, the width
 and height of the physical window. It is expected to return a tuple
 giving the width and height of the OpenGL viewport, the portion of the
-screen that Ren'Py wil draw pictures to.</p>
+screen that Ren'Py will draw pictures to.</p>
 <p>This can be used to configure Ren'Py to only allow certain sizes of
 screen. For example, the following code allows only integer multiples
 of the original screen size:</p>
@@ -1187,6 +1188,13 @@ delayed before auto-forward mode takes effect.</p>
 </dd></dl>
 
 <dl class="var">
+<dt id="var-config.afm_voice_delay">
+define <code class="descname">config.afm_voice_delay</code> = .5<a class="headerlink" href="#var-config.afm_voice_delay" title="Permalink to this definition"> link</a></dt>
+<dd><p>The number of seconds after a voice file finishes playing
+before AFM can advance text.</p>
+</dd></dl>
+
+<dl class="var">
 <dt id="var-config.all_character_callbacks">
 define <code class="descname">config.all_character_callbacks</code> = [ ]<a class="headerlink" href="#var-config.all_character_callbacks" title="Permalink to this definition"> link</a></dt>
 <dd><p>A list of callbacks that are called by all characters. This list
@@ -1580,7 +1588,7 @@ always be in this list.</p>
 <dt id="var-config.periodic_callback">
 define <code class="descname">config.periodic_callback</code> = None<a class="headerlink" href="#var-config.periodic_callback" title="Permalink to this definition"> link</a></dt>
 <dd><p>If not None, this should be a function. The function is called,
-with no arguments, at around 20hz.</p>
+with no arguments, at around 20Hz.</p>
 </dd></dl>
 
 <dl class="var">
diff --git a/doc/credits.html b/doc/credits.html
index 7450473..536a5f6 100644
--- a/doc/credits.html
+++ b/doc/credits.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/custom_text_tags.html b/doc/custom_text_tags.html
index e2149b1..1f0f9a7 100644
--- a/doc/custom_text_tags.html
+++ b/doc/custom_text_tags.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/developer_tools.html b/doc/developer_tools.html
index 6c6c5b1..5fafeb0 100644
--- a/doc/developer_tools.html
+++ b/doc/developer_tools.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/dialogue.html b/doc/dialogue.html
index 21ae5f5..e162fd2 100644
--- a/doc/dialogue.html
+++ b/doc/dialogue.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -550,7 +551,8 @@ used.</p>
 before statements listed in <a class="reference internal" href="config.html#var-config.window_auto_show"><code class="xref std std-var docutils literal"><span class="pre">config.window_auto_show</span></code></a> - by default,
 say statements. The window is hidden before statements listed in
 <a class="reference internal" href="config.html#var-config.window_auto_hide"><code class="xref std std-var docutils literal"><span class="pre">config.window_auto_hide</span></code></a> - by default, <code class="docutils literal"><span class="pre">scene</span></code> and <code class="docutils literal"><span class="pre">call</span> <span class="pre">screen</span></code>
-statements.</p>
+statements. (Only statements are considered, not statement equivalent
+functions.)</p>
 <p>The <code class="docutils literal"><span class="pre">window</span> <span class="pre">auto</span></code> statement uses <a class="reference internal" href="config.html#var-config.window_show_transition"><code class="xref std std-var docutils literal"><span class="pre">config.window_show_transition</span></code></a>
 and <a class="reference internal" href="config.html#var-config.window_hide_transition"><code class="xref std std-var docutils literal"><span class="pre">config.window_hide_transition</span></code></a> to show and hide the window,
 respectively. <code class="docutils literal"><span class="pre">window</span> <span class="pre">auto</span></code> is cancelled by <code class="docutils literal"><span class="pre">window</span> <span class="pre">show</span></code> or <code class="docutils literal"><span class="pre">window</span> <span class="pre">hide</span></code>.</p>
@@ -610,6 +612,32 @@ the default store, it can be defined using:</p>
     <span class="n">e</span> <span class="s2">"Our starting energy is [e] units."</span>
 </pre></div>
 </div>
+<p>Window management is performed by setting the <a class="reference internal" href="store_variables.html#var-_window"><code class="xref std std-var docutils literal"><span class="pre">_window</span></code></a> and
+<a class="reference internal" href="store_variables.html#var-_window_auto"><code class="xref std std-var docutils literal"><span class="pre">_window_auto</span></code></a> variables, and by using the following two functions:</p>
+<dl class="function">
+<dt id="_window_hide">
+<code class="descname">_window_hide</code><span class="sig-paren">(</span><em>trans=False</em><span class="sig-paren">)</span><a class="headerlink" href="#_window_hide" title="Permalink to this definition"> link</a></dt>
+<dd><p>The python equivalent of the "window hide" statement.</p>
+<dl class="docutils">
+<dt><cite>trans</cite></dt>
+<dd>If False, the default window hide transition is used. If None,
+no transition is used. Otherwise, the specified transition is
+used.</dd>
+</dl>
+</dd></dl>
+
+<dl class="function">
+<dt id="_window_show">
+<code class="descname">_window_show</code><span class="sig-paren">(</span><em>trans=False</em><span class="sig-paren">)</span><a class="headerlink" href="#_window_show" title="Permalink to this definition"> link</a></dt>
+<dd><p>The python equivalent of the "window show" statement.</p>
+<dl class="docutils">
+<dt><cite>trans</cite></dt>
+<dd>If False, the default window show transition is used. If None,
+no transition is used. Otherwise, the specified transition is
+used.</dd>
+</dl>
+</dd></dl>
+
 </div>
 </div>
 
diff --git a/doc/display_problems.html b/doc/display_problems.html
index 840a63b..38fd55b 100644
--- a/doc/display_problems.html
+++ b/doc/display_problems.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -49,7 +49,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -145,6 +145,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/displayables.html b/doc/displayables.html
index 8cad37e..7318b3e 100644
--- a/doc/displayables.html
+++ b/doc/displayables.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -266,6 +267,14 @@ extension.</p>
 <span class="k">image</span> <span class="n">logo</span> <span class="n">right</span> <span class="o">=</span> <span class="n">Image</span><span class="p">(</span><span class="s2">"logo.png"</span><span class="p">,</span> <span class="na">xalign</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span>
 </pre></div>
 </div>
+<p>There are three image file formats we recommend you use:</p>
+<ul class="simple">
+<li>Webp</li>
+<li>Png</li>
+<li>Jpg</li>
+</ul>
+<p>Non-animated Gif and Bmp files are also supported, but should not be
+used in modern games.</p>
 <p>Loading an Image from from a file on disk and decoding it so it can be
 drawn to the screen takes a long amount of time. While measured in the
 tenths or hundreds of seconds, the duration of the loading process is
diff --git a/doc/displaying_images.html b/doc/displaying_images.html
index 87dd616..266adf5 100644
--- a/doc/displaying_images.html
+++ b/doc/displaying_images.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/distributor.html b/doc/distributor.html
index 360e80d..adf69d3 100644
--- a/doc/distributor.html
+++ b/doc/distributor.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/drag_drop.html b/doc/drag_drop.html
index f84a779..c03f656 100644
--- a/doc/drag_drop.html
+++ b/doc/drag_drop.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/editor.html b/doc/editor.html
index a90e6cc..647b73d 100644
--- a/doc/editor.html
+++ b/doc/editor.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul class="current">
 <li class="toctree-l1 current"><a class="current reference internal" href="#">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/environment_variables.html b/doc/environment_variables.html
index e142ee1..191b0b1 100644
--- a/doc/environment_variables.html
+++ b/doc/environment_variables.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/file_python.html b/doc/file_python.html
index f34d8a4..e55ccaf 100644
--- a/doc/file_python.html
+++ b/doc/file_python.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/genindex.html b/doc/genindex.html
index 2fddb1b..f881eb3 100644
--- a/doc/genindex.html
+++ b/doc/genindex.html
@@ -17,7 +17,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -50,7 +50,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -146,6 +146,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -273,12 +274,12 @@
   <dt><a href="store_variables.html#var-_history_list">_history_list (variable)</a>
   </dt>
 
-  </dl></td>
-  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="rooms.html#var-_in_replay">_in_replay (variable)</a>
   </dt>
 
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="store_variables.html#var-_menu">_menu (variable)</a>
   </dt>
@@ -304,6 +305,14 @@
   </dt>
 
       
+  <dt><a href="dialogue.html#_window_hide">_window_hide() (built-in function)</a>
+  </dt>
+
+      
+  <dt><a href="dialogue.html#_window_show">_window_show() (built-in function)</a>
+  </dt>
+
+      
   <dt><a href="store_variables.html#var-_window_subtitle">_window_subtitle (variable)</a>
   </dt>
 
@@ -742,6 +751,10 @@
   </dt>
 
       
+  <dt><a href="config.html#var-config.afm_voice_delay">config.afm_voice_delay (variable)</a>
+  </dt>
+
+      
   <dt><a href="config.html#var-config.after_load_callbacks">config.after_load_callbacks (variable)</a>
   </dt>
 
@@ -1601,6 +1614,10 @@
   <dt><a href="screen_python.html#InputValue.Disable">Disable() (InputValue method)</a>
   </dt>
 
+      
+  <dt><a href="screen_actions.html#DisableAllInputValues">DisableAllInputValues() (built-in function)</a>
+  </dt>
+
   </dl></td>
   <td style="width: 33%" valign="top"><dl>
       
@@ -1992,6 +2009,10 @@
   </dt>
 
       
+  <dt><a href="translating_renpy.html#var-gui.FONT_SCALE">gui.FONT_SCALE (variable)</a>
+  </dt>
+
+      
   <dt><a href="gui.html#var-gui.frame_borders">gui.frame_borders (variable)</a>
   </dt>
 
@@ -2071,17 +2092,21 @@
   <dt><a href="gui.html#var-gui.interface_text_color">gui.interface_text_color (variable)</a>
   </dt>
 
-  </dl></td>
-  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="gui.html#var-gui.interface_text_size">gui.interface_text_size (variable)</a>
   </dt>
 
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="gui.html#var-gui.label_text_size">gui.label_text_size (variable)</a>
   </dt>
 
       
+  <dt><a href="translating_renpy.html#var-gui.LIGHT_FONT">gui.LIGHT_FONT (variable)</a>
+  </dt>
+
+      
   <dt><a href="gui.html#var-gui.muted_color">gui.muted_color (variable)</a>
   </dt>
 
@@ -2206,6 +2231,14 @@
   </dt>
 
       
+  <dt><a href="translating_renpy.html#var-gui.REGULAR_BOLD">gui.REGULAR_BOLD (variable)</a>
+  </dt>
+
+      
+  <dt><a href="translating_renpy.html#var-gui.REGULAR_FONT">gui.REGULAR_FONT (variable)</a>
+  </dt>
+
+      
   <dt><a href="gui.html#var-gui.scrollbar_borders">gui.scrollbar_borders (variable)</a>
   </dt>
 
@@ -4374,12 +4407,12 @@
   <dt><a href="rooms.html#MusicRoom.ToggleSingleTrack">ToggleSingleTrack() (MusicRoom method)</a>
   </dt>
 
-  </dl></td>
-  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="rooms.html#Gallery.ToggleSlideshow">ToggleSlideshow() (Gallery method)</a>
   </dt>
 
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
       
   <dt><a href="screen_actions.html#ToggleVariable">ToggleVariable() (built-in function)</a>
   </dt>
@@ -4441,6 +4474,14 @@
   </dt>
 
       
+  <dt><a href="translating_renpy.html#translate_define">translate_define() (built-in function)</a>
+  </dt>
+
+      
+  <dt><a href="translating_renpy.html#translate_font">translate_font() (built-in function)</a>
+  </dt>
+
+      
   <dt><a href="transforms.html#var-truecenter">truecenter (variable)</a>
   </dt>
 
diff --git a/doc/gesture.html b/doc/gesture.html
index 75dc08c..3f3c28e 100644
--- a/doc/gesture.html
+++ b/doc/gesture.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/gui.html b/doc/gui.html
index b5020f0..67a1699 100644
--- a/doc/gui.html
+++ b/doc/gui.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/history.html b/doc/history.html
index 239e000..4d16b86 100644
--- a/doc/history.html
+++ b/doc/history.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/iap.html b/doc/iap.html
index 45d8942..f2568ce 100644
--- a/doc/iap.html
+++ b/doc/iap.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/incompatible.html b/doc/incompatible.html
index 2335cd6..6a3e8bb 100644
--- a/doc/incompatible.html
+++ b/doc/incompatible.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/index.html b/doc/index.html
index 38d3fa1..a99a62c 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -50,7 +50,7 @@
         </button>
         <a class="navbar-brand" href="#">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -146,6 +146,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -389,6 +390,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 </div>
 </div>
diff --git a/doc/input.html b/doc/input.html
index 8e4c691..2cf42c8 100644
--- a/doc/input.html
+++ b/doc/input.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/ios.html b/doc/ios.html
index 2cb25e8..a64065f 100644
--- a/doc/ios.html
+++ b/doc/ios.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/keymap.html b/doc/keymap.html
index e115166..c24e03f 100644
--- a/doc/keymap.html
+++ b/doc/keymap.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/label.html b/doc/label.html
index c493f8c..3f96211 100644
--- a/doc/label.html
+++ b/doc/label.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/language_basics.html b/doc/language_basics.html
index 1b77148..971ef44 100644
--- a/doc/language_basics.html
+++ b/doc/language_basics.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/license.html b/doc/license.html
index 01c0b40..a86b576 100644
--- a/doc/license.html
+++ b/doc/license.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/menus.html b/doc/menus.html
index 44ed6f0..e262791 100644
--- a/doc/menus.html
+++ b/doc/menus.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/modes.html b/doc/modes.html
index 95abfb9..191ec40 100644
--- a/doc/modes.html
+++ b/doc/modes.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/movie.html b/doc/movie.html
index 67db63f..cbba75b 100644
--- a/doc/movie.html
+++ b/doc/movie.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/nvl_mode.html b/doc/nvl_mode.html
index 63240ba..12fd828 100644
--- a/doc/nvl_mode.html
+++ b/doc/nvl_mode.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/objects.inv b/doc/objects.inv
index 31423de..4933992 100644
Binary files a/doc/objects.inv and b/doc/objects.inv differ
diff --git a/doc/other.html b/doc/other.html
index 3e5cec8..6e2b895 100644
--- a/doc/other.html
+++ b/doc/other.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/persistent.html b/doc/persistent.html
index c8bf578..2cbb557 100644
--- a/doc/persistent.html
+++ b/doc/persistent.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/problems.html b/doc/problems.html
index 0f9e385..8771892 100644
--- a/doc/problems.html
+++ b/doc/problems.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/py-function-class-index.html b/doc/py-function-class-index.html
index 1de8963..49ea300 100644
--- a/doc/py-function-class-index.html
+++ b/doc/py-function-class-index.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -52,7 +52,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -148,6 +148,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -404,6 +405,11 @@
      <tr>
        <td></td>
        <td>
+       <a href="screen_actions.html#DisableAllInputValues"><code class="xref">DisableAllInputValues</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
        <a href="transitions.html#Dissolve"><code class="xref">Dissolve</code></a></td><td>
        <em></em></td></tr>
      <tr>
@@ -2241,6 +2247,16 @@
        <td>
        <a href="trans_trans_python.html#Transform"><code class="xref">Transform</code></a></td><td>
        <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="translating_renpy.html#translate_define"><code class="xref">translate_define</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="translating_renpy.html#translate_font"><code class="xref">translate_font</code></a></td><td>
+       <em></em></td></tr>
      <tr class="pcap"><td></td><td> </td><td></td></tr>
      <tr class="cap" id="cap-U"><td></td><td>
        <strong>U</strong></td><td></td></tr>
@@ -2404,6 +2420,16 @@
        <td>
        <a href="voice.html#_get_voice_info"><code class="xref">_get_voice_info</code></a></td><td>
        <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="dialogue.html#_window_hide"><code class="xref">_window_hide</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="dialogue.html#_window_show"><code class="xref">_window_show</code></a></td><td>
+       <em></em></td></tr>
    </table>
 
 
diff --git a/doc/python.html b/doc/python.html
index 81f23a9..5ea4b81 100644
--- a/doc/python.html
+++ b/doc/python.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/quickstart.html b/doc/quickstart.html
index f2b2979..eeb045f 100644
--- a/doc/quickstart.html
+++ b/doc/quickstart.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -427,8 +428,8 @@ the launcher. You'll probably want to copy the image files from the
 so you can run this example.</p>
 <p>Ren'Py does not make any distinction between character and background
 art, as they're both treated as images. In general, character art
-needs to be transparent, which means it should be a PNG
-file. Background art can be JPEG or PNG files. By convention,
+needs to be transparent, which means it should be a PNG or WEBP
+file. Background art can be JPEG, PNG, or WEBP files. By convention,
 background images start with the "bg" tag.</p>
 <p><strong>Hide Statement.</strong>
 Ren'Py also supports a hide statement, which hides the given image.</p>
@@ -695,21 +696,6 @@ things are possible.</p>
 <p>Once you've made a game, there are a number of things you should do
 before releasing it:</p>
 <dl class="docutils">
-<dt><strong>Edit options.rpy.</strong></dt>
-<dd>The options.rpy file, created when you create a new game, contains
-a number of settings that you may want to customize. Some of them,
-like the screen height and screen width, should probably be set
-before making the game. Others, like the window title, can be set
-any time.</dd>
-<dt><strong>Add a plug for Ren'Py.</strong></dt>
-<dd><p class="first">This step is completely optional, but we do ask that if you have
-credits in your game, you mention Ren'Py in them. We suggest using
-something like "Made with the Ren'Py visual novel engine.", but
-that's just a suggestion, and what you write is up to you.</p>
-<p class="last">We think that the games people make are the best advertising for
-Ren'Py, and we hope that by including this, you'll help more people
-learn how to make visual novels in Ren'Py.</p>
-</dd>
 <dt><strong>Check for a new version of Ren'Py.</strong></dt>
 <dd>New versions of Ren'Py are released on a regular basis, to fix bugs
 and add new features. Before releasing, click update in the launcher
diff --git a/doc/reserved.html b/doc/reserved.html
index a7322c2..6bc8028 100644
--- a/doc/reserved.html
+++ b/doc/reserved.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -49,7 +49,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -145,6 +145,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -361,6 +362,7 @@ so can cause obscure problems.</p>
 <li>DictEquality</li>
 <li><a class="reference internal" href="screen_actions.html#DictInputValue" title="DictInputValue"><code class="xref py py-func docutils literal"><span class="pre">DictInputValue()</span></code></a></li>
 <li><a class="reference internal" href="screen_actions.html#DictValue" title="DictValue"><code class="xref py py-func docutils literal"><span class="pre">DictValue()</span></code></a></li>
+<li><a class="reference internal" href="screen_actions.html#DisableAllInputValues" title="DisableAllInputValues"><code class="xref py py-func docutils literal"><span class="pre">DisableAllInputValues()</span></code></a></li>
 <li><a class="reference internal" href="transitions.html#Dissolve" title="Dissolve"><code class="xref py py-func docutils literal"><span class="pre">Dissolve()</span></code></a></li>
 <li><a class="reference internal" href="drag_drop.html#Drag" title="Drag"><code class="xref py py-class docutils literal"><span class="pre">Drag</span></code></a></li>
 <li><a class="reference internal" href="drag_drop.html#DragGroup" title="DragGroup"><code class="xref py py-class docutils literal"><span class="pre">DragGroup</span></code></a></li>
diff --git a/doc/rooms.html b/doc/rooms.html
index 7dbc604..9b6de7c 100644
--- a/doc/rooms.html
+++ b/doc/rooms.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -493,7 +494,7 @@ of one or more displayables.</p>
 
 <dl class="method">
 <dt id="Gallery.get_fraction">
-<code class="descname">get_fraction</code><span class="sig-paren">(</span><em>name</em>, <em>format='{seen}/{total}'</em><span class="sig-paren">)</span><a class="headerlink" href="#Gallery.get_fraction" title="Permalink to this definition"> link</a></dt>
+<code class="descname">get_fraction</code><span class="sig-paren">(</span><em>name</em>, <em>format=u'{seen}/{total}'</em><span class="sig-paren">)</span><a class="headerlink" href="#Gallery.get_fraction" title="Permalink to this definition"> link</a></dt>
 <dd><p>Returns a text string giving the number of unlocked images and total number of images in the button
 named <cite>name</cite>.</p>
 <dl class="docutils">
@@ -658,7 +659,7 @@ accomplishing it is to add the following line:</p>
 slider on the music screen.</p>
 <dl class="class">
 <dt id="MusicRoom">
-<em class="property">class </em><code class="descname">MusicRoom</code><span class="sig-paren">(</span><em>channel='music'</em>, <em>fadeout=0.0</em>, <em>fadein=0.0</em>, <em>loop=True</em>, <em>single_track=False</em>, <em>shuffle=False</em>, <em>stop_action=None</em><span class="sig-paren">)</span><a class="headerlink" href="#MusicRoom" title="Permalink to this definition"> link</a></dt>
+<em class="property">class </em><code class="descname">MusicRoom</code><span class="sig-paren">(</span><em>channel=u'music'</em>, <em>fadeout=0.0</em>, <em>fadein=0.0</em>, <em>loop=True</em>, <em>single_track=False</em>, <em>shuffle=False</em>, <em>stop_action=None</em><span class="sig-paren">)</span><a class="headerlink" href="#MusicRoom" title="Permalink to this definition"> link</a></dt>
 <dd><p>A music room that contains a series of songs that can be unlocked
 by the user, and actions that can play entries from the list in
 order.</p>
diff --git a/doc/save_load_rollback.html b/doc/save_load_rollback.html
index fc5a18c..1f0385e 100644
--- a/doc/save_load_rollback.html
+++ b/doc/save_load_rollback.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/screen_actions.html b/doc/screen_actions.html
index c688b1a..8452fe8 100644
--- a/doc/screen_actions.html
+++ b/doc/screen_actions.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -462,7 +463,7 @@ default screen, taken from _game_menu_screen.</p>
 
 <dl class="function">
 <dt id="Start">
-<code class="descname">Start</code><span class="sig-paren">(</span><em>label='start'</em><span class="sig-paren">)</span><a class="headerlink" href="#Start" title="Permalink to this definition"> link</a></dt>
+<code class="descname">Start</code><span class="sig-paren">(</span><em>label=u'start'</em><span class="sig-paren">)</span><a class="headerlink" href="#Start" title="Permalink to this definition"> link</a></dt>
 <dd><p>Causes Ren'Py to jump out of the menu context to the named
 label. The main use of this is to start a new game from the
 main menu. Common uses are:</p>
@@ -611,7 +612,7 @@ a picture of the screen before a file save screen is shown.</p>
 
 <dl class="function">
 <dt id="QuickSave">
-<code class="descname">QuickSave</code><span class="sig-paren">(</span><em>message='Quick save complete.'</em>, <em>newest=False</em><span class="sig-paren">)</span><a class="headerlink" href="#QuickSave" title="Permalink to this definition"> link</a></dt>
+<code class="descname">QuickSave</code><span class="sig-paren">(</span><em>message=u'Quick save complete.'</em>, <em>newest=False</em><span class="sig-paren">)</span><a class="headerlink" href="#QuickSave" title="Permalink to this definition"> link</a></dt>
 <dd><p>Performs a quick save.</p>
 <dl class="docutils">
 <dt><cite>message</cite></dt>
@@ -739,6 +740,14 @@ of the <cite>yes</cite> action.</p>
 </dd></dl>
 
 <dl class="function">
+<dt id="DisableAllInputValues">
+<code class="descname">DisableAllInputValues</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#DisableAllInputValues" title="Permalink to this definition"> link</a></dt>
+<dd><p>Disables all active InputValue. This will re-focus the default
+InputValue, if there is one. Otherwise, no InputValue will be
+focused.</p>
+</dd></dl>
+
+<dl class="function">
 <dt id="Function">
 <code class="descname">Function</code><span class="sig-paren">(</span><em>callable</em>, <em>*args</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#Function" title="Permalink to this definition"> link</a></dt>
 <dd><p>This Action calls <cite>callable</cite> with <cite>args</cite> and <cite>kwargs</cite>.</p>
@@ -936,7 +945,7 @@ to <cite>value</cite>.</dd>
 
 <dl class="function">
 <dt id="AudioPositionValue">
-<code class="descname">AudioPositionValue</code><span class="sig-paren">(</span><em>channel='music'</em>, <em>update_interval=0.1</em><span class="sig-paren">)</span><a class="headerlink" href="#AudioPositionValue" title="Permalink to this definition"> link</a></dt>
+<code class="descname">AudioPositionValue</code><span class="sig-paren">(</span><em>channel=u'music'</em>, <em>update_interval=0.1</em><span class="sig-paren">)</span><a class="headerlink" href="#AudioPositionValue" title="Permalink to this definition"> link</a></dt>
 <dd><p>A value that shows the playback position of the audio file playing
 in <cite>channel</cite>.</p>
 <dl class="docutils">
@@ -947,7 +956,7 @@ in <cite>channel</cite>.</p>
 
 <dl class="function">
 <dt id="DictValue">
-<code class="descname">DictValue</code><span class="sig-paren">(</span><em>dict</em>, <em>key</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style='bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#DictValue" title="Permalink to this definition"> link</a></dt>
+<code class="descname">DictValue</code><span class="sig-paren">(</span><em>dict</em>, <em>key</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style=u'bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#DictValue" title="Permalink to this definition"> link</a></dt>
 <dd><p>A value that allows the user to adjust the value of a key
 in a dict.</p>
 <dl class="docutils">
@@ -974,7 +983,7 @@ the bar.</dd>
 
 <dl class="function">
 <dt id="FieldValue">
-<code class="descname">FieldValue</code><span class="sig-paren">(</span><em>object</em>, <em>field</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style='bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FieldValue" title="Permalink to this definition"> link</a></dt>
+<code class="descname">FieldValue</code><span class="sig-paren">(</span><em>object</em>, <em>field</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style=u'bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FieldValue" title="Permalink to this definition"> link</a></dt>
 <dd><p>A bar value that allows the user to adjust the value of a field
 on an object.</p>
 <dl class="docutils">
@@ -1015,7 +1024,7 @@ mixers.</dd>
 
 <dl class="function">
 <dt id="ScreenVariableValue">
-<code class="descname">ScreenVariableValue</code><span class="sig-paren">(</span><em>variable</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style='bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#ScreenVariableValue" title="Permalink to this definition"> link</a></dt>
+<code class="descname">ScreenVariableValue</code><span class="sig-paren">(</span><em>variable</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style=u'bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#ScreenVariableValue" title="Permalink to this definition"> link</a></dt>
 <dd><p>A bar value that adjusts the value of a variable in a screen.</p>
 <dl class="docutils">
 <dt><cite>object</cite></dt>
@@ -1055,7 +1064,7 @@ the bar.</dd>
 
 <dl class="function">
 <dt id="VariableValue">
-<code class="descname">VariableValue</code><span class="sig-paren">(</span><em>variable</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style='bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#VariableValue" title="Permalink to this definition"> link</a></dt>
+<code class="descname">VariableValue</code><span class="sig-paren">(</span><em>variable</em>, <em>range</em>, <em>max_is_zero=False</em>, <em>style=u'bar'</em>, <em>offset=0</em>, <em>step=None</em><span class="sig-paren">)</span><a class="headerlink" href="#VariableValue" title="Permalink to this definition"> link</a></dt>
 <dd><p>A bar value that allows the user to adjust the value of a variable
 in the default store.</p>
 <dl class="docutils">
@@ -1105,7 +1114,8 @@ editable by default. To create a new input value, subclass the <a class="referen
 class.</p>
 <p>Ren'Py-defined input values inherit from InputValue, which means that
 all values also include Enable(), Disable(), and Toggle() methods that return
-actions that enable, disable, and toggle editing, respectively.</p>
+actions that enable, disable, and toggle editing, respectively. See also
+the <a class="reference internal" href="#DisableAllInputValues" title="DisableAllInputValues"><code class="xref py py-func docutils literal"><span class="pre">DisableAllInputValues()</span></code></a> action.</p>
 <dl class="function">
 <dt id="DictInputValue">
 <code class="descname">DictInputValue</code><span class="sig-paren">(</span><em>dict</em>, <em>key</em>, <em>default=True</em>, <em>returnable=False</em><span class="sig-paren">)</span><a class="headerlink" href="#DictInputValue" title="Permalink to this definition"> link</a></dt>
@@ -1136,8 +1146,23 @@ user presses enter.</dd>
 
 <dl class="function">
 <dt id="FilePageNameInputValue">
-<code class="descname">FilePageNameInputValue</code><span class="sig-paren">(</span><em>pattern='Page {}'</em>, <em>auto='Automatic saves'</em>, <em>quick='Quick saves'</em>, <em>page=None</em>, <em>default=False</em><span class="sig-paren">)</span><a class="headerlink" href="#FilePageNameInputValue" title="Permalink to this definition"> link</a></dt>
-<dd></dd></dl>
+<code class="descname">FilePageNameInputValue</code><span class="sig-paren">(</span><em>pattern=u'Page {}'</em>, <em>auto=u'Automatic saves'</em>, <em>quick=u'Quick saves'</em>, <em>page=None</em>, <em>default=False</em><span class="sig-paren">)</span><a class="headerlink" href="#FilePageNameInputValue" title="Permalink to this definition"> link</a></dt>
+<dd><p>An input value that updates the name of a file page.</p>
+<dl class="docutils">
+<dt><cite>pattern</cite></dt>
+<dd>This is used for the default name of a page. Python-style substition
+is performed, such that {} is replaced with the number of the page.</dd>
+<dt><cite>auto</cite></dt>
+<dd>The name of the autosave page.</dd>
+<dt><cite>quick</cite></dt>
+<dd>The name of the quicksave page.</dd>
+<dt><cite>page</cite></dt>
+<dd>If given, the number of the page to display. This should usually
+be left as None, to give the current page.</dd>
+<dt><cite>default</cite></dt>
+<dd>If true, this input can be editable by default.</dd>
+</dl>
+</dd></dl>
 
 <dl class="function">
 <dt id="ScreenVariableInputValue">
@@ -1346,7 +1371,7 @@ if the file is loadable, and false otherwise.</p>
 
 <dl class="function">
 <dt id="FilePageName">
-<code class="descname">FilePageName</code><span class="sig-paren">(</span><em>auto='a'</em>, <em>quick='q'</em><span class="sig-paren">)</span><a class="headerlink" href="#FilePageName" title="Permalink to this definition"> link</a></dt>
+<code class="descname">FilePageName</code><span class="sig-paren">(</span><em>auto=u'a'</em>, <em>quick=u'q'</em><span class="sig-paren">)</span><a class="headerlink" href="#FilePageName" title="Permalink to this definition"> link</a></dt>
 <dd><p>Returns the name of the current file page, as a string. If a normal
 page, this returns the page number. Otherwise, it returns
 <cite>auto</cite> or <cite>quick</cite>.</p>
@@ -1354,7 +1379,7 @@ page, this returns the page number. Otherwise, it returns
 
 <dl class="function">
 <dt id="FileSaveName">
-<code class="descname">FileSaveName</code><span class="sig-paren">(</span><em>name</em>, <em>empty=''</em>, <em>page=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FileSaveName" title="Permalink to this definition"> link</a></dt>
+<code class="descname">FileSaveName</code><span class="sig-paren">(</span><em>name</em>, <em>empty=u''</em>, <em>page=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FileSaveName" title="Permalink to this definition"> link</a></dt>
 <dd><p>Return the save_name that was in effect when the file was saved,
 or <cite>empty</cite> if the file does not exist.</p>
 </dd></dl>
@@ -1370,7 +1395,7 @@ in which case, a Null displayable is created.</p>
 
 <dl class="function">
 <dt id="FileSlotName">
-<code class="descname">FileSlotName</code><span class="sig-paren">(</span><em>slot</em>, <em>slots_per_page</em>, <em>auto='a'</em>, <em>quick='q'</em>, <em>format='%s%d'</em><span class="sig-paren">)</span><a class="headerlink" href="#FileSlotName" title="Permalink to this definition"> link</a></dt>
+<code class="descname">FileSlotName</code><span class="sig-paren">(</span><em>slot</em>, <em>slots_per_page</em>, <em>auto=u'a'</em>, <em>quick=u'q'</em>, <em>format=u'%s%d'</em><span class="sig-paren">)</span><a class="headerlink" href="#FileSlotName" title="Permalink to this definition"> link</a></dt>
 <dd><p>Returns the name of the numbered slot. This assumes that slots on
 normal pages are numbered in a linear order starting with 1, and
 that page numbers start with 1. When slot is 2, and slots_per_page
@@ -1398,7 +1423,7 @@ giving the page prefix, and an integer giving the slot number.</dd>
 
 <dl class="function">
 <dt id="FileTime">
-<code class="descname">FileTime</code><span class="sig-paren">(</span><em>name</em>, <em>format='%b %d</em>, <em>%H:%M'</em>, <em>empty=''</em>, <em>page=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FileTime" title="Permalink to this definition"> link</a></dt>
+<code class="descname">FileTime</code><span class="sig-paren">(</span><em>name</em>, <em>format=u'%b %d</em>, <em>%H:%M'</em>, <em>empty=u''</em>, <em>page=None</em><span class="sig-paren">)</span><a class="headerlink" href="#FileTime" title="Permalink to this definition"> link</a></dt>
 <dd><p>Returns the time the file was saved, formatted according
 to the supplied <cite>format</cite>. If the file is not found, <cite>empty</cite> is
 returned.</p>
diff --git a/doc/screen_optimization.html b/doc/screen_optimization.html
index d90d8cf..608e35b 100644
--- a/doc/screen_optimization.html
+++ b/doc/screen_optimization.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -534,6 +535,7 @@ directory.</p>
 <li><a class="reference internal" href="transitions.html#CropMove" title="CropMove"><code class="xref py py-func docutils literal"><span class="pre">CropMove()</span></code></a></li>
 <li><a class="reference internal" href="screen_actions.html#DictInputValue" title="DictInputValue"><code class="xref py py-func docutils literal"><span class="pre">DictInputValue()</span></code></a></li>
 <li><a class="reference internal" href="screen_actions.html#DictValue" title="DictValue"><code class="xref py py-func docutils literal"><span class="pre">DictValue()</span></code></a></li>
+<li><a class="reference internal" href="screen_actions.html#DisableAllInputValues" title="DisableAllInputValues"><code class="xref py py-func docutils literal"><span class="pre">DisableAllInputValues()</span></code></a></li>
 <li><a class="reference internal" href="transitions.html#Dissolve" title="Dissolve"><code class="xref py py-func docutils literal"><span class="pre">Dissolve()</span></code></a></li>
 <li><a class="reference internal" href="drag_drop.html#Drag" title="Drag"><code class="xref py py-class docutils literal"><span class="pre">Drag</span></code></a></li>
 <li>DynamicCharacter</li>
@@ -658,6 +660,7 @@ directory.</p>
 <li>_m1_00gallery__GalleryToggleSlideshow</li>
 <li>_m1_00musicroom__MusicRoomPlay</li>
 <li>_m1_00musicroom__MusicRoomRandomPlay</li>
+<li>_m1_00musicroom__MusicRoomStop</li>
 <li>_m1_00musicroom__MusicRoomTogglePlay</li>
 <li>_m1_00preferences__DisplayAction</li>
 <li>_movebottom</li>
diff --git a/doc/screen_python.html b/doc/screen_python.html
index 8ef6434..2511257 100644
--- a/doc/screen_python.html
+++ b/doc/screen_python.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/screen_special.html b/doc/screen_special.html
index f6396af..cbb469c 100644
--- a/doc/screen_special.html
+++ b/doc/screen_special.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/screens.html b/doc/screens.html
index 3ed3866..fea523d 100644
--- a/doc/screens.html
+++ b/doc/screens.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -1096,9 +1097,25 @@ following properties:</p>
 compute it's own size. If either component is None, the child's
 size is used.</dd>
 <dt><cite>mousewheel</cite></dt>
-<dd>If True, the mouse wheel can be used to scroll the viewport vertically.
-If "horizontal", the mouse wheel can be used to scroll the viewport
-horizontally.</dd>
+<dd><p class="first">This should be one of:</p>
+<dl class="last docutils">
+<dt>False</dt>
+<dd>To ignore the mousewheel. (The default.)</dd>
+<dt>True</dt>
+<dd>To scroll vertically.</dd>
+<dt>"horizontal"</dt>
+<dd>To scroll horizontally.</dd>
+<dt>"change"</dt>
+<dd>To scroll the viewport vertically, only if doing so would cause the
+viewport to move. If not, the mousewheel event is passed to the rest
+of the interface. (For example, if change is given, placing
+<code class="docutils literal"><span class="pre">key</span> <span class="pre">"viewport_wheeldown"</span> <span class="pre">action</span> <span class="pre">Return()</span></code> before the viewport
+will cause the screen to return if the viewport scrolls past the
+bottom.)</dd>
+<dt>"horizontal-change"</dt>
+<dd>Combines horizontal scrolling with change mode.</dd>
+</dl>
+</dd>
 <dt><cite>draggable</cite></dt>
 <dd>If True, dragging the mouse will scroll the viewport.</dd>
 <dt><cite>edgescroll</cite></dt>
diff --git a/doc/search.html b/doc/search.html
index ede5e3d..0db2745 100644
--- a/doc/search.html
+++ b/doc/search.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -57,7 +57,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -153,6 +153,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/searchindex.js b/doc/searchindex.js
index 0508429..6c7f2e5 100644
--- a/doc/searchindex.js
+++ b/doc/searchindex.js
@@ -1 +1 @@
-Search.setIndex({envversion:47,filenames:["achievement","android","android-packaging","atl","audio","build","cds","changelog","character_callbacks","chromeos","color_class","conditional","config","credits","custom_text_tags","developer_tools","dialogue","display_problems","displayables","displaying_images","distributor","drag_drop","editor","environment_variables","file_python","gesture","gui","history","iap","incompatible","index","input","ios","keymap","label","language_basics","licens [...]
\ No newline at end of file
+Search.setIndex({envversion:47,filenames:["achievement","android","android-packaging","atl","audio","build","cds","changelog","character_callbacks","chromeos","color_class","conditional","config","credits","custom_text_tags","developer_tools","dialogue","display_problems","displayables","displaying_images","distributor","drag_drop","editor","environment_variables","file_python","gesture","gui","history","iap","incompatible","index","input","ios","keymap","label","language_basics","licens [...]
\ No newline at end of file
diff --git a/doc/self_voicing.html b/doc/self_voicing.html
index 717af8e..c137892 100644
--- a/doc/self_voicing.html
+++ b/doc/self_voicing.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/side_image.html b/doc/side_image.html
index 6b62afe..22de9ba 100644
--- a/doc/side_image.html
+++ b/doc/side_image.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/skins.html b/doc/skins.html
index d9491e2..1bd8c3f 100644
--- a/doc/skins.html
+++ b/doc/skins.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -30,7 +30,7 @@
     <script type="text/javascript" src="_static/bootstrap-3.3.6/js/bootstrap.min.js"></script>
     <script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
     <link rel="top" title="Ren'Py Documentation" href="index.html" />
-    <link rel="next" title="Full Changelog" href="changelog.html" />
+    <link rel="next" title="Translating Ren'Py" href="translating_renpy.html" />
     <link rel="prev" title="Text Editor Integration" href="editor.html" />
 <meta charset='utf-8'>
 <meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1 current"><a class="current reference internal" href="#">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/sprites.html b/doc/sprites.html
index 6508911..2f45ace 100644
--- a/doc/sprites.html
+++ b/doc/sprites.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/statement_equivalents.html b/doc/statement_equivalents.html
index 3cf4ad6..3162a14 100644
--- a/doc/statement_equivalents.html
+++ b/doc/statement_equivalents.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/std-style-property-index.html b/doc/std-style-property-index.html
index 7476040..a24073a 100644
--- a/doc/std-style-property-index.html
+++ b/doc/std-style-property-index.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -52,7 +52,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -148,6 +148,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/std-transform-property-index.html b/doc/std-transform-property-index.html
index 4fd10e5..fb34fa8 100644
--- a/doc/std-transform-property-index.html
+++ b/doc/std-transform-property-index.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -52,7 +52,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -148,6 +148,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/std-var-index.html b/doc/std-var-index.html
index 1559351..a286a3c 100644
--- a/doc/std-var-index.html
+++ b/doc/std-var-index.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -52,7 +52,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -148,6 +148,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -317,6 +318,11 @@
      <tr>
        <td></td>
        <td>
+       <a href="config.html#var-config.afm_voice_delay"><code class="xref">config.afm_voice_delay</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
        <a href="config.html#var-config.after_load_callbacks"><code class="xref">config.after_load_callbacks</code></a></td><td>
        <em></em></td></tr>
      <tr>
@@ -1334,6 +1340,26 @@
      <tr>
        <td></td>
        <td>
+       <a href="translating_renpy.html#var-gui.FONT_SCALE"><code class="xref">gui.FONT_SCALE</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="translating_renpy.html#var-gui.LIGHT_FONT"><code class="xref">gui.LIGHT_FONT</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="translating_renpy.html#var-gui.REGULAR_BOLD"><code class="xref">gui.REGULAR_BOLD</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="translating_renpy.html#var-gui.REGULAR_FONT"><code class="xref">gui.REGULAR_FONT</code></a></td><td>
+       <em></em></td></tr>
+     <tr>
+       <td></td>
+       <td>
        <a href="gui.html#var-gui.accent_color"><code class="xref">gui.accent_color</code></a></td><td>
        <em></em></td></tr>
      <tr>
diff --git a/doc/store_variables.html b/doc/store_variables.html
index cb6243c..16c4374 100644
--- a/doc/store_variables.html
+++ b/doc/store_variables.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/style.html b/doc/style.html
index 614e461..a2d8d3d 100644
--- a/doc/style.html
+++ b/doc/style.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/style_properties.html b/doc/style_properties.html
index 4c94982..397931d 100644
--- a/doc/style_properties.html
+++ b/doc/style_properties.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/text.html b/doc/text.html
index 15e882a..f6a4b1d 100644
--- a/doc/text.html
+++ b/doc/text.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/thequestion.html b/doc/thequestion.html
index 6641397..84bbf46 100644
--- a/doc/thequestion.html
+++ b/doc/thequestion.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/thequestion_nvl.html b/doc/thequestion_nvl.html
index 4ed727f..8ed5339 100644
--- a/doc/thequestion_nvl.html
+++ b/doc/thequestion_nvl.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -50,7 +50,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -146,6 +146,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/trans_trans_python.html b/doc/trans_trans_python.html
index ecac01c..2eb2fb0 100644
--- a/doc/trans_trans_python.html
+++ b/doc/trans_trans_python.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/transforms.html b/doc/transforms.html
index bd79901..6559e8d 100644
--- a/doc/transforms.html
+++ b/doc/transforms.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/transitions.html b/doc/transitions.html
index 586914e..7d74a30 100644
--- a/doc/transitions.html
+++ b/doc/transitions.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -668,7 +669,7 @@ direction indicated.</dd>
 related transitions.</p>
 <dl class="function">
 <dt id="define.move_transitions">
-<code class="descclassname">define.</code><code class="descname">move_transitions</code><span class="sig-paren">(</span><em>prefix, delay, time_warp=None, in_time_warp=None, out_time_warp=None, old=False, layers=['master'], **kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#define.move_transitions" title="Permalink to this definition"> link</a></dt>
+<code class="descclassname">define.</code><code class="descname">move_transitions</code><span class="sig-paren">(</span><em>prefix, delay, time_warp=None, in_time_warp=None, out_time_warp=None, old=False, layers=[u'master'], **kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#define.move_transitions" title="Permalink to this definition"> link</a></dt>
 <dd><p>This defines a family of move transitions, similar to the move and ease
 transitions. For a given <cite>prefix</cite>, this defines the transitions:</p>
 <ul class="simple">
diff --git a/doc/updater.html b/doc/translating_renpy.html
similarity index 54%
copy from doc/updater.html
copy to doc/translating_renpy.html
index d432d2f..b3a1a01 100644
--- a/doc/updater.html
+++ b/doc/translating_renpy.html
@@ -5,7 +5,7 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     
-    <title>Web Updater — Ren'Py Documentation</title>
+    <title>Translating Ren'Py — Ren'Py Documentation</title>
     
     <link rel="stylesheet" href="_static/renpydoc.css" type="text/css" />
     <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -30,8 +30,8 @@
     <script type="text/javascript" src="_static/bootstrap-3.3.6/js/bootstrap.min.js"></script>
     <script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
     <link rel="top" title="Ren'Py Documentation" href="index.html" />
-    <link rel="next" title="Android" href="android.html" />
-    <link rel="prev" title="Building Distributions" href="build.html" />
+    <link rel="next" title="Full Changelog" href="changelog.html" />
+    <link rel="prev" title="Skins" href="skins.html" />
 <meta charset='utf-8'>
 <meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
 <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -130,9 +130,9 @@
 <li class="toctree-l1"><a class="reference internal" href="color_class.html">Color Class</a></li>
 <li class="toctree-l1"><a class="reference internal" href="other.html">Other Functions and Variables</a></li>
 </ul>
-<ul class="current">
+<ul>
 <li class="toctree-l1"><a class="reference internal" href="build.html">Building Distributions</a></li>
-<li class="toctree-l1 current"><a class="current reference internal" href="#">Web Updater</a></li>
+<li class="toctree-l1"><a class="reference internal" href="updater.html">Web Updater</a></li>
 <li class="toctree-l1"><a class="reference internal" href="android.html">Android</a></li>
 <li class="toctree-l1"><a class="reference internal" href="chromeos.html">Chrome OS / Chrome Browser</a></li>
 <li class="toctree-l1"><a class="reference internal" href="ios.html">iOS</a></li>
@@ -144,9 +144,10 @@
 <li class="toctree-l1"><a class="reference internal" href="environment_variables.html">Environment Variables</a></li>
 <li class="toctree-l1"><a class="reference internal" href="self_voicing.html">Self Voicing</a></li>
 </ul>
-<ul>
+<ul class="current">
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1 current"><a class="current reference internal" href="#">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -187,11 +188,11 @@
   <div class="row">
       <div class="col-md-3">
         <div id="sidebar" class="bs-sidenav" role="complementary"><ul>
-<li><a class="reference internal" href="#">Web Updater</a><ul>
-<li><a class="reference internal" href="#server-requirements">Server Requirements</a></li>
-<li><a class="reference internal" href="#building-an-update">Building an Update</a></li>
+<li><a class="reference internal" href="#">Translating Ren'Py</a><ul>
+<li><a class="reference internal" href="#translation-files">Translation Files</a></li>
+<li><a class="reference internal" href="#changing-fonts">Changing Fonts</a></li>
+<li><a class="reference internal" href="#changing-the-launcher-style">Changing the Launcher Style</a></li>
 <li><a class="reference internal" href="#functions">Functions</a></li>
-<li><a class="reference internal" href="#screen">Screen</a></li>
 </ul>
 </li>
 </ul>
@@ -200,153 +201,162 @@
       </div>
     <div class="col-md-9 content">
       
-  <div class="section" id="web-updater">
-<h1>Web Updater<a class="headerlink" href="#web-updater" title="Permalink to this headline"> link</a></h1>
-<p>Ren'Py includes an updater that can automatically download and install
-updates to a Ren'Py game hosted at a website. This can be useful in
-keeping a large game up to date.</p>
-<p>The Ren'Py updater works by automatically performing the following
-steps:</p>
+  <div class="section" id="translating-ren-py">
+<span id="translating-renpy"></span><h1>Translating Ren'Py<a class="headerlink" href="#translating-ren-py" title="Permalink to this headline"> link</a></h1>
+<p>It is possible to translate Ren'Py itself. A complete translation translates
+the GUI, various Ren'Py messages, new projects, and the launcher. This should
+cover most gameplay and development scenarios. Right now, not every error
+message can be translated.</p>
+<p>To create a new translation:</p>
 <ol class="arabic simple">
-<li>Downloading an index file that controls what is updated.</li>
-<li>Asking the user if he or she wants to proceed with the update.</li>
-<li>Producing an archive file from the files on disk.</li>
-<li>Downloading a zsync control file from the server.</li>
-<li>Using the zsync tool to update the archive file to the version on
-the server. Zsync automatically computes the differences between
-the two files, and attempts to only download the portions that
-have changed.</li>
-<li>Unpacking the archive, replacing the files on disk.</li>
-<li>Deleting files that have been removed between the old and new
-versions.</li>
-<li>Restarting the game.</li>
+<li>Open the Ren'PY launcher.</li>
+<li>On the preferences page, choose "Open launcher project".</li>
+<li>Choose "Generate Translations."</li>
+<li>Enter the name of the language to translate to. This should consist of
+lower-case ASCII characters and underscores, so "japanese", "russian",
+or "ancient_klingon" are all valid language names.</li>
+<li>Choose "Generate Translations."</li>
 </ol>
-<p>The Ren'Py updater shows an updater screen during this process,
-prompting the user to proceed and allowing the user to cancel
-when appropriate.</p>
-<div class="section" id="server-requirements">
-<h2>Server Requirements<a class="headerlink" href="#server-requirements" title="Permalink to this headline"> link</a></h2>
-<p>The updater requires that you provide your own hosting. You should be
-able to download the update files by going to the appropriate URL
-directly, and your server must support HTTP range queries.</p>
-<p>(This means paying for web hosting, as "sharing" sites tend not to
-support the required features.)</p>
-</div>
-<div class="section" id="building-an-update">
-<h2>Building an Update<a class="headerlink" href="#building-an-update" title="Permalink to this headline"> link</a></h2>
-<p>Updates are built automatically when distributions are built. To build
-an update, set build.include_update to True in options.rpy. This will
-unlock the "Build Updates" option in the "Build Distributions" section
-of the launcher. Check this option, and Ren'Py will create the update
+<p>The same procedure can be used to update a language translation. To access
+the created translation, return to the preferences, then choose the newly
+created language. Note that by default, the translation will be a copy of
+the English translation.</p>
+<div class="section" id="translation-files">
+<h2>Translation Files<a class="headerlink" href="#translation-files" title="Permalink to this headline"> link</a></h2>
+<p>The translation files live in launcher/game/tl/<cite>language</cite>/. With the
+exception of script.rpy, all files consist of string translations that
+can be translated using the <a class="reference internal" href="translation.html#string-translations"><span class="std std-ref">string translation</span></a>
+syntax. Some strings might begin with "## ". These are comments that
+are translated, wrapped, and included in the options.rpy and gui.rpy
 files.</p>
-<p>The update files consist of:</p>
+<p>The translation files are:</p>
 <dl class="docutils">
-<dt>updates.json</dt>
-<dd>An index of available updates and their versions.</dd>
-<dt><em>package</em>.sums</dt>
-<dd>Contains checksums for each block in the package.</dd>
-<dt><em>package</em>.update.gz</dt>
-<dd>Contains the update data for the given package.</dd>
-<dt><em>package</em>.update.json</dt>
-<dd>Contains a list of the files in each package, which the updater
-uses when downloading DLC.</dd>
-<dt><em>package</em>.zsync</dt>
-<dd>This is a control file that's used by zsync to manage the download.</dd>
+<dt>common.rpy</dt>
+<dd>This file contains interface messages (strings) that Ren'Py may present to the
+player.</dd>
+<dt>developer.rpy</dt>
+<dd>This file contains strings that are only of interest to creators,
+and not players.</dd>
+<dt>error.rpy</dt>
+<dd>This file contains strings that are displayed to the developer or player
+when Ren'Py has a problem.</dd>
+<dt>gui.rpy</dt>
+<dd>This file contains comments that are placed into the default GUI code.</dd>
+<dt>launcher.rpy</dt>
+<dd>This file contains strings that are displayed as part of the launcher.</dd>
+<dt>obsolete.rpy</dt>
+<dd>The file contains strings that are not used by modern Ren'Py code.</dd>
+<dt>options.rpy</dt>
+<dd>This file contains strings that are used to translate the comments in
+the default options.rpy file.</dd>
+<dt>screens.rpy</dt>
+<dd>This file contains strings that are used by the default gui, and the
+comments in the default screens.rpy file.</dd>
+<dt>script.rpym</dt>
+<dd>The contents of this file are copied, verbatim, into script.rpy
+when a new project is created.</dd>
+<dt>style.rpy</dt>
+<dd>This file does not exist by default, but should be created when needed.
+It configures the launcher styles, and the font that is used by a
+generated game.</dd>
 </dl>
-<p>You must upload all these files to a single directory on your web
-server.</p>
 </div>
-<div class="section" id="functions">
-<h2>Functions<a class="headerlink" href="#functions" title="Permalink to this headline"> link</a></h2>
-<p>To cause an update to occur, invoke either updater.update or the
-updater.Update action.</p>
-<dl class="function">
-<dt id="updater.Update">
-<code class="descclassname">updater.</code><code class="descname">Update</code><span class="sig-paren">(</span><em>*args</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#updater.Update" title="Permalink to this definition"> link</a></dt>
-<dd><p>An action that calls <a class="reference internal" href="#updater.update" title="updater.update"><code class="xref py py-func docutils literal"><span class="pre">updater.update()</span></code></a>. All arguments are
-stored and passed to that function.</p>
+<div class="section" id="changing-fonts">
+<h2>Changing Fonts<a class="headerlink" href="#changing-fonts" title="Permalink to this headline"> link</a></h2>
+<p>Ren'Py ships with a default font (DejaVuSans) that covers most western
+languages, but other fonts are often needed. A font can be configured by
+editing launcher/game/tl/language/style.rpy, and adding the code:</p>
+<div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="k">init</span> <span class="k">python</span><span class="p">:</span>
+    <span class="n">translate_font</span><span class="p">(</span><span class="s2">"language"</span><span class="p">,</span> <span class="s2">"myfont.ttf"</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Where "language" is the language in question (for example, "japanese"), and
+"myfont.ttf" is the font that should be used (for example, "MTLc3m.ttf").
+The font file should be placed in the launcher/game/tl/language directory,
+so it can be found by the launcher.</p>
+</div>
+<div class="section" id="changing-the-launcher-style">
+<h2>Changing the Launcher Style<a class="headerlink" href="#changing-the-launcher-style" title="Permalink to this headline"> link</a></h2>
+<p>The styles used by the launcher can be configured by setting variables
+in a translate python block. The following variables are available. The
+names are a bit confusing, as they reflect the English-language translation.</p>
+<p>These variables are only available in the launcher.</p>
+<dl class="var">
+<dt id="var-gui.LIGHT_FONT">
+define <code class="descname">gui.LIGHT_FONT</code> = "Roboto-Light.ttf"<a class="headerlink" href="#var-gui.LIGHT_FONT" title="Permalink to this definition"> link</a></dt>
+<dd><p>The path to the font used for normal text in the launcher.</p>
 </dd></dl>
 
-<dl class="function">
-<dt id="updater.UpdateVersion">
-<code class="descclassname">updater.</code><code class="descname">UpdateVersion</code><span class="sig-paren">(</span><em>url</em>, <em>check_interval=21600</em>, <em>simulate=None</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#updater.UpdateVersion" title="Permalink to this definition"> link</a></dt>
-<dd><p>This function contacts the server at <cite>url</cite>, and determines if there is
-a newer version of software available at that url. If there is, this
-function returns the new version. Otherwise, it returns None.</p>
-<p>Since contacting the server can take some time, this function launches
-a thread in the background, and immediately returns the version from
-the last time the server was contacted, or None if the server has never
-been contacted. The background thread will restart the current interaction
-once the server has been contacted, which will cause screens that call
-this function to update.</p>
-<p>Each url will be contacted at most once per Ren'Py session, and not
-more than once every <cite>check_interval</cite> seconds. When the server is not
-contacted, cached data will be returned.</p>
-<p>Additional keyword arguments (including <cite>simulate</cite>) are passed to the
-update mechanism as if they were given to <a class="reference internal" href="#updater.update" title="updater.update"><code class="xref py py-func docutils literal"><span class="pre">updater.update()</span></code></a>.</p>
+<dl class="var">
+<dt id="var-gui.REGULAR_FONT">
+define <code class="descname">gui.REGULAR_FONT</code> = "Roboto-Regular.ttf"<a class="headerlink" href="#var-gui.REGULAR_FONT" title="Permalink to this definition"> link</a></dt>
+<dd><p>The path to the font used for heavy-weight text in the launcher.</p>
 </dd></dl>
 
-<dl class="function">
-<dt id="updater.can_update">
-<code class="descclassname">updater.</code><code class="descname">can_update</code><span class="sig-paren">(</span><em>base=None</em><span class="sig-paren">)</span><a class="headerlink" href="#updater.can_update" title="Permalink to this definition"> link</a></dt>
-<dd><p>Returns true if it's possible that an update can succeed. Returns false
-if updating is totally impossible. (For example, if the update directory
-was deleted.)</p>
-<p>Note that this does not determine if an update is actually available.
-To do that, use <a class="reference internal" href="#updater.UpdateVersion" title="updater.UpdateVersion"><code class="xref py py-func docutils literal"><span class="pre">updater.UpdateVersion()</span></code></a>.</p>
+<dl class="var">
+<dt id="var-gui.REGULAR_BOLD">
+define <code class="descname">gui.REGULAR_BOLD</code> = False<a class="headerlink" href="#var-gui.REGULAR_BOLD" title="Permalink to this definition"> link</a></dt>
+<dd><p>If true, heavy-weight text is bolded.</p>
+</dd></dl>
+
+<dl class="var">
+<dt id="var-gui.FONT_SCALE">
+define <code class="descname">gui.FONT_SCALE</code> = 1.0<a class="headerlink" href="#var-gui.FONT_SCALE" title="Permalink to this definition"> link</a></dt>
+<dd><p>A scaling factor that is applied to all text in the launcher.</p>
 </dd></dl>
 
+<p>A translate python block is used to set these variables. For example, the
+following code is used to change the fonts in the Arabic translation of
+Ren'Py:</p>
+<div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="k">translate</span> <span class="n">arabic</span> <span class="k">python</span><span class="p">:</span>
+    <span class="n">gui</span><span class="o">.</span><span class="n">REGULAR_FONT</span> <span class="o">=</span> <span class="s2">"DejaVuSans.ttf"</span>
+    <span class="n">gui</span><span class="o">.</span><span class="n">LIGHT_FONT</span> <span class="o">=</span> <span class="s2">"DejaVuSans.ttf"</span>
+    <span class="n">gui</span><span class="o">.</span><span class="n">FONT_SCALE</span> <span class="o">=</span> <span class="o">.</span><span class="mi">9</span>
+    <span class="n">gui</span><span class="o">.</span><span class="n">REGULAR_BOLD</span> <span class="o">=</span> <span class="bp">True</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="functions">
+<h2>Functions<a class="headerlink" href="#functions" title="Permalink to this headline"> link</a></h2>
+<p>The following functions are used to configure translation in the launcher.
+They should be called from the init python block.</p>
 <dl class="function">
-<dt id="updater.get_installed_packages">
-<code class="descclassname">updater.</code><code class="descname">get_installed_packages</code><span class="sig-paren">(</span><em>base=None</em><span class="sig-paren">)</span><a class="headerlink" href="#updater.get_installed_packages" title="Permalink to this definition"> link</a></dt>
-<dd><p>Returns a list of installed DLC package names.</p>
+<dt id="translate_font">
+<code class="descname">translate_font</code><span class="sig-paren">(</span><em>language</em>, <em>font</em>, <em>prefix=None</em><span class="sig-paren">)</span><a class="headerlink" href="#translate_font" title="Permalink to this definition"> link</a></dt>
+<dd><p>This is used to set a font for <cite>language</cite>. The font is used in the
+launcher, and also used to in games generated in that language.</p>
 <dl class="docutils">
-<dt><cite>base</cite></dt>
-<dd>The base directory to update. Defaults to the current project's
-base directory.</dd>
+<dt><cite>font</cite></dt>
+<dd>A string giving the name of the font file.</dd>
+<dt><cite>prefix</cite></dt>
+<dd>The path to the font file (not including the font itself), relative
+to the launcher game directory. If not given, tl/<cite>language</cite> is used.</dd>
 </dl>
 </dd></dl>
 
 <dl class="function">
-<dt id="updater.update">
-<code class="descclassname">updater.</code><code class="descname">update</code><span class="sig-paren">(</span><em>url</em>, <em>base=None</em>, <em>force=False</em>, <em>public_key=None</em>, <em>simulate=None</em>, <em>add=[]</em>, <em>restart=True</em><span class="sig-paren">)</span><a class="headerlink" href="#updater.update" title="Permalink to this definition"> link</a></dt>
-<dd><p>Updates this Ren'Py game to the latest version.</p>
+<dt id="translate_define">
+<code class="descname">translate_define</code><span class="sig-paren">(</span><em>language</em>, <em>define</em>, <em>value</em>, <em>help=None</em><span class="sig-paren">)</span><a class="headerlink" href="#translate_define" title="Permalink to this definition"> link</a></dt>
+<dd><p>This is used to set a define when generating a game. For example, it can
+be used to change the size of a font.</p>
 <dl class="docutils">
-<dt><cite>url</cite></dt>
-<dd>The URL to the updates.json file.</dd>
-<dt><cite>base</cite></dt>
-<dd>The base directory that will be updated. Defaults to the base
-of the current game. (This can usually be ignored.)</dd>
-<dt><cite>force</cite></dt>
-<dd>Force the update to occur even if the version numbers are
-the same. (Used for testing.)</dd>
-<dt><cite>public_key</cite></dt>
-<dd>The path to a PEM file containing a public key that the
-update signature is checked against. (This can usually be ignored.)</dd>
-<dt><cite>simulate</cite></dt>
-<dd><p class="first">This is used to test update guis without actually performing
-an update. This can be:</p>
-<ul class="last simple">
-<li>None to perform an update.</li>
-<li>"available" to test the case where an update is available.</li>
-<li>"not_available" to test the case where no update is available.</li>
-<li>"error" to test an update error.</li>
-</ul>
-</dd>
-<dt><cite>add</cite></dt>
-<dd>A list of packages to add during this update. This is only necessary
-for dlc.</dd>
-<dt><cite>restart</cite></dt>
-<dd>Restart the game after the update.</dd>
+<dt><cite>language</cite></dt>
+<dd>The language involved.</dd>
+<dt><cite>define</cite></dt>
+<dd>The name of the define.</dd>
+<dt><cite>value</cite></dt>
+<dd>A string giving the value the define should be set to. (ie. "10",
+"False", or "'Font.ttf'").</dd>
+<dt><cite>help</cite></dt>
+<dd>If not None, help text that is placed before the define.</dd>
 </dl>
+<p>For example, the following code changes the size of dialogue text:</p>
+<div class="highlight-renpy"><div class="highlight"><pre><span></span><span class="n">translate_define</span><span class="p">(</span><span class="s2">"martian"</span><span class="p">,</span> <span class="s2">"gui.text_size"</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span>
+</pre></div>
+</div>
 </dd></dl>
 
 </div>
-<div class="section" id="screen">
-<h2>Screen<a class="headerlink" href="#screen" title="Permalink to this headline"> link</a></h2>
-<p>To customize the look of the updater, you may override the <code class="docutils literal"><span class="pre">updater</span></code>
-screen. The default screen is defined in common/00updater.rpy.</p>
-</div>
 </div>
 
 
diff --git a/doc/translation.html b/doc/translation.html
index ebfd0ff..0059f1d 100644
--- a/doc/translation.html
+++ b/doc/translation.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -415,7 +416,7 @@ side effects to occur multiple times.</p>
 </div>
 </div>
 <div class="section" id="menu-and-string-translations">
-<h2>Menu and String Translations<a class="headerlink" href="#menu-and-string-translations" title="Permalink to this headline"> link</a></h2>
+<span id="string-translations"></span><h2>Menu and String Translations<a class="headerlink" href="#menu-and-string-translations" title="Permalink to this headline"> link</a></h2>
 <p>In addition to dialogue, Ren'Py is able to translate text found in
 menus and other strings. Interface translations are a 1-to-1
 substitution. Wherever a string is found, it will be replaced by a
diff --git a/doc/udd.html b/doc/udd.html
index 22df207..18ea5e7 100644
--- a/doc/udd.html
+++ b/doc/udd.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/updater.html b/doc/updater.html
index d432d2f..b7607b8 100644
--- a/doc/updater.html
+++ b/doc/updater.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
diff --git a/doc/voice.html b/doc/voice.html
index 3f3d80c..4c353bb 100644
--- a/doc/voice.html
+++ b/doc/voice.html
@@ -16,7 +16,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    './',
-        VERSION:     '6.99.11',
+        VERSION:     '6.99.12',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -51,7 +51,7 @@
         </button>
         <a class="navbar-brand" href="index.html">
           Ren'Py Documentation</a>
-        <span class="navbar-text navbar-version pull-left"><b>6.99.11</b></span>
+        <span class="navbar-text navbar-version pull-left"><b>6.99.12</b></span>
       </div>
 
         <div class="collapse navbar-collapse nav-collapse">
@@ -147,6 +147,7 @@
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="editor.html">Text Editor Integration</a></li>
 <li class="toctree-l1"><a class="reference internal" href="skins.html">Skins</a></li>
+<li class="toctree-l1"><a class="reference internal" href="translating_renpy.html">Translating Ren'Py</a></li>
 </ul>
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="changelog.html">Full Changelog</a></li>
@@ -343,7 +344,7 @@ voices of particular characters.</p>
 
 <dl class="function">
 <dt id="voice_sustain">
-<code class="descname">voice_sustain</code><span class="sig-paren">(</span><em>ignored=''</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#voice_sustain" title="Permalink to this definition"> link</a></dt>
+<code class="descname">voice_sustain</code><span class="sig-paren">(</span><em>ignored=u''</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#voice_sustain" title="Permalink to this definition"> link</a></dt>
 <dd><p>The equivalent of the voice sustain statement.</p>
 </dd></dl>
 
diff --git a/gui/game/gui.rpy b/gui/game/gui.rpy
index 18e3ede..c1cf540 100644
--- a/gui/game/gui.rpy
+++ b/gui/game/gui.rpy
@@ -14,7 +14,7 @@ init python:
 
 
 ################################################################################
-# GUI Configuration Variables
+## GUI Configuration Variables
 ################################################################################
 
 
@@ -165,14 +165,14 @@ define gui.button_text_font = gui.interface_font
 ## The size of the text used by the button.
 define gui.button_text_size = gui.interface_text_size
 
-# The color of button text in various states.
+## The color of button text in various states.
 define gui.button_text_idle_color = gui.idle_color
 define gui.button_text_hover_color = gui.hover_color
 define gui.button_text_selected_color = gui.selected_color
 define gui.button_text_insensitive_color = gui.insensitive_color
 
-# The horizontal alignment of the button text. (0.0 is left, 0.5 is center,
-# 1.0 is right).
+## The horizontal alignment of the button text. (0.0 is left, 0.5 is center,
+## 1.0 is right).
 define gui.button_text_xalign = 0.0
 
 
@@ -392,10 +392,17 @@ define gui.nvl_thought_xalign = 0.0
 define gui.nvl_button_xpos = gui.scale(450)
 define gui.nvl_button_xalign = 0.0
 
+## Localization ################################################################
+
+## This controls where a line break is permitted. The default is suitable for
+## most languages. A list of available values can be found at
+## https://www.renpy.org/doc/html/style_properties.html#style-property-language
+
+define gui.language = "unicode"
 
 
 ################################################################################
-# Mobile devices
+## Mobile devices
 ################################################################################
 
 init python:
@@ -404,7 +411,7 @@ init python:
     ## touch on tablets and phones.
     if renpy.variant("touch"):
 
-        gui.quick_button_borders = Borders(gui.scale(60), gui.scale(14), gui.scale(60), gui.scale(0))
+        gui.quick_button_borders = Borders(gui.scale(40), gui.scale(14), gui.scale(40), gui.scale(0))
 
     ## This changes the size and spacing of various GUI elements to ensure
     ## they are easily visible on phones.
diff --git a/gui/game/options.rpy b/gui/game/options.rpy
index 36b9711..deced86 100644
--- a/gui/game/options.rpy
+++ b/gui/game/options.rpy
@@ -143,8 +143,8 @@ default preferences.afm_time = 15
 define config.save_directory = "gui-7"
 
 
-## Icon ########################################################################'
-
+## Icon ########################################################################
+##
 ## The icon displayed on the taskbar or dock.
 
 define config.window_icon = "gui/window_icon.png"
diff --git a/gui/game/screens.rpy b/gui/game/screens.rpy
index 0e72927..6874f1b 100644
--- a/gui/game/screens.rpy
+++ b/gui/game/screens.rpy
@@ -13,6 +13,7 @@ style default:
     font gui.default_font
     size gui.text_size
     color gui.text_color
+    language gui.language
 
 style input:
     color gui.accent_color
@@ -107,16 +108,17 @@ screen say(who, what):
     window:
         id "window"
 
-        text what id "what"
-
         if who is not None:
 
             window:
                 style "namebox"
                 text who id "who"
 
-    # If there's a side image, display it above the text. Do not display
-    # on the phone variant - there's no room.
+        text what id "what"
+
+
+    ## If there's a side image, display it above the text. Do not display
+    ## on the phone variant - there's no room.
     if not renpy.variant("small"):
         add SideImage() xalign 0.0 yalign 1.0
 
@@ -247,24 +249,25 @@ style choice_button_text is default:
 
 screen quick_menu():
 
-    # Ensure this appears on top of other screens.
+    ## Ensure this appears on top of other screens.
     zorder 100
 
-    # Add an in-game quick menu.
-    hbox:
-        style_prefix "quick"
+    if quick_menu:
 
-        xalign 0.5
-        yalign 1.0
+        hbox:
+            style_prefix "quick"
 
-        textbutton _("Back") action Rollback()
-        textbutton _("History") action ShowMenu('history')
-        textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
-        textbutton _("Auto") action Preference("auto-forward", "toggle")
-        textbutton _("Save") action ShowMenu('save')
-        textbutton _("Q.Save") action QuickSave()
-        textbutton _("Q.Load") action QuickLoad()
-        textbutton _("Prefs") action ShowMenu('preferences')
+            xalign 0.5
+            yalign 1.0
+
+            textbutton _("Back") action Rollback()
+            textbutton _("History") action ShowMenu('history')
+            textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
+            textbutton _("Auto") action Preference("auto-forward", "toggle")
+            textbutton _("Save") action ShowMenu('save')
+            textbutton _("Q.Save") action QuickSave()
+            textbutton _("Q.Load") action QuickLoad()
+            textbutton _("Prefs") action ShowMenu('preferences')
 
 
 ## This code ensures that the quick_menu screen is displayed in-game, whenever
@@ -272,6 +275,7 @@ screen quick_menu():
 init python:
     config.overlay_screens.append("quick_menu")
 
+default quick_menu = True
 
 style quick_button is default
 style quick_button_text is button_text
@@ -284,7 +288,7 @@ style quick_button_text:
 
 
 ################################################################################
-# Main and Game Menu Screens
+## Main and Game Menu Screens
 ################################################################################
 
 ## Navigation screen ###########################################################
@@ -354,14 +358,14 @@ style navigation_button_text:
 
 screen main_menu():
 
-    # This ensures that any other menu screen is replaced.
+    ## This ensures that any other menu screen is replaced.
     tag menu
 
     style_prefix "main_menu"
 
     add gui.main_menu_background
 
-    # This empty frame darkens the main menu.
+    ## This empty frame darkens the main menu.
     frame:
         pass
 
@@ -420,20 +424,19 @@ style main_menu_title:
 
 screen game_menu(title, scroll=None):
 
-    # Add the backgrounds.
+    style_prefix "game_menu"
+
     if main_menu:
         add gui.main_menu_background
     else:
         add gui.game_menu_background
 
-    style_prefix "game_menu"
-
     frame:
         style "game_menu_outer_frame"
 
         hbox:
 
-            # Reserve space for the navigation section.
+            ## Reserve space for the navigation section.
             frame:
                 style "game_menu_navigation_frame"
 
@@ -603,7 +606,7 @@ screen load():
 
 screen file_slots(title):
 
-    default page_name_value = FilePageNameInputValue()
+    default page_name_value = FilePageNameInputValue(pattern=_("Page {}"), auto=_("Automatic saves"), quick=_("Quick saves"))
 
     use game_menu(title):
 
@@ -613,7 +616,7 @@ screen file_slots(title):
             ## event before any of the buttons do.
             order_reverse True
 
-            # The page name, which can be edited by clicking on a button.
+            ## The page name, which can be edited by clicking on a button.
             button:
                 style "page_label"
 
@@ -668,7 +671,7 @@ screen file_slots(title):
 
                 textbutton _("{#quick_page}Q") action FilePage("quick")
 
-                # range(1, 10) gives the numbers from 1 to 9.
+                ## range(1, 10) gives the numbers from 1 to 9.
                 for page in range(1, 10):
                     textbutton "[page]" action FilePage(page)
 
@@ -1070,15 +1073,15 @@ screen gamepad_help():
 
     hbox:
         label _("Right Trigger\nA/Bottom Button")
-        text _("Advance dialogue and activates the interface.")
+        text _("Advances dialogue and activates the interface.")
 
     hbox:
-        label ("Left Trigger\nLeft Shoulder")
-        text _("Roll back to earlier dialogue.")
+        label _("Left Trigger\nLeft Shoulder")
+        text _("Rolls back to earlier dialogue.")
 
     hbox:
         label _("Right Shoulder")
-        text _("Roll forward to later dialogue.")
+        text _("Rolls forward to later dialogue.")
 
     hbox:
         label _("D-Pad, Sticks")
@@ -1086,7 +1089,7 @@ screen gamepad_help():
 
     hbox:
         label _("Start, Guide")
-        text _("Access the game menu.")
+        text _("Accesses the game menu.")
 
     hbox:
         label _("Y/Top Button")
@@ -1422,9 +1425,10 @@ screen quick_menu():
         xalign 0.5
         yalign 1.0
 
+        textbutton _("Back") action Rollback()
         textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
-        textbutton _("Menu") action ShowMenu()
         textbutton _("Auto") action Preference("auto-forward", "toggle")
+        textbutton _("Menu") action ShowMenu()
 
 
 style window:
diff --git a/gui/game/script.rpy b/gui/game/script.rpy
index 8bec067..9d2a51c 100644
--- a/gui/game/script.rpy
+++ b/gui/game/script.rpy
@@ -1,28 +1,28 @@
-## The script of the game goes in this file.
+# The script of the game goes in this file.
 
-## Declare characters used by this game. The color argument colorizes the
-## name of the character.
+# Declare characters used by this game. The color argument colorizes the
+# name of the character.
 
-define e = Character('Eileen')
+define e = Character("Eileen")
 
 
-## The game starts here.
+# The game starts here.
 
 label start:
 
-    ## Show a background. This uses a placeholder by default, but you can
-    ## add a file (named either "bg room.png" or "bg room.jpg") to the
-    ## images directory to show it.
+    # Show a background. This uses a placeholder by default, but you can
+    # add a file (named either "bg room.png" or "bg room.jpg") to the
+    # images directory to show it.
 
     scene bg room
 
-    ## This shows a character sprite. A placeholder is used, but you can
-    ## replace it by adding a file named "eileen happy.png" to the images
-    ## directory.
+    # This shows a character sprite. A placeholder is used, but you can
+    # replace it by adding a file named "eileen happy.png" to the images
+    # directory.
 
     show eileen happy
 
-    ## These display lines of dialogue.
+    # These display lines of dialogue.
 
     "Hello, world."
 
@@ -30,6 +30,6 @@ label start:
 
     e "Once you add a story, pictures, and music, you can release it to the world!"
 
-    ## This ends the game.
+    # This ends the game.
 
     return
diff --git a/gui/game/testcases.rpy b/gui/game/testcases.rpy
new file mode 100644
index 0000000..6eec065
--- /dev/null
+++ b/gui/game/testcases.rpy
@@ -0,0 +1,14 @@
+testcase default:
+
+    "Start"
+    pause .6
+
+    # Test rollback
+    "Hello, World."
+    "Back"
+
+    # Test history.
+    click
+    click
+    "History"
+
diff --git a/launcher/game/EasyDialogsWin.py b/launcher/game/EasyDialogsWin.py
index aea17ed..8b2e48f 100644
--- a/launcher/game/EasyDialogsWin.py
+++ b/launcher/game/EasyDialogsWin.py
@@ -20,6 +20,7 @@ Based upon STDWIN dialogs with the same names and functions.
 """
 
 from __future__ import division
+from __future__ import print_function
 
 import os
 
@@ -1029,7 +1030,7 @@ def test():
     argv = GetArgv(optionlist=optionlist, commandlist=commandlist, addoldfile=0)
     Message("Command line: %s"%' '.join(argv))
     for i in range(len(argv)):
-        print 'arg[%d] = %r' % (i, argv[i])
+        print(('arg[%d] = %r' % (i, argv[i])))
     ok = AskYesNoCancel("Do you want to proceed?")
     ok = AskYesNoCancel("Do you want to identify?", yes="Identify", no="No")
     if ok > 0:
diff --git a/launcher/game/about.rpy b/launcher/game/about.rpy
index 7dd67ab..ec0122d 100644
--- a/launcher/game/about.rpy
+++ b/launcher/game/about.rpy
@@ -42,7 +42,7 @@ screen about:
 
             textbutton _("View license") action interface.OpenLicense() xalign 0.5
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
 label about:
     call screen about
diff --git a/launcher/game/android.rpy b/launcher/game/android.rpy
index fdb7073..fa2de10 100644
--- a/launcher/game/android.rpy
+++ b/launcher/game/android.rpy
@@ -280,7 +280,7 @@ screen android_process(interface):
     text "[ft.text!q]":
         size 14
         color TEXT
-        font "Roboto-Light.ttf"
+        font gui.LIGHT_FONT
         xpos 75
         ypos 350
 
@@ -428,7 +428,7 @@ screen android:
                             text AndroidStateText(state)
 
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
 
 label android:
diff --git a/launcher/game/archiver.rpy b/launcher/game/archiver.rpy
index befe5e2..579f4be 100644
--- a/launcher/game/archiver.rpy
+++ b/launcher/game/archiver.rpy
@@ -48,7 +48,7 @@ init python in archiver:
             # A fixed key minimizes difference between archive versions.
             self.key = 0x42424242
 
-            padding = "RPA-3.0 XXXXXXXXXXXXXXXX XXXXXXXX\n"
+            padding = b"RPA-3.0 XXXXXXXXXXXXXXXX XXXXXXXX\n"
             self.f.write(padding)
 
         def add(self, name, path):
@@ -63,14 +63,14 @@ init python in archiver:
                 dlen = len(data)
 
             # Pad.
-            padding = "Made with Ren'Py."
+            padding = b"Made with Ren'Py."
             self.f.write(padding)
 
             offset = self.f.tell()
 
             self.f.write(data)
 
-            self.index[name].append((offset ^ self.key, dlen ^ self.key, ""))
+            self.index[name].append((offset ^ self.key, dlen ^ self.key, b""))
 
         def close(self):
 
@@ -79,7 +79,7 @@ init python in archiver:
             self.f.write(dumps(self.index, HIGHEST_PROTOCOL).encode("zlib"))
 
             self.f.seek(0)
-            self.f.write("RPA-3.0 %016x %08x\n" % (indexoff, self.key))
+            self.f.write(b"RPA-3.0 %016x %08x\n" % (indexoff, self.key))
 
             self.f.close()
 
diff --git a/launcher/game/change_icon.py b/launcher/game/change_icon.py
index 7de59ff..9d7a8bc 100644
--- a/launcher/game/change_icon.py
+++ b/launcher/game/change_icon.py
@@ -23,13 +23,17 @@
 # http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
 # Contains a reasonable description of the format.
 
+from __future__ import print_function
+
 import struct
 import sys
 import array
-import pefile # @UnresolvedImport
+import pefile  # @UnresolvedImport
 
 # This class performs various operations on memory-loaded binary files,
 # including modifications.
+
+
 class BinFile(object):
 
     def set_u32(self, addr, value):
@@ -74,11 +78,11 @@ class BinFile(object):
     def tostring(self):
         return self.a.tostring()
 
-    def substring(self, start, len): #@ReservedAssignment
+    def substring(self, start, len):  # @ReservedAssignment
         return self.a[start:start+len].tostring()
 
     def __init__(self, data):
-        self.a = array.array('B')
+        self.a = array.array(b'B')
         self.a.fromstring(data)
 
 ##############################################################################
@@ -89,6 +93,8 @@ class BinFile(object):
 resource_virtual = 0
 
 # This parses a data block out of the resources.
+
+
 def parse_data(bf, offset):
     bf.seek(offset)
     data_offset = bf.u32()
@@ -102,16 +108,18 @@ def parse_data(bf, offset):
     for _i in range(data_len):
         l.append(chr(bf.u8()))
 
-    return (code_page, "".join(l))
+    return (code_page, b"".join(l))
 
 # This parses a resource directory.
+
+
 def parse_directory(bf, offset):
 
     bf.seek(offset)
-    char = bf.u32() #@UnusedVariable
-    timedate = bf.u32() #@UnusedVariable
-    major = bf.u16() #@UnusedVariable
-    minor = bf.u16() #@UnusedVariable
+    char = bf.u32()  # @UnusedVariable
+    timedate = bf.u32()  # @UnusedVariable
+    major = bf.u16()  # @UnusedVariable
+    minor = bf.u16()  # @UnusedVariable
     n_named = bf.u16()
     n_id = bf.u16()
 
@@ -143,32 +151,33 @@ def parse_directory(bf, offset):
 def show_resources(d, prefix):
 
     if not isinstance(d, dict):
-        print prefix, "Codepage", d[0], "length", len(d[1])
+        print(prefix, "Codepage", d[0], "length", len(d[1]))
         return
 
     for k in d:
-        print prefix, k
+        print(prefix, k)
         show_resources(d[k], prefix + "  ")
 
 ##############################################################################
 # These functions repack the resources into a new resource segment. Here,
 # the offset is relative to the start of the resource segment.
 
+
 class Packer(object):
 
     def pack(self, d):
-        self.data = ""
+        self.data = b""
         self.data_offset = 0
 
-        self.entries = ""
+        self.entries = b""
         self.entries_offset = 0
 
         head = self.pack_dict(d, 0)
 
-        self.data = ""
+        self.data = b""
         self.data_offset = len(head) + len(self.entries)
 
-        self.entries = ""
+        self.entries = b""
         self.entries_offset = len(head)
 
         return self.pack_dict(d, 0) + self.entries + self.data
@@ -178,7 +187,7 @@ class Packer(object):
 
         l = len(s)
         s = s.encode("utf-16le")
-        self.data += struct.pack("<H", l) + s + "\0\0"
+        self.data += struct.pack("<H", l) + s + b"\0\0"
 
         return rv
 
@@ -188,7 +197,7 @@ class Packer(object):
         rv = len(self.entries) + self.entries_offset
 
         if len(self.data) % 2:
-            self.data += "P"
+            self.data += b"P"
 
         daddr = len(self.data) + self.data_offset
 
@@ -208,7 +217,7 @@ class Packer(object):
 
         offset += len(rv) + (len(name_entries) + len(id_entries)) * 8
 
-        rest = ""
+        rest = b""
 
         for (name, value) in name_entries + id_entries:
             if isinstance(name, unicode):
@@ -229,6 +238,8 @@ class Packer(object):
 ##############################################################################
 # This loads in an icon file, and returns a dictionary that is suitable for
 # use in the resources of an exe file.
+
+
 def load_icon(fn):
     f = BinFile(file(fn, "rb").read())
 
@@ -259,7 +270,6 @@ def load_icon(fn):
 
         rv[3][i + 1] = { 0 : (1252, f.substring(offset, size)) }
 
-
         group += struct.pack("BBBBHHIH", width, height, colors, reserved,
                              planes, bpp, size, i + 1)
 
@@ -279,7 +289,7 @@ def change_icons(oldexe, icofn):
     pe = pefile.PE(oldexe)
 
     for s in pe.sections:
-        if s.Name == ".rsrc\0\0\0":
+        if s.Name == b".rsrc\0\0\0":
             rsrc_section = s
             break
     else:
@@ -311,7 +321,7 @@ def change_icons(oldexe, icofn):
 
     if len(rsrc) % alignment:
         pad = alignment - (len(rsrc) % alignment)
-        padding = "RENPYVNE" * (pad / 8 + 1)
+        padding = b"RENPYVNE" * (pad / 8 + 1)
         padding = padding[:pad]
         rsrc += padding
 
@@ -346,4 +356,3 @@ if __name__ == "__main__":
     f = file(sys.argv[3], "wb")
     f.write(change_icons(sys.argv[1], sys.argv[2]))
     f.close()
-
diff --git a/launcher/game/choose_directory.rpy b/launcher/game/choose_directory.rpy
index 9523f80..c41caad 100644
--- a/launcher/game/choose_directory.rpy
+++ b/launcher/game/choose_directory.rpy
@@ -21,6 +21,20 @@
 
 init python:
 
+    def directory_is_writable(path):
+        test = os.path.join(path, "renpy test do not use")
+
+        try:
+            if os.path.isdir(test):
+                os.rmdir(test)
+
+            os.mkdir(test)
+            os.rmdir(test)
+
+            return True
+
+        except:
+            return False
 
     def choose_directory(path):
         """
@@ -86,8 +100,12 @@ init python:
 
         path = renpy.fsdecode(path)
 
-        if not os.path.isdir(path):
-            path = os.path.abspath(config.renpy_base)
+        if (not os.path.isdir(path)) or (not directory_is_writable(path)):
+            interface.error(_("The selected projects directory is not writable."))
+            path = default_path
             is_default = True
 
+        if is_default and (not directory_is_writable(path)):
+            path = os.path.expanduser("~")
+
         return path, is_default
diff --git a/launcher/game/choose_theme.rpy b/launcher/game/choose_theme.rpy
index 5e29000..d802b26 100644
--- a/launcher/game/choose_theme.rpy
+++ b/launcher/game/choose_theme.rpy
@@ -491,7 +491,7 @@ screen choose_theme:
 
                     use theme_demo
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
     textbutton _("Continue") action Return(True) style "l_right_button"
 
 
diff --git a/launcher/game/distribute.rpy b/launcher/game/distribute.rpy
index 97efb88..ce1faa7 100644
--- a/launcher/game/distribute.rpy
+++ b/launcher/game/distribute.rpy
@@ -50,6 +50,7 @@ init python in distribute:
     import re
     import plistlib
     import time
+    import shutil
 
     match_cache = { }
 
@@ -305,6 +306,38 @@ init python in distribute:
 
             return rv
 
+        def mac_lib_transform(self, app, duplicate):
+            """
+            Moves the mac lib into position. If duplicate is set, the
+
+            Creates a new file list that has lib/darwin-x86_64 and lib/pythonlib2.7
+            copied into the mac app, the latter iff it's not duplicated elsewhere.
+            """
+
+            for f in list(self):
+
+                if f.name.startswith("lib/darwin-x86_64/lib/python2.7"):
+                    name = app + "/Contents/MacOS/lib/darwin-x86_64/Lib" + f.name[31:]
+
+                elif f.name.startswith("lib/pythonlib2.7") and (not duplicate):
+                    name = app + "/Contents/MacOS/lib/darwin-x86_64/Lib" + f.name[16:]
+
+                elif f.name.startswith("lib/darwin-x86_64"):
+                    name = app + "/Contents/MacOS/" + f.name
+
+                else:
+                    continue
+
+                new = f.copy()
+                new.name = name
+                self.append(new)
+
+                if not duplicate:
+                    self.remove(f)
+
+            self.sort()
+
+
         def hash(self, distributor):
             """
             Returns a hex digest representing this file list.
@@ -317,6 +350,23 @@ init python in distribute:
 
             return sha.hexdigest()
 
+        def split_by_prefix(self, prefix):
+            """
+            Returns two filelists, one that contains all the files starting with prefix,
+            and one tht contains all other files.
+            """
+
+            yes = FileList()
+            no = FileList()
+
+            for f in self:
+                if f.name.startswith(prefix):
+                    yes.append(f)
+                else:
+                    no.append(f)
+
+            return yes, no
+
 
     class Distributor(object):
         """
@@ -366,6 +416,10 @@ init python in distribute:
             # A map from file to its hash.
             self.hash_cache = { }
 
+            # A map from a list of file lists and formats to a single integrated
+            # file list with transforms applied.
+            self.file_list_cache = { }
+
             # Status reporter.
             self.reporter = reporter
 
@@ -489,6 +543,7 @@ init python in distribute:
             for p in build_packages:
 
                 for f in p["formats"]:
+
                     self.make_package(
                         p["name"],
                         f,
@@ -517,8 +572,6 @@ init python in distribute:
             if open_directory:
                 store.OpenDirectory(self.destination)()
 
-
-
         def scan_and_classify(self, directory, patterns):
             """
             Walks through the `directory`, finds files and directories that
@@ -576,6 +629,48 @@ init python in distribute:
             for fn in os.listdir(directory):
                 walk(fn, os.path.join(directory, fn))
 
+        def rescan(self, oldlist, directory):
+            """
+            Scans `directory`, and produces a filelist from it. Returns the
+            produced filelist.
+
+            `oldlist`
+                Is a filelist. If a file has the xbit set in the oldlist, it
+                has the xbit set in the new list.
+            """
+
+            executable = set()
+
+            for f in oldlist:
+                if f.executable:
+                    executable.add(f.name)
+
+            rv = FileList()
+
+            def walk(name, path):
+
+                # Ignore ASCII control characters, like (Icon\r on the mac).
+                if re.search('[\x00-\x19]', name):
+                    return
+
+                is_dir = os.path.isdir(path)
+
+                f = File(name, path, is_dir, name in executable)
+                rv.append(f)
+
+                if is_dir:
+
+                    for fn in os.listdir(path):
+                        walk(
+                            name + "/" + fn,
+                            os.path.join(path, fn),
+                            )
+
+            for fn in os.listdir(directory):
+                walk(fn, os.path.join(directory, fn))
+
+            return rv
+
         def temp_filename(self, name):
             self.project.make_tmp()
             return os.path.join(self.project.tmp, name)
@@ -605,6 +700,20 @@ init python in distribute:
             for fl in file_list:
                 self.file_lists[fl].append(f)
 
+        def add_directory(self, file_list, name):
+            """
+            Adds an empty directory to the file lists.
+            """
+
+            if isinstance(file_list, basestring):
+                file_list = file_list.split()
+
+            f = File(name, None, True, False)
+
+            for fl in file_list:
+                self.file_lists[fl].append(f)
+
+
         def ignore_archives(self, archives):
             """
             Ignore archiving commands by adding the files that would be in
@@ -791,6 +900,10 @@ init python in distribute:
 
             contents = self.app + "/Contents"
 
+            self.add_directory(filelist, self.app)
+            self.add_directory(filelist, contents)
+            self.add_directory(filelist, contents + "/MacOS")
+
             plist_fn = self.write_plist()
             self.add_file(filelist, contents + "/Info.plist", plist_fn)
             self.add_file(filelist, contents + "/MacOS/" + self.executable_name, os.path.join(config.renpy_base, "renpy.sh"))
@@ -803,8 +916,23 @@ init python in distribute:
             else:
                 icon_fn = default_fn
 
-            self.add_file(filelist, contents + "/Resources/icon.icns", icon_fn)
+            resources = contents + "/Resources"
+
+            self.add_directory(filelist, resources)
+            self.add_file(filelist, resources + "/icon.icns", icon_fn)
 
+            self.add_directory(filelist, contents + "/MacOS/lib")
+            self.add_directory(filelist, contents + "/MacOS/lib/darwin-x86_64")
+            self.add_directory(filelist, contents + "/MacOS/lib/darwin-x86_64/Lib")
+            self.add_directory(filelist, contents + "/MacOS/lib/darwin-x86_64/Modules")
+
+            sfn = self.temp_filename("Setup")
+            with open(sfn, "wb") as f:
+                pass
+
+            self.add_file(filelist, contents + "/MacOS/lib/darwin-x86_64/Modules/Setup", sfn)
+
+            self.file_lists[filelist].mac_lib_transform(self.app, self.build['renpy'])
 
         def add_windows_files(self):
             """
@@ -872,6 +1000,137 @@ init python in distribute:
                 for f in l:
                     f.name = rename_one(f.name)
 
+        def run(self, message, command, **kwargs):
+            """
+            Runs a command.
+            """
+
+            self.reporter.info(message)
+
+            cmd = [ renpy.fsencode(i.format(**kwargs)) for i in command ]
+
+            # print "\"" + "\" \"".join(cmd) + "\""
+
+            try:
+                import sys, os
+                isatty = os.isatty(sys.stdin.fileno())
+            except:
+                isatty = False
+
+            if isatty:
+                subprocess.check_call(cmd)
+            else:
+                subprocess.check_call(cmd, stdout=self.log, stderr=subprocess.STDOUT)
+
+
+        def sign_app(self, fl, appzip):
+            """
+            Signs the mac app contained in appzip.
+            """
+
+            identity = self.build.get('mac_identity', None)
+
+            if identity is None:
+                return fl
+
+            # Figure out where it goes.
+            if appzip:
+                dn = "sign.app-standalone"
+            else:
+                dn = "sign.app-crossplatform"
+
+            dn = self.temp_filename(dn)
+
+            if os.path.exists(dn):
+                shutil.rmtree(dn)
+
+            # Unpack the app.
+            pkg = DirectoryPackage(dn)
+
+            for i, f in enumerate(fl):
+                self.reporter.progress(_("Unpacking the Macintosh application for signing..."), i, len(fl))
+
+                if f.directory:
+                    pkg.add_directory(f.name, f.path)
+                else:
+                    pkg.add_file(f.name, f.path, f.executable)
+
+            pkg.close()
+
+            # Sign the mac app.
+            self.run(
+                _("Signing the Macintosh application...\n(This may take a long time.)"),
+                self.build["mac_codesign_command"],
+                identity=identity,
+                app=os.path.join(dn, self.app),
+                )
+
+            # Rescan the signed app.
+            fl = self.rescan(fl, dn)
+
+            return fl
+
+        def make_dmg(self, volname, sourcedir, dmg):
+            """
+            Packages `sourcedir` as a dmg.
+            """
+
+            identity = self.build.get('mac_identity', None)
+
+            if identity is None:
+                raise Exception("Creating an unsigned DMG is not supported. Please set build.mac_identity.")
+
+            self.run(
+                _("Creating the Macintosh DMG..."),
+                self.build["mac_create_dmg_command"],
+                identity=identity,
+                volname=volname,
+                sourcedir=sourcedir,
+                dmg=dmg,
+            )
+
+            self.run(
+                _("Signing the Macintosh DMG..."),
+                self.build["mac_codesign_dmg_command"],
+                identity=identity,
+                volname=volname,
+                sourcedir=sourcedir,
+                dmg=dmg,
+            )
+
+        def prepare_file_list(self, format, file_lists):
+            """
+            Prepares a master list of files, given the format and file lists.
+            This also takes care of the mac transforms, and signing the app
+            if necessary.
+            """
+
+            macapp = (format in { "app-zip", "app-directory", "app-dmg" })
+            key = (macapp, tuple(file_lists))
+
+            if key in self.file_list_cache:
+                return self.file_list_cache[key].copy()
+
+            fl = FileList.merge([ self.file_lists[i] for i in file_lists ])
+            fl = fl.copy()
+            fl.sort()
+
+            if self.build.get("exclude_empty_directories", True):
+                fl = fl.filter_empty()
+
+            if macapp:
+                fl = fl.mac_transform(self.app, self.documentation_patterns)
+
+            app, rest = fl.split_by_prefix(self.app)
+
+            if app:
+                app = self.sign_app(app, macapp)
+
+                fl = FileList.merge([ app, rest ])
+
+            self.file_list_cache[key] = fl
+            return fl.copy()
+
         def make_package(self, variant, format, file_lists, dlc=False):
             """
             Creates a package file in the projects directory.
@@ -881,9 +1140,7 @@ init python in distribute:
                 part of the file and directory names.
 
             `format`
-                The format things will be packaged in. This should be one of "zip", "tar.bz2", or
-                "update".
-
+                The format things will be packaged in. See the table of formats below.
             `file_lists`
                 A string containing a space-separated list of file_lists to include in this
                 package.
@@ -894,15 +1151,42 @@ init python in distribute:
             filename = self.base_name + "-" + variant
             path = os.path.join(self.destination, filename)
 
+
+            # A map from the name of the format, to the options that will be
+            # used with it. The fields are:
+            #
+            # - The extension used.
+            # - Is this a directory based format?
+            # - Should the directory be turned into a dmg?
+            # - Should a directory name be prepended?
+
+            FORMATS = {
+                "update" : (".update", False, False, False),
+
+                "tar.bz2" : (".tar.bz2", False, False, True),
+                "zip" : (".zip", False, False, True),
+                "directory" : ("", True, False, False),
+                "dmg" : ("-dmg", True, True, True),
+
+                "app-zip" : (".zip", False, False, False),
+                "app-directory" : ("-app", True, False, False),
+                "app-dmg" : ("-app-dmg", True, True, False),
+            }
+
+            if format not in FORMATS:
+                raise Exception("Format %r is unknown." % format)
+
+            ext, directory, dmg, prepend = FORMATS[format]
+
+            mac_identity = self.build.get('mac_identity', None)
+
+            if dmg and (mac_identity is None):
+                return
+
             if self.packagedest:
                 path = self.packagedest
 
-            fl = FileList.merge([ self.file_lists[i] for i in file_lists ])
-            fl = fl.copy()
-            fl.sort()
-
-            if self.build.get("exclude_empty_directories", True):
-                fl = fl.filter_empty()
+            fl = self.prepare_file_list(format, file_lists)
 
             # Write the update information.
             update_files = [ ]
@@ -922,34 +1206,23 @@ init python in distribute:
 
             update = { variant : { "version" : self.update_versions[variant], "files" : update_files, "directories" : update_directories, "xbit" : update_xbit } }
 
-            if self.include_update and (variant not in [ 'ios', 'android', 'source' ]):
+            update_fn = os.path.join(self.destination, filename + ".update.json")
 
-                update_fn = os.path.join(self.destination, filename + ".update.json")
+            if self.include_update and (variant not in [ 'ios', 'android', 'source']) and (not format.startswith("app-")):
 
                 with open(update_fn, "wb") as f:
                     json.dump(update, f, indent=2)
 
                 if (not dlc) or (format == "update"):
-
                     fl.append(File("update", None, True, False))
                     fl.append(File("update/current.json", update_fn, False, False))
 
-            # The mac transform.
-            if format == "app-zip":
-                fl = fl.mac_transform(self.app, self.documentation_patterns)
-
             # If we're not an update file, prepend the directory.
-            if (not dlc) and format != "update" and format != "directory":
+            if (not dlc) and prepend:
                 fl.prepend_directory(filename)
 
-            if format == "tar.bz2":
-                ext = ".tar.bz2"
-            elif format == "update":
-                ext = ".update"
-            elif format == "zip" or format == "app-zip":
-                ext = ".zip"
-            elif format == "directory":
-                ext = ""
+            # The path to the DMG, if we're going to make one.
+            dmg_path = path + ".dmg"
 
             full_filename = filename + ext
             path += ext
@@ -961,7 +1234,7 @@ init python in distribute:
 
             file_hash, old_fl_hash = self.build_cache.get(full_filename, ("", ""))
 
-            if format == "directory" or old_fl_hash != fl_hash:
+            if directory or old_fl_hash != fl_hash:
 
                 if format == "tar.bz2":
                     pkg = TarPackage(path, "w:bz2")
@@ -969,7 +1242,7 @@ init python in distribute:
                     pkg = TarPackage(path, "w", notime=True)
                 elif format == "zip" or format == "app-zip":
                     pkg = ZipPackage(path)
-                elif format == "directory":
+                elif directory:
                     pkg = DirectoryPackage(path)
 
                 for i, f in enumerate(fl):
@@ -1015,11 +1288,15 @@ init python in distribute:
                 if self.include_update and not self.build_update and not dlc:
                     os.unlink(update_fn)
 
-                if format != "directory":
+                if not directory:
                     file_hash = hash_file(path)
                 else:
                     file_hash = ""
 
+            if dmg:
+                self.make_dmg(filename, path, dmg_path)
+                shutil.rmtree(path)
+
             if file_hash:
                 self.build_cache[full_filename] = (file_hash, fl_hash)
 
diff --git a/launcher/game/distribute_gui.rpy b/launcher/game/distribute_gui.rpy
index bee6228..84d5874 100644
--- a/launcher/game/distribute_gui.rpy
+++ b/launcher/game/distribute_gui.rpy
@@ -242,7 +242,7 @@ screen build_distributions:
                         textbutton _("Force Recompile") action DataToggle("force_recompile") style "l_checkbox"
 
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
     textbutton _("Build") action Jump("start_distribute") style "l_right_button"
 
 label add_from_common:
diff --git a/launcher/game/editor.rpy b/launcher/game/editor.rpy
index 95c1fc0..b8196dd 100644
--- a/launcher/game/editor.rpy
+++ b/launcher/game/editor.rpy
@@ -238,13 +238,13 @@ init 1 python in editor:
             if i.name == persistent.editor:
                 if i.installed and i.name in editors:
                     ei = editors[i.name]
-                    os.environ["RENPY_EDIT_PY"] = renpy.fsencode(os.path.abspath(ei.filename))
+                    os.environ[b"RENPY_EDIT_PY"] = renpy.fsencode(os.path.abspath(ei.filename))
                     error_message = i.error_message
                     break
 
         else:
             persistent.editor = None
-            os.environ.pop("RENPY_EDIT_PY", None)
+            os.environ.pop(b"RENPY_EDIT_PY", None)
 
         renpy.editor.init()
 
diff --git a/launcher/game/fonts/DroidSansFallback.ttf b/launcher/game/fonts/DroidSansFallback.ttf
new file mode 100644
index 0000000..2b75113
Binary files /dev/null and b/launcher/game/fonts/DroidSansFallback.ttf differ
diff --git a/launcher/game/fonts/MTLc3m.ttf b/launcher/game/fonts/MTLc3m.ttf
new file mode 100644
index 0000000..86bdcc7
Binary files /dev/null and b/launcher/game/fonts/MTLc3m.ttf differ
diff --git a/launcher/game/fonts/NanumGothic.ttf b/launcher/game/fonts/NanumGothic.ttf
new file mode 100644
index 0000000..c14ce88
Binary files /dev/null and b/launcher/game/fonts/NanumGothic.ttf differ
diff --git a/launcher/game/tl/korean/Naver Nanum Font License.txt b/launcher/game/fonts/Naver Nanum Font License.txt
similarity index 100%
rename from launcher/game/tl/korean/Naver Nanum Font License.txt
rename to launcher/game/fonts/Naver Nanum Font License.txt
diff --git a/launcher/game/fonts/Roboto-Light.ttf b/launcher/game/fonts/Roboto-Light.ttf
new file mode 100644
index 0000000..aa45340
Binary files /dev/null and b/launcher/game/fonts/Roboto-Light.ttf differ
diff --git a/launcher/game/fonts/Roboto-Regular.ttf b/launcher/game/fonts/Roboto-Regular.ttf
new file mode 100644
index 0000000..0e58508
Binary files /dev/null and b/launcher/game/fonts/Roboto-Regular.ttf differ
diff --git a/launcher/game/front_page.rpy b/launcher/game/front_page.rpy
index 209eac9..c356a9b 100644
--- a/launcher/game/front_page.rpy
+++ b/launcher/game/front_page.rpy
@@ -88,7 +88,7 @@ screen front_page:
                     has hbox:
                         xfill True
 
-                    text "PROJECTS:" style "l_label_text" size 36 yoffset 10
+                    text _("PROJECTS:") style "l_label_text" size 36 yoffset 10
 
                     textbutton _("refresh"):
                         xalign 1.0
diff --git a/launcher/game/gui7.rpy b/launcher/game/gui7.rpy
index 02efa36..ee13070 100644
--- a/launcher/game/gui7.rpy
+++ b/launcher/game/gui7.rpy
@@ -19,13 +19,57 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-init python:
+define gui.project_system_font = None
+define gui.asian = False
+
+init -1 python:
+
     import gui7
+    from gui7 import translate_define, translate_copy, translate_code
+
     import os
 
     from store import config
 
-    for fn in [ "gui.rpy", "options.rpy", "script.rpy" ]:
+    def translate_font(language, font, path=None):
+        """
+        Selects the font file that is used when translating `language`.
+
+        `font`
+            Is the name of the font file used for both the launcher and
+            the new GUI template. This should be a string giving the name
+            of the font file.
+
+        `path`
+            The path to the font file, relative to the launcher's game
+            directory. If not given, defaults to fonts.
+        """
+
+        if path is None:
+            path = "fonts"
+
+        fullfont = path + "/" + font
+
+        def callback():
+            gui.REGULAR_FONT = fullfont
+            gui.LIGHT_FONT = fullfont
+            gui.REGULAR_BOLD = True
+
+            style._default.font = fullfont
+            style.default.font = fullfont
+
+            gui.system_font = fullfont
+            gui.project_system_font = font
+
+        config.language_callbacks[language].append(callback)
+
+        gui7.translate_copy(language, fullfont, font)
+        gui7.translate_define(language, "gui.default_font", repr(font))
+        gui7.translate_define(language, "gui.name_font", repr(font))
+        gui7.translate_define(language, "gui.interface_font", repr(font))
+
+
+    for fn in [ "gui.rpy", "options.rpy", "screens.rpy" ]:
         fn = os.path.join(config.renpy_base, "gui", "game", fn)
         if os.path.exists(fn):
             config.translate_files.append(fn)
@@ -72,8 +116,6 @@ init python:
     ]
 
 
-
-
 screen gui_swatches():
 
     grid 5 4:
@@ -147,22 +189,24 @@ screen gui_demo(accent, boring, light, display):
 
             text _("Display"):
                 style "empty"
-                # font "DejaVuSans.ttf"
+                font (gui.system_font or "DejaVuSans.ttf")
                 color p.accent_color
                 size 24
 
             for i in [ _("Window"), _("Fullscreen"), _("Planetarium") ]:
 
                 textbutton i:
-                    action SetScreenVariable("display", i)
+                    action (None if i == "Planetarium" else SetScreenVariable("display", i))
                     style "empty"
 
                     text_style "empty"
+                    text_font (gui.system_font or "DejaVuSans.ttf")
                     text_size 24
 
                     text_color p.idle_color
                     text_hover_color p.hover_color
                     text_selected_color p.selected_color
+                    text_insensitive_color p.insensitive_color
 
                     xmargin 4
                     ymargin 4
@@ -176,6 +220,7 @@ screen gui_demo(accent, boring, light, display):
                 style "empty"
                 color p.accent_color
                 size 24
+                font (gui.system_font or "DejaVuSans.ttf")
 
             bar:
                 value ScreenVariableValue("value", 1.0)
@@ -238,7 +283,7 @@ screen choose_gui_color():
 
                     use gui_demo(gui_color[0], gui_color[1], gui_color[2], display)
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
     if gui_color:
         textbutton _("Continue") action Return(True) style "l_right_button"
@@ -366,6 +411,15 @@ label gui_project_common:
             project.manager.scan()
             project.Select(project.manager.get(project_name))()
 
+    if gui_new:
+        call update_renpy_strings
+
+        python hide:
+            if gui.project_system_font:
+                with open(os.path.join(project.current.gamedir, "tl/None/common.rpym"), "ab") as f:
+                    f.write("define gui.system_font = {!r}\r\n".format(gui.project_system_font))
+
+
 label gui_generate_images:
 
     python:
diff --git a/launcher/game/gui7/__init__.py b/launcher/game/gui7/__init__.py
index 92b7f91..dd7d7fc 100644
--- a/launcher/game/gui7/__init__.py
+++ b/launcher/game/gui7/__init__.py
@@ -19,20 +19,22 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-from gui7.code import CodeGenerator
+from gui7.code import CodeGenerator, translate_define, translate_copy, translate_code
 from gui7.images import ImageGenerator
 from gui7.parameters import GuiParameters
 
 import renpy.arguments
 import os
 
+
 def generate_gui(p):
 
     ImageGenerator(p).generate_all()
-    CodeGenerator(p).generate_gui("gui.rpy")
+    CodeGenerator(p).generate_gui("gui.rpy", defines=True)
     CodeGenerator(p).generate_gui("screens.rpy")
     CodeGenerator(p).generate_code("options.rpy")
-    CodeGenerator(p).generate_code("script.rpy")
+    CodeGenerator(p).copy_script("script.rpy")
+    CodeGenerator(p).copy_files()
 
     images = os.path.join(p.prefix, "images")
 
@@ -93,10 +95,3 @@ def generate_gui_command():
     generate_gui(p)
 
 renpy.arguments.register_command("generate_gui", generate_gui_command)
-
-
-
-
-
-
-
diff --git a/launcher/game/gui7/code.py b/launcher/game/gui7/code.py
index 392a2d7..124b463 100644
--- a/launcher/game/gui7/code.py
+++ b/launcher/game/gui7/code.py
@@ -19,13 +19,85 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import unicode_literals
+
 import os
 import codecs
 import re
 import math
+import textwrap
+import collections
+import shutil
 
 import renpy
-import textwrap
+
+
+class Define(object):
+
+    def __init__(self, name, value, comment):
+        self.name = name
+        self.value = value
+        self.comment = comment
+
+# A map from language name to a list of defines.
+language_defines = collections.defaultdict(list)
+
+
+def translate_define(language, name, value, comment=None):
+    """
+    This function should be called to register the value of a define that is
+    set when generating code in `language`.
+
+    `name`
+        A string giving the name of the define.
+
+    `value`
+        A string giving the value of the define. Be sure to quote it properly,
+        or use repr().
+
+    `comment`
+        If not None, a comment that will be generated before the define. The
+        comment will only be generated if the define does not exist in
+        gui.rpy. There is no need to use "## ", as the comment will be
+        added and wrapped automatically.
+    """
+
+    language_defines[language].append(Define(name, value, comment))
+
+
+# A map from a language name to a list of (src, dst) pairs. Each represents a
+# file that is copied into place.
+language_copies = collections.defaultdict(list)
+
+
+def translate_copy(language, src, dst):
+    """
+    This function should be called to copy a file from `src` to `dst`
+    when generating code in `language`.
+
+    `src`
+        A path, relative to the launcher game directory.
+
+    `dst`
+        A path, relative to the game directory of the new game.
+    """
+
+    language_copies[language].append((src, dst))
+
+
+# A map from language name and filename to code that should be added to the
+# end of a newly-generated file.
+language_code = collections.defaultdict(list)
+
+
+def translate_code(language, filename, code):
+    """
+    This function can be called to include a block of code verbatim
+    into `file` when a game is generated in `language`.
+    """
+
+    language_code[language, filename].extend([''] + code.split("\n"))
+
 
 class CodeGenerator(object):
     """
@@ -58,7 +130,6 @@ class CodeGenerator(object):
             scaled = int(math.ceil(original * self.p.scale))
             return str(scaled)
 
-
         lines = [ ]
 
         for l in self.lines:
@@ -79,12 +150,18 @@ class CodeGenerator(object):
 
         self.lines = lines
 
-
-    def update_defines(self, replacements):
+    def update_defines(self, replacements, additions=[]):
         """
         Replaces define statements in gui.rpy.
         """
 
+        replacements = dict(replacements)
+
+        for d in additions:
+            replacements[d.name] = d.value
+
+        seen = set()
+
         lines = [ ]
 
         for l in self.lines:
@@ -98,10 +175,26 @@ class CodeGenerator(object):
                 if variable in replacements:
                     l = "{}define {} = {}".format(indent, variable, replacements[variable])
 
+                seen.add(variable)
+
             lines.append(l)
 
-        self.lines = lines
+        for d in additions:
+
+            if d.name in seen:
+                continue
+
+            seen.add(d.name)
+
+            lines.append("")
+
+            if d.comment:
+                for s in textwrap.wrap(d.comment):
+                    lines.append("## " + s)
+
+            lines.append("define {} = {}".format(d.name, d.value))
 
+        self.lines = lines
 
     def update_gui_defines(self):
         """
@@ -123,15 +216,13 @@ class CodeGenerator(object):
             'gui.choice_text_color' : repr(self.p.choice_color.hexcode),
             }
 
-        self.update_defines(replacements)
-
+        self.update_defines(replacements, language_defines[self.p.language])
 
     def update_options_defines(self):
         """
         Replaces define statements in options.rpy.
         """
 
-
         def quote(s):
             s = s.replace("\\", "\\\\")
             s = s.replace("\"", "\\\"")
@@ -145,7 +236,6 @@ class CodeGenerator(object):
 
         self.update_defines(replacements)
 
-
     def write_target(self, filename):
 
         target = os.path.join(self.p.prefix, filename)
@@ -238,7 +328,9 @@ class CodeGenerator(object):
                     len_prefix = len(indent) + len(prefix)
                     len_wrap = 80 - len_prefix
 
-                    for i, s in enumerate(textwrap.wrap(rest, width=len_wrap)):
+                    import store.gui
+
+                    for i, s in enumerate(renpy.text.extras.textwrap(rest, len_wrap, store.gui.asian)):
 
                         if i == 0:
                             s = indent + prefix + s
@@ -256,18 +348,62 @@ class CodeGenerator(object):
 
         self.lines = lines
 
-    def generate_gui(self, fn):
+    def copy_files(self):
+
+        for src, dst in language_copies[self.p.language]:
+            src = os.path.join(renpy.config.gamedir, src)
+            dst = os.path.join(self.p.prefix, dst)
+
+            if os.path.exists(dst):
+                continue
+
+            dstdir = os.path.dirname(dst)
+
+            if not os.path.exists(dstdir):
+                os.makedirs(dstdir, 0o777)
+
+            shutil.copy(src, dst)
+
+    def copy_script(self, name):
+        dst = os.path.join(self.p.prefix, name)
+
+        if os.path.exists(dst):
+            return
+
+        language = renpy.store._preferences.language  # @UndefinedVariable
+
+        if language is None:
+            language = "None"
+
+        src = os.path.join(renpy.config.gamedir, "tl", language, name + "m")
+
+        if not os.path.exists(src):
+            src = os.path.join(self.p.template, name)
+
+        shutil.copy(src, dst)
+
+    def add_code(self, fn):
+
+        if not self.p.replace_code:
+            return
+
+        self.lines.extend(language_code[self.p.language, fn])
+
+    def generate_gui(self, fn, defines=False):
         if not self.p.update_code:
             return
 
         self.load_template(fn)
-        self.update_gui_defines()
+
+        if defines:
+            self.update_gui_defines()
 
         if self.p.replace_code:
             self.remove_scale()
             self.update_size()
             self.translate_strings()
             self.translate_comments()
+            self.add_code(fn)
 
         self.write_target(fn)
 
@@ -284,4 +420,6 @@ class CodeGenerator(object):
         self.translate_comments()
         self.update_options_defines()
 
+        self.add_code(fn)
+
         self.write_target(fn)
diff --git a/launcher/game/gui7/images.py b/launcher/game/gui7/images.py
index d6a97ca..1088af1 100644
--- a/launcher/game/gui7/images.py
+++ b/launcher/game/gui7/images.py
@@ -134,7 +134,7 @@ class ImageGenerator(object):
             index = 1
 
             while True:
-                bfn = "{}.{}.bak".format(fn, index)
+                bfn = u"{}.{}.bak".format(fn, index)
 
                 if not os.path.exists(bfn):
                     break
diff --git a/launcher/game/interface.rpy b/launcher/game/interface.rpy
index 57d0117..03fb91e 100644
--- a/launcher/game/interface.rpy
+++ b/launcher/game/interface.rpy
@@ -197,7 +197,7 @@ screen common:
         label title text_color title_color style "l_info_label"
 
     if back:
-        textbutton _("Back") action back style "l_left_button"
+        textbutton _("Return") action back style "l_left_button"
     elif cancel:
         textbutton _("Cancel") action cancel style "l_left_button"
 
diff --git a/launcher/game/ios.rpy b/launcher/game/ios.rpy
index 298a170..d7f10ab 100644
--- a/launcher/game/ios.rpy
+++ b/launcher/game/ios.rpy
@@ -336,7 +336,7 @@ screen ios:
                             text IOSStateText(state)
 
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
 
 label ios:
diff --git a/launcher/game/itch.rpy b/launcher/game/itch.rpy
index f42de65..352d781 100644
--- a/launcher/game/itch.rpy
+++ b/launcher/game/itch.rpy
@@ -27,6 +27,10 @@ init python:
 
         if renpy.windows:
             rv = os.path.join(os.environ.get("APPDATA", ""), "Roaming", "itch", "bin", "butler.exe")
+
+            if not os.path.exists(rv):
+                rv = os.path.join(os.environ.get("APPDATA", ""), "itch", "bin", "butler.exe")
+
         elif renpy.macintosh:
             rv = os.path.join(os.environ.get("HOME", ""), "Library", "Application Support", "itch", "bin", "butler")
         else:
diff --git a/launcher/game/navigation.rpy b/launcher/game/navigation.rpy
index c42e124..ce2c3a0 100644
--- a/launcher/game/navigation.rpy
+++ b/launcher/game/navigation.rpy
@@ -257,7 +257,7 @@ screen navigation:
                                 xalign 0.5
                                 yalign 0.5
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
     textbutton _("Launch Project") action project.Launch() style "l_right_button"
 
 label navigation:
diff --git a/launcher/game/new_project.rpy b/launcher/game/new_project.rpy
index ac3730e..3b653d8 100644
--- a/launcher/game/new_project.rpy
+++ b/launcher/game/new_project.rpy
@@ -108,7 +108,7 @@ screen select_template:
                     text _("Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'.")
 
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
     textbutton _("Continue") action Return(result) style "l_right_button"
 
 
@@ -162,6 +162,12 @@ label new_theme_project:
             with open(fn, "wb") as f:
                 f.write(options.encode("utf-8"))
 
+            font = template.data.get("font", None)
+            if font is not None:
+                src = os.path.join(config.gamedir, "fonts", font)
+                dst = os.path.join(project_dir, "game", "tl", "None", font)
+                shutil.copy(src, dst)
+
         # Activate the project.
         with interface.error_handling("activating the new project"):
             project.manager.scan()
diff --git a/launcher/game/options.rpy b/launcher/game/options.rpy
index 066b4d6..7e6873d 100644
--- a/launcher/game/options.rpy
+++ b/launcher/game/options.rpy
@@ -19,30 +19,30 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-## This file contains some of the options that can be changed to customize
-## your Ren'Py game. It only contains the most common options... there
-## is quite a bit more customization you can do.
-##
-## Lines beginning with two '#' marks are comments, and you shouldn't
-## uncomment them. Lines beginning with a single '#' mark are
-## commented-out code, and you may want to uncomment them when
-## appropriate.
+# This file contains some of the options that can be changed to customize
+# your Ren'Py game. It only contains the most common options... there
+# is quite a bit more customization you can do.
+#
+# Lines beginning with two '#' marks are comments, and you shouldn't
+# uncomment them. Lines beginning with a single '#' mark are
+# commented-out code, and you may want to uncomment them when
+# appropriate.
 
 init -1 python hide:
 
-    ## Should we enable the use of developer tools? This should be
-    ## set to False before the game is released, so the user can't
-    ## cheat using developer tools.
+    # Should we enable the use of developer tools? This should be
+    # set to False before the game is released, so the user can't
+    # cheat using developer tools.
 
     config.developer = True
 
-    ## These control the width and height of the screen.
+    # These control the width and height of the screen.
 
     config.screen_width = 800
     config.screen_height = 600
 
-    ## This controls the title of the window, when Ren'Py is
-    ## running in a window.
+    # This controls the title of the window, when Ren'Py is
+    # running in a window.
 
     config.window_title = u"Ren'Py Launcher"
 
@@ -51,135 +51,135 @@ init -1 python hide:
     config.name = "Ren'Py Launcher"
     config.version = renpy.version().split()[1]
 
-    #########################################
+    #####################
     # Themes
 
-    ## We then want to call a theme function. themes.roundrect is
-    ## a theme that features the use of rounded rectangles. It's
-    ## the only theme we currently support.
-    ##
-    ## The theme function takes a number of parameters that can
-    ## customize the color scheme.
+    # We then want to call a theme function. themes.roundrect is
+    # a theme that features the use of rounded rectangles. It's
+    # the only theme we currently support.
+    #
+    # The theme function takes a number of parameters that can
+    # customize the color scheme.
 
     theme.roundrect(
-        ## Theme: Roundrect
-        ## Color scheme: Basic Blue
+        # Theme: Roundrect
+        # Color scheme: Basic Blue
 
-        ## The color of an idle widget face.
+        # The color of an idle widget face.
         widget = "#003c78",
 
-        ## The color of a focused widget face.
+        # The color of a focused widget face.
         widget_hover = "#0050a0",
 
-        ## The color of the text in a widget.
+        # The color of the text in a widget.
         widget_text = "#c8ffff",
 
-        ## The color of the text in a selected widget. (For
-        ## example, the current value of a preference.)
+        # The color of the text in a selected widget. (For
+        # example, the current value of a preference.)
         widget_selected = "#ffffc8",
 
-        ## The color of a disabled widget face.
+        # The color of a disabled widget face.
         disabled = "#404040",
 
-        ## The color of disabled widget text.
+        # The color of disabled widget text.
         disabled_text = "#c8c8c8",
 
-        ## The color of informational labels.
+        # The color of informational labels.
         label = "#ffffff",
 
-        ## The color of a frame containing widgets.
+        # The color of a frame containing widgets.
         frame = "#6496c8",
 
-        ## The background of the main menu. This can be a color
-        ## beginning with '#', or an image filename. The latter
-        ## should take up the full height and width of the screen.
+        # The background of the main menu. This can be a color
+        # beginning with '#', or an image filename. The latter
+        # should take up the full height and width of the screen.
         mm_root = "#dcebff",
 
-        ## The background of the game menu. This can be a color
-        ## beginning with '#', or an image filename. The latter
-        ## should take up the full height and width of the screen.
+        # The background of the game menu. This can be a color
+        # beginning with '#', or an image filename. The latter
+        # should take up the full height and width of the screen.
         gm_root = "#dcebff",
 
-        ## If this is True, the in-game window is rounded. If False,
-        ## the in-game window is square.
+        # If this is True, the in-game window is rounded. If False,
+        # the in-game window is square.
         rounded_window = False,
 
-        ## And we're done with the theme. The theme will customize
-        ## various styles, so if we want to change them, we should
-        ## do so below.
+        # And we're done with the theme. The theme will customize
+        # various styles, so if we want to change them, we should
+        # do so below.
         )
 
-    #########################################
-    ## Help.
+    #####################
+    # Help.
 
-    ## This lets you configure the help option on the Ren'Py menus.
-    ## It may be:
-    ## - A label in the script, in which case that label is called to
-    ##   show help to the user.
-    ## - A file name relative to the base directory, which is opened in a
-    ##   web browser.
-    ## - None, to disable help.
+    # This lets you configure the help option on the Ren'Py menus.
+    # It may be:
+    # - A label in the script, in which case that label is called to
+    #   show help to the user.
+    # - A file name relative to the base directory, which is opened in a
+    #   web browser.
+    # - None, to disable help.
     config.help = "README.html"
 
-    #########################################
-    ## Transitions.
+    #####################
+    # Transitions.
 
-    ## Used when entering the game menu from the game.
+    # Used when entering the game menu from the game.
     config.enter_transition = None
 
-    ## Used when exiting the game menu to the game.
+    # Used when exiting the game menu to the game.
     config.exit_transition = None
 
-    ## Used between screens of the game menu.
+    # Used between screens of the game menu.
     config.intra_transition = None
 
-    ## Used when entering the game menu from the main menu.
+    # Used when entering the game menu from the main menu.
     config.main_game_transition = None
 
-    ## Used when returning to the main menu from the game.
+    # Used when returning to the main menu from the game.
     config.game_main_transition = None
 
-    ## Used when entering the main menu from the splashscreen.
+    # Used when entering the main menu from the splashscreen.
     config.end_splash_transition = None
 
-    ## Used when entering the main menu after the game has ended.
+    # Used when entering the main menu after the game has ended.
     config.end_game_transition = None
 
-    ## Used when a game is loaded.
+    # Used when a game is loaded.
     config.after_load_transition = None
 
-    ## Used when the window is shown.
+    # Used when the window is shown.
     config.window_show_transition = None
 
-    ## Used when the window is hidden.
+    # Used when the window is hidden.
     config.window_hide_transition = None
 
 
-    #########################################
-    ## This is the name of the directory where the game's data is
-    ## stored. (It needs to be set early, before any other init code
-    ## is run, so the persistent information can be found by the init code.)
+    #####################
+    # This is the name of the directory where the game's data is
+    # stored. (It needs to be set early, before any other init code
+    # is run, so the persistent information can be found by the init code.)
 python early:
     config.save_directory = "launcher-4"
 
 init -1 python hide:
-    #########################################
-    ## Default values of Preferences.
+    #####################
+    # Default values of Preferences.
 
-    ## Note: These options are only evaluated the first time a
-    ## game is run. To have them run a second time, delete
-    ## game/saves/persistent
+    # Note: These options are only evaluated the first time a
+    # game is run. To have them run a second time, delete
+    # game/saves/persistent
 
-    ## Should we start in fullscreen mode?
+    # Should we start in fullscreen mode?
 
     config.default_fullscreen = False
 
-    ## The default text speed in characters per second. 0 is infinite.
+    # The default text speed in characters per second. 0 is infinite.
 
     config.default_text_cps = 0
 
-    #########################################
-    ## More customizations can go here.
+    #####################
+    # More customizations can go here.
 
     config.sound = False
     config.quit_action = Quit(confirm=False)
@@ -194,50 +194,66 @@ init -1 python hide:
 
     config.underlay = [
         renpy.Keymap(
+            screenshot = _screenshot,
+            reload_game = _reload_game,
+            developer = _developer,
             quit = renpy.quit_event,
             iconify = renpy.iconify,
+            help = _help,
             choose_renderer = renpy.curried_call_in_new_context("_choose_renderer"),
+            console = _console.enter,
+            profile_once = _profile_once,
+            memory_profile = _memory_profile,
             self_voicing = Preference("self voicing", "toggle"),
+            clipboard_voicing = Preference("clipboard voicing", "toggle"),
+            debug_voicing = Preference("debug voicing", "toggle"),
+            progress_screen = _progress_screen,
             ),
-    ]
+        ]
 
     config.rollback_enabled = False
 
-translate None python:
-    config.rtl = False
-
-## This section controls how to build Ren'Py. (Building the launcher is how
-## we build Ren'Py distributions.)
+# This section controls how to build Ren'Py. (Building the launcher is how
+# we build Ren'Py distributions.)
 init python:
 
-    ## We're building Ren'Py tonight.
+    # We're building Ren'Py tonight.
     build.renpy = True
 
-    ## The version number that's supplied to the updater.
+    # The version number that's supplied to the updater.
     build.version = "Ren'Py {}".format(config.version)
 
-    ## The name that's used for directories and archive files. For example, if
-    ## this is 'mygame-1.0', the windows distribution will be in the
-    ## directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
+    # The name that's used for directories and archive files. For example, if
+    # this is 'mygame-1.0', the windows distribution will be in the
+    # directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
 
     if 'RENPY_BUILD_VERSION' in os.environ:
         build.directory_name = "renpy-" + os.environ['RENPY_BUILD_VERSION']
     else:
         build.directory_name = "renpy-" + config.version.rsplit('.', 1)[0]
 
-    ## The name that's uses for executables - the program that users will run
-    ## to start the game. For example, if this is 'mygame', then on Windows,
-    ## users can click 'mygame.exe' to start the game.
+    # The name that's uses for executables - the program that users will run
+    # to start the game. For example, if this is 'mygame', then on Windows,
+    # users can click 'mygame.exe' to start the game.
     build.executable_name = "renpy"
 
-    ## If True, Ren'Py will include update information into packages. This
-    ## allows the updater to run.
+    # If True, Ren'Py will include update information into packages. This
+    # allows the updater to run.
     build.include_update = True
 
-    ## Allow empty directories, so we can distribute the images directory.
+    # Allow empty directories, so we can distribute the images directory.
     build.exclude_empty_directories = False
 
-    ## Clear out various file patterns.
+
+    # Mac signing options.
+    import os
+    build.mac_identity = os.environ.get("RENPY_MAC_IDENTITY", None)
+    build.mac_codesign_command = [ "/home/tom/ab/renpy-deps/mac/mac_sign_client.sh", "{identity}", "{app}" ]
+    build.mac_create_dmg_command = [ "/home/tom/ab/renpy-deps/mac/mac_dmg_client.sh", "{identity}", "{volname}", "{sourcedir}", "{dmg}" ]
+    build.mac_codesign_dmg_command = [ "/bin/true" ]
+
+
+    # Clear out various file patterns.
     build.renpy_patterns = [ ]
     build.early_base_patterns = [ ]
     build.base_patterns = [ ]
@@ -246,8 +262,7 @@ init python:
     # We don't need to clear out the executable patterns, since they're
     # correct for Ren'Py.
 
-    ## Now, add the Ren'Py distribution in using classify_renpy.
-
+    # Now, add the Ren'Py distribution in using classify_renpy.
 
     build.classify_renpy("**~", None)
     build.classify_renpy("**/#*", None)
@@ -355,7 +370,7 @@ init python:
     # Packages.
     build.packages = [ ]
 
-    build.package("sdk", "zip tar.bz2", "source binary")
+    build.package("sdk", "zip tar.bz2 dmg", "source binary")
     build.package("source", "tar.bz2", "source source_only", update=False)
 
     build.package("jedit", "zip", "jedit", dlc=True)
@@ -364,3 +379,7 @@ init python:
     build.package("editra-windows", "zip", "editra-all editra-windows", dlc=True)
     build.package("rapt", "zip", "rapt", dlc=True)
     build.package("renios", "zip", "renios", dlc=True)
+
+
+# Enable the special launcher translation mode.
+define config.translate_launcher = True
diff --git a/launcher/game/package_formats.rpy b/launcher/game/package_formats.rpy
index 42927ce..e594370 100644
--- a/launcher/game/package_formats.rpy
+++ b/launcher/game/package_formats.rpy
@@ -222,6 +222,7 @@ init python in distribute:
 
         def add_file(self, name, path, xbit):
             fn = os.path.join(self.path, name)
+
             shutil.copy2(path, fn)
 
             if xbit:
diff --git a/launcher/game/pefile.py b/launcher/game/pefile.py
index 9fd10a5..b47d915 100644
--- a/launcher/game/pefile.py
+++ b/launcher/game/pefile.py
@@ -41,6 +41,8 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 OF SUCH DAMAGE.
 """
 
+from __future__ import print_function
+
 __revision__ = "$LastChangedRevision: 63 $"
 __author__ = 'Ero Carrera'
 __version__ = '1.2.10-%d' % int( __revision__[21:-2] )
@@ -1668,7 +1670,7 @@ class PE:
         """
 
         for warning in self.__warnings:
-            print '>', warning
+            print('>', warning)
 
 
     def full_load(self):
@@ -3251,7 +3253,7 @@ class PE:
 
     def print_info(self):
         """Print all the PE header information in a human readable from."""
-        print self.dump_info()
+        print(self.dump_info())
 
 
     def dump_info(self, dump=None):
@@ -3930,5 +3932,4 @@ class PE:
 if __name__ == "__main__":
     import sys
     pe = PE(sys.argv[1])
-    print pe
-
+    print(pe)
diff --git a/launcher/game/preferences.rpy b/launcher/game/preferences.rpy
index ea975fb..d91eac4 100644
--- a/launcher/game/preferences.rpy
+++ b/launcher/game/preferences.rpy
@@ -226,7 +226,7 @@ screen preferences:
                                     textbutton tlname action Language(tlvalue) style "l_list"
 
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
 label projects_directory_preference:
     call choose_projects_directory
diff --git a/launcher/game/project.rpy b/launcher/game/project.rpy
index 1bfcd5e..d62e65d 100644
--- a/launcher/game/project.rpy
+++ b/launcher/game/project.rpy
@@ -53,7 +53,10 @@ init python in project:
 
     class Project(object):
 
-        def __init__(self, path):
+        def __init__(self, path, name=None):
+
+            if name is None:
+                name = os.path.basename(path)
 
             while path.endswith("/"):
                 path = path[:-1]
@@ -61,11 +64,7 @@ init python in project:
             if not os.path.exists(path):
                 raise Exception("{} does not exist.".format(path))
 
-            # The name of the project.
-            if path.endswith(".app/Contents/Resources/autorun"):
-                self.name = os.path.basename(path[:-len(".app/Contents/Resources/autorun")])
-            else:
-                self.name = os.path.basename(path)
+            self.name = name
 
             # The path to the project.
             self.path = path
@@ -120,10 +119,24 @@ init python in project:
             data = self.data
 
             data.setdefault("build_update", False)
-            data.setdefault("packages", [ "all" ])
+            data.setdefault("packages", [ "pc", "mac" ])
             data.setdefault("add_from", True)
             data.setdefault("force_recompile", True)
 
+            if "renamed_all" not in data:
+                dp = data["packages"]
+
+                if "all" in dp:
+                    dp.remove("all")
+
+                    if "pc" not in dp:
+                        dp.append("pc")
+
+                    if "mac" not in dp:
+                        dp.append("mac")
+
+                data["renamed_all"] = True
+
         def make_tmp(self):
             """
             Makes the project's temporary directory, if it doesn't exist
@@ -133,7 +146,7 @@ init python in project:
             if self.tmp and os.path.isdir(self.tmp):
                 return
 
-            tmp = os.path.join(config.basedir, "tmp", self.name)
+            tmp = os.path.join(config.renpy_base, "tmp", self.name)
 
             try:
                 os.makedirs(tmp)
@@ -212,13 +225,18 @@ init python in project:
             environ = dict(os.environ)
             environ.update(env)
 
-            for k in environ:
-                environ[k] = renpy.fsencode(environ[k])
+            encoded_environ = { }
+
+            for k, v in environ.items():
+                if v is None:
+                    continue
+
+                encoded_environ[renpy.fsencode(k)] = renpy.fsencode(v)
 
             # Launch the project.
             cmd = [ renpy.fsencode(i) for i in cmd ]
 
-            p = subprocess.Popen(cmd, env=environ)
+            p = subprocess.Popen(cmd, env=encoded_environ)
 
             if wait:
                 if p.wait():
@@ -385,6 +403,33 @@ init python in project:
             self.projects.sort(key=lambda p : p.name.lower())
             self.templates.sort(key=lambda p : p.name.lower())
 
+
+        def find_basedir(self, d):
+            """
+            Try to find a project basedir in d.
+            """
+
+            def has_game(dn):
+                return os.path.isdir(os.path.join(dn, "game"))
+
+            if has_game(d):
+                return d
+
+            dn = os.path.join(d, "Contents", "Resources", "autorun")
+            if has_game(dn):
+                return dn
+
+            for dn in os.listdir(d):
+                if not dn.endswith(".app"):
+                    continue
+
+                dn = os.path.join(d, dn, "Contents", "Resources", "autorun")
+
+                if has_game(dn):
+                    return dn
+
+            return None
+
         def scan_directory(self, d):
             """
             Scans for projects in directories directly underneath `d`.
@@ -405,21 +450,21 @@ init python in project:
                 if not os.path.isdir(ppath):
                     continue
 
-                autorun = os.path.join(ppath, "Contents", "Resources", "autorun")
-                if os.path.exists(autorun):
-                    ppath = autorun
+                try:
+                    ppath = self.find_basedir(ppath)
+                except:
+                    continue
 
-                # A project has either a game/ directory, or a project.json
-                # file.
-                if (not os.path.isdir(os.path.join(ppath, "game"))) and (not os.path.exists(os.path.join(ppath, "project.json"))):
+                if ppath is None:
                     continue
 
                 if ppath in self.scanned:
                     continue
+
                 self.scanned.add(ppath)
 
                 # We have a project directory, so create a Project.
-                p = Project(ppath)
+                p = Project(ppath, pdir)
 
                 project_type = p.data.get("type", "normal")
 
@@ -556,6 +601,11 @@ init python in project:
     if isinstance(persistent.projects_directory, str):
         persistent.projects_directory = renpy.fsdecode(persistent.projects_directory)
 
+init 10 python:
+    if persistent.projects_directory is not None:
+        if not directory_is_writable(persistent.projects_directory):
+            persistent.projects_directory = None
+
 ###############################################################################
 # Code to choose the projects directory.
 
diff --git a/launcher/game/style.rpy b/launcher/game/style.rpy
index dfdba30..9ecaab7 100644
--- a/launcher/game/style.rpy
+++ b/launcher/game/style.rpy
@@ -19,8 +19,22 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+init -1:
+
+    # Fonts.
+    define gui.LIGHT_FONT = "fonts/Roboto-Light.ttf"
+    define gui.REGULAR_FONT = "fonts/Roboto-Regular.ttf"
+
+    # Used to scale the size of fonts.
+    define gui.FONT_SCALE = 1.0
+
+    # Should places where the regular font used be bolded?
+    define gui.REGULAR_BOLD = False
+
 init -1 python:
 
+    config.defer_styles = True
+
     # The color of non-interactive text.
     TEXT = "#545454"
 
@@ -63,12 +77,6 @@ init -1 python:
     # The color of input text.
     INPUT_COLOR = "#d86b45"
 
-    # FONTS/WEIGHTS
-    LIGHT = "Roboto-Light.ttf"
-    REGULAR = "Roboto-Regular.ttf"
-
-    if persistent.large_print:
-        LIGHT = REGULAR
 
 init 1 python:
 
@@ -80,8 +88,18 @@ init 1 python:
         if persistent.large_print and n < 18:
             n = 18
 
+        n = int(n * gui.FONT_SCALE)
+
         return n
 
+    def light_font():
+        if persistent.large_print:
+            return gui.REGULAR_FONT
+
+        return gui.LIGHT_FONT
+
+    def regular_font():
+        return gui.REGULAR_FONT
 
     INDENT = 20
     HALF_INDENT = 10
@@ -108,240 +126,242 @@ init 1 python:
         else:
             return im.Twocolor("images/checkbox_empty.png", color, color, style="l_checkbox_box")
 
-init 1:
-
-    # The default style.
-    style l_default is default:
-        font LIGHT
-        color TEXT
-        idle_color IDLE
-        hover_color HOVER
-        size size(18)
-
-    style l_text is l_default
-
-    style l_button is l_default
-    style l_button_text is l_default:
-        insensitive_color DISABLED
-        selected_font REGULAR
-
-    # A small button, used at the bottom of the screen.
-    style l_link is l_default
-    style l_link_text is l_default:
-        size size(14)
-        font LIGHT
-
-    # Action buttons on the bottom of the screen.
-    style l_right_button is l_default:
-        xalign 1.0
-        ypos 600 - 128 + 12
-        left_margin 8 + INDENT
-        right_margin 10 + INDENT
-
-    style l_right_button_text is l_default:
-        size size(30)
-
-    style l_left_button is l_right_button:
-        xalign 0.0
-
-    style l_left_button_text is l_right_button_text
-
-
-    # The root frame. This contains everything but the bottom navigation,
-    # and buttons.
-    style l_root is l_default:
-        background BACKGROUND
-        xpadding 10
-        top_padding 64
-        bottom_padding 128
-
-    # An inner window.
-    style l_window is l_default:
-        background WINDOW
-        left_padding 6
-        xfill True
-        yfill True
-
-    # Normal size labels.
-    style l_label is l_default:
-        xfill True
-        top_padding 10
-        bottom_padding 8
-        bottom_margin 12
-        background SEPARATOR
-
-    style l_label_text is l_default:
-        size size(24)
-        xpos INDENT
-        yoffset 6
-
-    style l_label_small is l_default:
-        xfill True
-        bottom_padding 8
-        bottom_margin HALF_SPACER_HEIGHT
-        background SEPARATOR
-
-    # Small labels.
-    style l_label_small_text is l_default:
-        xpos INDENT
-        yoffset 6
-        size size(20)
-
-    # Alternate labels. This nests inside an l_label, and gives a button
-    # or label that's nested inside another label.
-
-    style l_alternate is l_default:
-        xalign 1.0
-        yalign 1.0
-        yoffset 4
-        right_margin INDENT
-
-    style l_alternate_text is l_default:
-        size size(14)
-        font LIGHT
-        text_align 1.0
-
-    style l_small_button is l_button
-
-    style l_small_button_text is l_button_text:
-        size size(14)
-
-    style l_small_text is l_text:
-        size size(14)
-
-    # Indents its contents.
-    style l_indent is l_default:
-        left_margin INDENT
-
-    # Indents its contents and pads vertically.
-    style l_indent_margin is l_indent:
-        ymargin 6
-
-    # Lists.
-    style l_list is l_default:
-        left_padding HALF_INDENT
-        xfill True
-        selected_background REVERSE_IDLE
-        selected_hover_background REVERSE_HOVER
-
-    style l_list_text is l_default:
-        idle_color IDLE
-        hover_color HOVER
-        selected_idle_color REVERSE_TEXT
-        selected_hover_color REVERSE_TEXT
-        insensitive_color DISABLED
-
-    style l_list2 is l_list:
-        left_padding (HALF_INDENT + INDENT)
-
-    style l_list2_text is l_list_text
-
-    # Scrollbar.
-    style l_vscrollbar is l_default:
-        thumb Fixed(
-            Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
-            Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
-            xmaximum = SCROLLBAR_SIZE)
-        hover_thumb Fixed(
-            Solid(SCROLLBAR_HOVER, xmaximum=8, xalign=0.5),
-            Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
-            xmaximum = SCROLLBAR_SIZE)
-        xmaximum SCROLLBAR_SIZE
-        bar_vertical True
-        bar_invert True
-        unscrollable "hide"
-
-    # Information window.
-    style l_info_vbox is vbox:
-        yalign 0.5
-        xalign 0.5
-        xfill True
-
-    style l_info_frame is l_default:
-        ypadding 21
-        xfill True
-        background Fixed(
-            INFO_WINDOW,
-            Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=0.0, yoffset=8),
-            Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0, yoffset=-8),
-            )
-        yminimum 180
-        ypos 75
-
-    style l_info_label is l_default:
-        xalign 0.5
-        ypos 75
-        yanchor 1.0
-        yoffset 12
-
-    style l_info_label_text is l_default:
-        size size(36)
-
-    style l_info_text is l_default:
-        xalign 0.5
-
-    style l_info_button is l_button:
-        xalign 0.5
-        xmargin 50
-
-    style l_info_button_text is l_button_text:
-        text_align 0.5
-        layout "subtitle"
-
-    # Progress bar.
-    style l_progress_frame is l_default:
-        background Frame(PATTERN, 0, 0, tile=True)
-        ypadding 5
-
-    style l_progress_bar is l_default:
-        left_bar REVERSE_IDLE
-        right_bar Null()
-        ymaximum 24
-
-    # Navigation.
-    style l_navigation_button is l_button:
-        size_group "navigation"
-        right_margin INDENT
-        top_margin 3
-
-    style l_navigation_button_text is l_button_text:
-        size size(14)
-        font REGULAR
-
-    style l_navigation_text is l_text:
-        size size(14)
-        font LIGHT
-        color TEXT
-
-    # Checkboxes.
-    style l_checkbox is l_button:
-        left_padding INDENT
-        background checkbox(False, IDLE)
-        hover_background checkbox(False, HOVER)
-        selected_idle_background checkbox(True, IDLE)
-        selected_hover_background checkbox(True, HOVER)
-        insensitive_background checkbox(False, DISABLED)
-
-    style l_checkbox_box:
-        yanchor 0.5
-        ypos 11
-
-    style l_checkbox_text is l_button_text:
-        selected_font LIGHT
-
-    # Lines up with a checkbox.
-    style l_nonbox is l_button:
-        xpadding INDENT
-
-    style l_nonbox_text is l_button_text:
-        selected_font LIGHT
-
-    # Projects list.
-    style l_projects is l_default:
-        background PROJECTS_WINDOW
-
-    style hyperlink_text:
-        size size(18)
-        font LIGHT
-        color IDLE
-        hover_color HOVER
+
+
+# The default style.
+style l_default is default:
+    font light_font()
+    color TEXT
+    idle_color IDLE
+    hover_color HOVER
+    size size(18)
+
+style l_text is l_default
+
+style l_button is l_default
+style l_button_text is l_default:
+    insensitive_color DISABLED
+    selected_font regular_font()
+    selected_bold gui.REGULAR_BOLD
+
+# A small button, used at the bottom of the screen.
+style l_link is l_default
+style l_link_text is l_default:
+    size size(14)
+    font light_font()
+
+# Action buttons on the bottom of the screen.
+style l_right_button is l_default:
+    xalign 1.0
+    ypos 600 - 128 + 12
+    left_margin 8 + INDENT
+    right_margin 10 + INDENT
+
+style l_right_button_text is l_default:
+    size size(30)
+
+style l_left_button is l_right_button:
+    xalign 0.0
+
+style l_left_button_text is l_right_button_text
+
+
+# The root frame. This contains everything but the bottom navigation,
+# and buttons.
+style l_root is l_default:
+    background BACKGROUND
+    xpadding 10
+    top_padding 64
+    bottom_padding 128
+
+# An inner window.
+style l_window is l_default:
+    background WINDOW
+    left_padding 6
+    xfill True
+    yfill True
+
+# Normal size labels.
+style l_label is l_default:
+    xfill True
+    top_padding 10
+    bottom_padding 8
+    bottom_margin 12
+    background SEPARATOR
+
+style l_label_text is l_default:
+    size size(24)
+    xpos INDENT
+    yoffset 6
+
+style l_label_small is l_default:
+    xfill True
+    bottom_padding 8
+    bottom_margin HALF_SPACER_HEIGHT
+    background SEPARATOR
+
+# Small labels.
+style l_label_small_text is l_default:
+    xpos INDENT
+    yoffset 6
+    size size(20)
+
+# Alternate labels. This nests inside an l_label, and gives a button
+# or label that's nested inside another label.
+
+style l_alternate is l_default:
+    xalign 1.0
+    yalign 1.0
+    yoffset 4
+    right_margin INDENT
+
+style l_alternate_text is l_default:
+    size size(14)
+    font light_font()
+    text_align 1.0
+
+style l_small_button is l_button
+
+style l_small_button_text is l_button_text:
+    size size(14)
+
+style l_small_text is l_text:
+    size size(14)
+
+# Indents its contents.
+style l_indent is l_default:
+    left_margin INDENT
+
+# Indents its contents and pads vertically.
+style l_indent_margin is l_indent:
+    ymargin 6
+
+# Lists.
+style l_list is l_default:
+    left_padding HALF_INDENT
+    xfill True
+    selected_background REVERSE_IDLE
+    selected_hover_background REVERSE_HOVER
+
+style l_list_text is l_default:
+    idle_color IDLE
+    hover_color HOVER
+    selected_idle_color REVERSE_TEXT
+    selected_hover_color REVERSE_TEXT
+    insensitive_color DISABLED
+
+style l_list2 is l_list:
+    left_padding (HALF_INDENT + INDENT)
+
+style l_list2_text is l_list_text
+
+# Scrollbar.
+style l_vscrollbar is l_default:
+    thumb Fixed(
+        Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
+        Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
+        xmaximum = SCROLLBAR_SIZE)
+    hover_thumb Fixed(
+        Solid(SCROLLBAR_HOVER, xmaximum=8, xalign=0.5),
+        Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
+        xmaximum = SCROLLBAR_SIZE)
+    xmaximum SCROLLBAR_SIZE
+    bar_vertical True
+    bar_invert True
+    unscrollable "hide"
+
+# Information window.
+style l_info_vbox is vbox:
+    yalign 0.5
+    xalign 0.5
+    xfill True
+
+style l_info_frame is l_default:
+    ypadding 21
+    xfill True
+    background Fixed(
+        INFO_WINDOW,
+        Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=0.0, yoffset=8),
+        Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0, yoffset=-8),
+        )
+    yminimum 180
+    ypos 75
+
+style l_info_label is l_default:
+    xalign 0.5
+    ypos 75
+    yanchor 1.0
+    yoffset 12
+
+style l_info_label_text is l_default:
+    size size(36)
+
+style l_info_text is l_default:
+    xalign 0.5
+
+style l_info_button is l_button:
+    xalign 0.5
+    xmargin 50
+
+style l_info_button_text is l_button_text:
+    text_align 0.5
+    layout "subtitle"
+
+# Progress bar.
+style l_progress_frame is l_default:
+    background Frame(PATTERN, 0, 0, tile=True)
+    ypadding 5
+
+style l_progress_bar is l_default:
+    left_bar REVERSE_IDLE
+    right_bar Null()
+    ymaximum 24
+
+# Navigation.
+style l_navigation_button is l_button:
+    size_group "navigation"
+    right_margin INDENT
+    top_margin 3
+
+style l_navigation_button_text is l_button_text:
+    size size(14)
+    font regular_font()
+
+style l_navigation_text is l_text:
+    size size(14)
+    font light_font()
+    color TEXT
+
+# Checkboxes.
+style l_checkbox is l_button:
+    left_padding INDENT
+    background checkbox(False, IDLE)
+    hover_background checkbox(False, HOVER)
+    selected_idle_background checkbox(True, IDLE)
+    selected_hover_background checkbox(True, HOVER)
+    insensitive_background checkbox(False, DISABLED)
+
+style l_checkbox_box:
+    yanchor 0.5
+    ypos 11
+
+style l_checkbox_text is l_button_text:
+    selected_font light_font()
+    selected_bold False
+
+# Lines up with a checkbox.
+style l_nonbox is l_button:
+    xpadding INDENT
+
+style l_nonbox_text is l_button_text:
+    selected_font light_font()
+
+# Projects list.
+style l_projects is l_default:
+    background PROJECTS_WINDOW
+
+style hyperlink_text:
+    size size(18)
+    font light_font()
+    color IDLE
+    hover_color HOVER
diff --git a/launcher/game/testcases.rpy b/launcher/game/testcases.rpy
new file mode 100644
index 0000000..26b6667
--- /dev/null
+++ b/launcher/game/testcases.rpy
@@ -0,0 +1,112 @@
+init python:
+    TEST_PROJECTS = u"/tmp/renpy-moé"
+    import shutil
+
+testcase default:
+    call new_project
+    call translate_project
+    call extract_dialogue
+
+    "Delete Persistent"
+    "Force Recompile"
+
+    call build_project
+
+    "quit"
+
+testcase new_project:
+    python:
+        if os.path.exists(TEST_PROJECTS):
+            shutil.rmtree(TEST_PROJECTS)
+
+        os.mkdir(TEST_PROJECTS, 0o777)
+
+        persistent.projects_directory = TEST_PROJECTS
+
+    "refresh"
+    "Create New Project"
+
+    # Kind of interface
+    "New GUI Interface"
+    "Continue"
+
+    # Name
+    type "Test Project"
+    "Continue"
+
+    # Size
+    "1280x720"
+    "Continue"
+
+    # Color Selection
+    "Continue"
+
+testcase choose_colors:
+    "Change/Update GUI"
+    "Choose new colors"
+    "Continue"
+    "Continue"
+
+    "Change/Update GUI"
+    "Regenerate the"
+    "Continue"
+
+
+
+testcase translate_project:
+    "Generate Translations"
+
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+    type BACKSPACE
+
+    type "piglatin"
+
+    "Generate Translations"
+    "Continue"
+
+    "Generate Translations"
+    "Extract String Translations"
+    "Continue"
+
+    "Generate Translations"
+    "Merge String Translations"
+    "Continue"
+
+    "Generate Translations"
+    "Update Default"
+
+testcase build_project:
+    "Build Distributions"
+    "Build"
+
+testcase extract_dialogue_common:
+    "Extract Dialogue"
+    "Strip text tags"
+    "Escape quotes"
+    "Extract all"
+
+testcase extract_dialogue:
+    call extract_dialogue_common
+    "Tab-delimited"
+    "Continue"
+    "Continue"
+
+
+    call extract_dialogue_common
+    "Text Only"
+    "Continue"
+    "Continue"
diff --git a/launcher/game/tl/arabic/about.rpy b/launcher/game/tl/arabic/about.rpy
deleted file mode 100644
index 30d4eab..0000000
--- a/launcher/game/tl/arabic/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate arabic strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "عرض الرخصة"
-
-    # game/about.rpy:27
-    old "Back"
-    new "عودة"
-
diff --git a/launcher/game/tl/arabic/add_file.rpy b/launcher/game/tl/arabic/add_file.rpy
deleted file mode 100644
index c4bff55..0000000
--- a/launcher/game/tl/arabic/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate arabic strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "اسم الملف"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "إختر اسم لملف الحوار الذي سيتم تكوينه"
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "يجب ان ينتهي اسم الملف بالصيغة .rpy"
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "هذا الملف موجود مسبقاً"
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "رينباي يقوم بتشغيل الملفات المنتهية بـ .rpy تلقائياً. لكي تستعمل هذا الملف, اختر له تبويب وافتحه عبر ملف آخر."
-
diff --git a/launcher/game/tl/arabic/android.rpy b/launcher/game/tl/arabic/android.rpy
deleted file mode 100644
index 0987644..0000000
--- a/launcher/game/tl/arabic/android.rpy
+++ /dev/null
@@ -1,200 +0,0 @@
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "لتجهيز اللعبة للعمل على اجهزة اندرويد يمكنك تحميل الحزمة الخاصة بذلك {a=http://www.renpy.org/dl/android}here{/a}) و فك الضغط عنها, ثم نسخها إلى مجلد رينباي الرئيسي ثم إعادة فتح هذا المشغِّل."
-
-    # game/android.rpy:13
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "حزمة الاندرويد RAPT موجوده, لكنك تحتاج لتنصيب Android SDK قبل ان تبدأ بتجهيز حزم للعمل على اندرويد. الرجاء اختيار تنصيب Android SDK لتستطيع ذلك."
-
-    # game/android.rpy:14
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "حزمة اندرويد RAPT موجوده, لكن المفتاح لم يتم تجهيزه. الرجاء تكوين مفتاح جديد او استرجاع android.keystore"
-
-    # game/android.rpy:15
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "المشروع الحالي لم يتم تجهيز إعدادته. الرجاء اختيار \"Configure\" لتقوم بتجهيزها قبل بناء الحزمة."
-
-    # game/android.rpy:16
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "قم باختيار زر \"Build\" لتقوم بتجهيز المشروع الحالي إلى حزمة قابلة للعمل على اندرويد. او قم بربط جهاز اندرويد و اختيار \"Build & Install\" ليتم تنصيبها مباشرة على الجهاز المطلوب."
-
-    # game/android.rpy:18
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "يقوم بمحاكاة جهاز اندرويد هاتفي محمول. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء."
-
-    # game/android.rpy:19
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "يقوم بمحاكاة جهاز اندرويد تابلت. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء"
-
-    # game/android.rpy:20
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "يقوم بمحاكاة جهاز Ouya. \n\n يد التحكم تتم محاكاتها بأزرار الإتجاهات, زر الإدخال يحاكي select, زر الخروج يحاكي زر menu, و PageUp يحاكي زر العودة."
-
-    # game/android.rpy:22
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "يقوم بتحميل و تنصيب Android SDK والحزم المساندة لها. يعطيك خيار تكوين المفاتيح المطلوبة لتتمكن من استعمال الحزمة."
-
-    # game/android.rpy:23
-    old "Configures the package name, version, and other information about this project."
-    new "يقوم بتجهيز إعدادات الحزمة, رقم النسخة, و معلومات أخرى تتعلق بهذا المشروع."
-
-    # game/android.rpy:24
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "يفتح الملف الخاص بمعلومات مفتاح Google Play في محرر النصوص. \n\n هذه الخطوة غير مطلوبة إلا لو كان البرنامج يحتاج إحدى الحوم المساندة expansion APK. الرجاء الإطلاع على ملفات المساعدة للحصول على المزيد من المعلومات."
-
-    # game/android.rpy:25
-    old "Builds the Android package."
-    new "يقوم ببناء حزمة للأندرويد."
-
-    # game/android.rpy:26
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "يقوم ببناء حزمة للأندرويد, ثم يقوم بتنصيبها على جهاز أندرويد المتصل بحاسوبك."
-
-    # game/android.rpy:142
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:361
-    old "Android: [project.current.name!q]"
-    new "أندرويد: [project.current.name!q]"
-
-    # game/android.rpy:381
-    old "Emulation:"
-    new "محاكاة"
-
-    # game/android.rpy:389
-    old "Phone"
-    new "هاتف"
-
-    # game/android.rpy:393
-    old "Tablet"
-    new "تابلت/ لوحي"
-
-    # game/android.rpy:397
-    old "Television / OUYA"
-    new "تلفزيون / OUYA"
-
-    # game/android.rpy:409
-    old "Build:"
-    new "بناء"
-
-    # game/android.rpy:417
-    old "Install SDK & Create Keys"
-    new "تنصيب SDK و اختلاق مفاتيح"
-
-    # game/android.rpy:421
-    old "Configure"
-    new "إعدادات"
-
-    # game/android.rpy:425
-    old "Build Package"
-    new "بناء الحزمة"
-
-    # game/android.rpy:429
-    old "Build & Install"
-    new "بناء و تنصيب"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "لبناء ملفات الأندرويد, الرجاء تحميل RAPT, ثم فك الضغط عن الملف ووضعه في مجلد رينباي. قد تحتاج لإعادة تشغيل رينباي ليعمل بشكل صحيح."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "تحتاج لنسخة برمجية من جافا تعتمد الـ 32-بت لتستطيع إنشاء ملفات الأندرويد على نظام الوندوز. حزمة JDK تختلف عن JRE, قد تكون الجافا لديك موجوده لكنها تفتقد الـ JDK. \n\n الرجاء {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}تحميل و تنصيب JDK{/a} ثم إعادة تشغيل رينباي"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "يحاول محاكاة نظام تلفزيوني للأندرويد مثل جهاز OUYA او Fire TV. \n\n يتم تخطيط الأزرار لعصا التحكم لتناسب ازرار جهاز التحكم عن بعد. Controller input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "يتصل بجهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "يفصل الاتصال عن جهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
-
-    # game/android.rpy:516
-    old "Other:"
-    new "آخر:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "الإتصال عن بعد عن طريق ADB"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "قطع إتصال ADB عن بعد"
-
-    # game/android.rpy:561
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "قبل ان تصتطيع إنشاء ملفات للأندرويد, عليك ان تقوم بتحميل ملفات RAPT الخاصة بتحويل ملفات رينباي للأندرويد. هل تريد ان تقوم بتحميل الحزمة الآن؟"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "عنوان ADB عن بعد"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "الرجاء إدخال عنوان الأي بي ورقم المنفذ المطلوب للإتصال, على شكل \"192.168.1.143:5555\". الرجاء العودة لدليل المستخدم الخاص بجهازك لتعرف إن كان يدعم الإتصال عن بعد للـ ADB و إن كان قادراً على ذلك, ستجد العنوان و المنفذ المطلوبان."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "عنوان ِADB خاطيء"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "العنوان يجب ان يحتوي على علامة ':' واحده فقط لا غير"
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "الخادم يجب ان لا يحتوي على مساحات فارغة"
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "يجب ان يكون العنوان مكون من أرقام فقط"
-
-
-translate arabic strings:
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "يبني الحزمة الخاصة بالأندرويد و يقوم بتنصيبها على جهاز أندرويد متصل بجهازك, ثم يقوم بإقلاع البرنامج على جهاز الأندرويد."
-
-    # game/android.rpy:290
-    old "Television"
-    new "تلفاز"
-
-    # game/android.rpy:326
-    old "Build, Install & Launch"
-    new "بناء,تنصيب و إقلاع."
-
-# : Translation updated at 2015-06-19 08:55
-
-translate arabic strings:
-
-    # game/android.rpy:50
-    old "Retrieves the log from the Android device and writes it to a file."
-    new "يجلب قائمة المهام من جعاز الأندرويد و يكتبها في ملف."
-
-    # game/android.rpy:240
-    old "Copying Android files to distributions directory."
-    new "يتم الآن نسخ ملفات الأندرويد إلى المجلد الخاص بالنشر"
-
-    # game/android.rpy:404
-    old "Logcat"
-    new "Logcat"
-
-    # game/android.rpy:538
-    old "Retrieving logcat information from device."
-    new "يتم النسخ من الجهاز لمعلومات Logcat"
-
-
diff --git a/launcher/game/tl/arabic/choose_directory.rpy b/launcher/game/tl/arabic/choose_directory.rpy
deleted file mode 100644
index 677158c..0000000
--- a/launcher/game/tl/arabic/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate arabic strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "لم يتمكن رينباي من تشغيل بايثون باستخدام tkinter لاختيار المجلد. الرجال تنصيب حزمة tkinter أو python-tk."
-
diff --git a/launcher/game/tl/arabic/choose_theme.rpy b/launcher/game/tl/arabic/choose_theme.rpy
deleted file mode 100644
index e1cc4cf..0000000
--- a/launcher/game/tl/arabic/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate arabic strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "لم يتمكن رينباي من تغيير المظهر, ربما ملف options.rpy قد تغير بشكل كبير"
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "عرض"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "نافذة"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "ملء الشاشة"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "مستوى الصوت"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "إختر المظهر"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "المظهر"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "توليفة الألوان"
-
-    # game/choose_theme.rpy:444
-    old "Continue"
-    new "استمرار"
-
diff --git a/launcher/game/tl/arabic/common.rpy b/launcher/game/tl/arabic/common.rpy
index 67e86b8..c7c313c 100644
--- a/launcher/game/tl/arabic/common.rpy
+++ b/launcher/game/tl/arabic/common.rpy
@@ -1,589 +1,335 @@
-# : Translation updated at 2013-04-30 07:54
-
+
 translate arabic strings:
 
-    # renpy/common/00action_file.rpy:118
-    old "%b %d, %H:%M"
-    new "%b %d, %H:%M"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-# : Translation updated at 2013-04-30 07:54
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-translate arabic strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "تسريع الرسومات"
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "إختر بشكل اوتوماتيكي"
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "فرض استعمال محركات Angle/DirectX"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "فرض استعمال محركات OpenGL"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "فرض استعمال المحركات البرمجية software renderer"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "سيتم تفعيل التغييرات في المرة القادمة التي تفتح فيها البرنامج"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "خروج"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "عودة"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "تحذير عن الأداء"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "هذا الجهاز يستعمل software rendering"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "هذا الجهاز لا يستعمل shaders"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "هذا الجهاز يستعرض الرسوميات بشكل بطيء"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "هذا الجهاز يواجه مشكلة في استعراض الرسوميات [problem]"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض, القيام بتحديث directX قد يساعد في حل المشكلة."
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new " محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض."
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "تحديث DirectX"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "استمرار, الرجاء عرض هذا التحذير في المرة الثادمة ايضاً"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "استمرار, لا تعرض هذا التحذير مرة اخرى"
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "يتم تحديث DirectX"
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "يتم الآن تنصيب DirectX, قد يبدأ ذلك بشكل مصغر في شريط المهام. الرجاء اتباع التعليمات لاكمال التنصيب."
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}ملاحظة:{/b} مايكروسوفت دايركت أكس يقوم تلقائياً بتنصيب شريط بينق Bing toolbar. إذا لم ترغب بذلك الرجاء القيام بإلغاء تحديد خانة الاختيار"
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "حيثن ينتهي التنصيب, الرجاء الضغط ادناه لإعادة تشغيل البرنامج"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "إعادة تشغيل"
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-# : Translation updated at 2013-04-30 07:54
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-translate arabic strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00keymap.rpy:167
-    old "Saved screenshot as %s."
-    new "تم حفظ الصورة كـ %s"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-# : Translation updated at 2013-04-30 07:54
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-translate arabic strings:
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
-    # renpy/common/00layout.rpy:421
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
+
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d, %H:%M"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "تم الحفظ السريع"
+
+    # 00gui.rpy:227
     old "Are you sure?"
     new "هل انت متأكد؟"
 
-    # renpy/common/00layout.rpy:422
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "هل انت متأكد من رغبتك في حذف خانة الحفظ هذه؟"
 
-    # renpy/common/00layout.rpy:423
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "هل انت متأكد من رغبتك في الحفظ على هذه الخانة؟"
 
-    # renpy/common/00layout.rpy:424
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "الاسترجاع سيضيع كل ما فعلته منذ خانة الحفظ السابقة. \n هل انت متأكد من رغبتك في الاسترجاع إلى هذه النقطة؟"
 
-    # renpy/common/00layout.rpy:425
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "هل انت متأكد من رغبتك في الخروج؟"
 
-    # renpy/common/00layout.rpy:426
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "هل انت متأكد من رغبتك في العودة للقائمة الرئيسية؟ \n كل ما لم تقم بحفظة سيضيع."
 
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "وضع التسريع"
-
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "وضع التسريع السريع"
-
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/00updater.rpy:1258
-    old "Updater"
-    new "برنامج التحديث"
-
-    # renpy/common/00updater.rpy:1267
-    old "This program is up to date."
-    new "هذه النسخة هي الأحدث"
-
-    # renpy/common/00updater.rpy:1269
-    old "[u.version] is available. Do you want to install it?"
-    new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
-
-    # renpy/common/00updater.rpy:1271
-    old "Preparing to download the updates."
-    new "يتم التجهيز لتحميل البرنامج من الانترنت"
-
-    # renpy/common/00updater.rpy:1273
-    old "Downloading the updates."
-    new "يتم تنزيل التحديثات"
-
-    # renpy/common/00updater.rpy:1275
-    old "Unpacking the updates."
-    new "يتم فك الضغط عن التحديثات"
-
-    # renpy/common/00updater.rpy:1279
-    old "The updates have been installed. The program will restart."
-    new "تم التحديث.. سيتم إعادة تشغيل البرنامج."
-
-    # renpy/common/00updater.rpy:1281
-    old "The updates have been installed."
-    new "تم التحديث."
-
-    # renpy/common/00updater.rpy:1283
-    old "The updates were cancelled."
-    new "تم إلغاء التحديث."
-
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/_compat/gamemenu.rpym:180
-    old "Empty Slot."
-    new "خانة فارغة"
-
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "السابق"
-
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "التالي"
-
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "خيارات عصى التحكم"
-
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "حصل استثناء"
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "تراجع"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "يقوم بالتراجع لنقطة سابقة لكي تستطيع اختيار شيء آخر"
-
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "تجاهل"
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "يتجاهل الاستثناء مما يستمح لك بالاستمرار. قد يسبب هذا المزيد من الاخطاء."
-
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "إعادة المحاولة"
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "يعيد تشغيل اللعبة من القرص الصلب, مع محاولة استعمادة آخر نقطة وحفظها عند الإستطاعة."
-
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "قراءة التقرير"
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "يفتح تقرير الخطأ في برنامج الملفات النصية."
-
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "يخرج من اللعبة."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "حصل خطأ أثناء تشغيل النص."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "يفتح قائمة اخطاء التشغيل."
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "يفتح ملف errors.txt في برنامج الملفات النصية"
-
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "تم الحفظ السريع بنجاح"
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "يوجد عدد صور [index] من أصل [count] مقفل"
-
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "السابق"
-
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "التالي"
-
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "عرض الشرائح"
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
 
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "العودة"
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # renpy/common/00layout.rpy:427
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "هل أنت متأكد من رغبتك في البدء بالتسريع؟"
 
-    # renpy/common/00layout.rpy:428
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "هل انت متأكد من رغبتك في التسريع حتى الخيار التالي؟"
 
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "هل انت متأكد من رغبتك في تسريع الخيارات و الحوار الذي لم يسبق لك قرائته؟"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new ""
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "إضغط زر الخروج لإغلاق لوحة التحكم, اكتب كلمة help للمساعدة"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "لغة برمحة رينباي متاحه"
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "لغة برمجة رينباي غير متاحه"
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "مساعده: عرض هذه المساعده"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "أوامر: \n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new "<renpy script statement>: عرض الأوامر\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <python expression or statement>: عرض التعبير او الأوامر"
-
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: مسح تاريخ  لوحة التحكم"
-
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: الخروج من لوحة التحكم"
-
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "استرجاع <slot>: يقوم باسترجاع اللعب من نقطة الحفظ"
-
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "حفظ <slot>: يقوم بحفظ اللعب في نقطة الحفظ"
-
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: يعيد تشغيل اللعبة مع عرض التغييرات في النص"
-
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "مشاهده <expression>: يقوم بعرض تبيرات بايثون"
-
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expression>: يقوم بإيقاف تعبير بايثون"
-
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: يقوم بإيقاف كل تعبيرات بايثون"
-
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: يقفز للعنوان"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "إعادة التحميل تلقائياً"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "قائمة المبرمج"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "إعادة تشغيل اللعبة (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "لوحة التحكم (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "مستعرض الأوامر"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "اختبار القوالب"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "مكان الصور المطلوبة"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "قائمة اسماء الملفات"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "عرض قائمة الصور "
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "إخفاء قائمة الصور"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "لم يتم تغيير اي من الأوامر منذ ان بدأت اللعبة"
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "العودة للوحة المبرمج"
-
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}صور مفقودة{/b}"
-
-    # renpy/common/_developer/developer.rpym:424
-    old "Rectangle: %r"
-    new "مثلث: %r"
-
-    # renpy/common/_developer/developer.rpym:429
-    old "Mouse position: %r"
-    new "مكان المؤشر: %r"
-
-    # renpy/common/_developer/developer.rpym:431
-    old "Right-click or escape to quit."
-    new "إضغط بالزر الايمن او إضغط زر الخروح للإغلاق"
-
-    # renpy/common/_developer/developer.rpym:482
-    old "Done"
-    new "تم"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # renpy/common/_developer/inspector.rpym:43
-    old "Displayable Inspector"
-    new "اختبار المستعرضات"
-
-    # renpy/common/_developer/inspector.rpym:49
-    old "Nothing to inspect."
-    new "لا يوجد شيء ليتم اختباره"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-    # renpy/common/_developer/inspector.rpym:58
-    old "Size"
-    new "حجم"
-
-    # renpy/common/_developer/inspector.rpym:63
-    old "Style"
-    new "مظهر"
-
-    # renpy/common/_developer/inspector.rpym:123
-    old "Inspecting Styles of [displayable_name!q]"
-    new "يتم اختبار المظهر الخاص بـ [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:135
-    old "displayable:"
-    new "مستعرضات"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "        (no properties affect the displayable)"
-    new "        (لا توجد اي مؤثرات على هذا المستعرض)"
-
-    # renpy/common/_developer/inspector.rpym:144
-    old "        (default properties omitted)"
-    new "        (تم استبعاد تأثير المؤثرات القياسية)"
-
-    # renpy/common/_developer/inspector.rpym:174
-    old "<repr() failed>"
-    new "<repr() failed>"
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "تم حفظ الصورة كـ %s"
 
-# Translation updated at 2014-09-30 23:01
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-translate arabic strings:
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "الموقع"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "وضع التسريع"
 
-translate arabic strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:387
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "تشغيل الأصوات من  الحافظة مفعّل. إضغط لإيقافه زريّ: Shift+C"
 
-    # renpy/common/00preferences.rpy:389
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "التكلّم التلقائي مفعَل. لإيقافه إضغط زر V"
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate arabic strings:
-
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "تحديث برنامج رينباي غير مدعوم على الأجهزة المحمولة."
 
-    # renpy/common/00updater.rpy:478
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "يتم محاكاة خطأ الآن."
 
-    # renpy/common/00updater.rpy:654
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "هذا المشروع لا يدعم التحديث، أو أن ملف حالة نسخة البرنامج محذوفة."
 
-    # renpy/common/00updater.rpy:668
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "هذا الحساب ليست لديه الصلاحية ليقوم بالتحديث."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new " هذا الحساب ليست لديه الصلاحية ليكتب ملف التحديث."
 
-    # renpy/common/00updater.rpy:696
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "لم نتمكن من التحقق من توقيع التحديث update signature."
 
-    # renpy/common/00updater.rpy:956
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "لم يتم تحميل ملف التحديث."
 
-    # renpy/common/00updater.rpy:974
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "ملف التحديث لا يحتوي على المختصرات الصحيحة - قد يكون معطوباً."
 
-    # renpy/common/00updater.rpy:1030
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "عند فك الحزمة {}، نوع مجهول {}."
 
+    # 00updater.rpy:1393
+    old "Updater"
+    new "برنامج التحديث"
 
-translate arabic strings:
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "هذه النسخة هي الأحدث"
+
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
+
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "يتم التجهيز لتحميل البرنامج من الانترنت"
+
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "يتم تنزيل التحديثات"
+
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "يتم فك الضغط عن التحديثات"
+
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "تم التحديث.. سيتم إعادة تشغيل البرنامج."
 
-    # renpy/common/_developer/developer.rpym:437
-    old "Rectangle copied to clipboard."
-    new "تم نسخ المربع إلى الحافظة."
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "تم التحديث."
 
-    # renpy/common/_developer/developer.rpym:440
-    old "Position copied to clipboard."
-    new "تم نسخ الموضع إلى الحافظة."
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "تم إلغاء التحديث."
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "يوجد عدد صور [index] من أصل [count] مقفل"
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "السابق"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "التالي"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "عرض الشرائح"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "العودة"
 
diff --git a/launcher/game/tl/arabic/developer.rpy b/launcher/game/tl/arabic/developer.rpy
new file mode 100644
index 0000000..735293e
--- /dev/null
+++ b/launcher/game/tl/arabic/developer.rpy
@@ -0,0 +1,179 @@
+
+translate arabic strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "قائمة المبرمج"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "إعادة تشغيل اللعبة (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "لوحة التحكم (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "مستعرض الأوامر"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "اختبار القوالب"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "مكان الصور المطلوبة"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "قائمة اسماء الملفات"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "عرض قائمة الصور "
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "إخفاء قائمة الصور"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "لا يوجد شيء ليتم اختباره"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "العودة للوحة المبرمج"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "مثلث: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "مكان المؤشر: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "إضغط بالزر الايمن او إضغط زر الخروح للإغلاق"
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "تم نسخ المربع إلى الحافظة."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "تم نسخ الموضع إلى الحافظة."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "اختبار المستعرضات"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "حجم"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "مظهر"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "الموقع"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "يتم اختبار المظهر الخاص بـ [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "مستعرضات"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (لا توجد اي مؤثرات على هذا المستعرض)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (تم استبعاد تأثير المؤثرات القياسية)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "إضغط زر الخروج لإغلاق لوحة التحكم, اكتب كلمة help للمساعدة"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "لغة برمحة رينباي متاحه"
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "لغة برمجة رينباي غير متاحه"
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "مساعده: عرض هذه المساعده"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "أوامر: \n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new "<renpy script statement>: عرض الأوامر\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: عرض التعبير او الأوامر"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: مسح تاريخ  لوحة التحكم"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: الخروج من لوحة التحكم"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "استرجاع <slot>: يقوم باسترجاع اللعب من نقطة الحفظ"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "حفظ <slot>: يقوم بحفظ اللعب في نقطة الحفظ"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: يعيد تشغيل اللعبة مع عرض التغييرات في النص"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "مشاهده <expression>: يقوم بعرض تبيرات بايثون"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: يقوم بإيقاف تعبير بايثون"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: يقوم بإيقاف كل تعبيرات بايثون"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: يقفز للعنوان"
+
diff --git a/launcher/game/tl/arabic/distribute.rpy b/launcher/game/tl/arabic/distribute.rpy
deleted file mode 100644
index 73499b7..0000000
--- a/launcher/game/tl/arabic/distribute.rpy
+++ /dev/null
@@ -1,52 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/distribute.rpy:333
-    old "Nothing to do."
-    new "لا شيء لإنجازه"
-
-    # game/distribute.rpy:337
-    old "Scanning project files..."
-    new "يتم فحص الملفات..."
-
-    # game/distribute.rpy:344
-    old "Scanning Ren'Py files..."
-    new "يتم فحص ملفات رينباي..."
-
-    # game/distribute.rpy:494
-    old "Archiving files..."
-    new "يتم أرشفة الملفات..."
-
-    # game/distribute.rpy:745
-    old "Writing the [variant] [format] package."
-    new "يتم كتابة ملفات [variant] [format]"
-
-    # game/distribute.rpy:758
-    old "Making the [variant] update zsync file."
-    new "Making the [variant] update zsync file."
-
-    # game/distribute.rpy:854
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "تم انهاء {b}[complete]{/b} من عدد {b}[total]{/b} من الملفات."
-
-    # game/distribute.rpy:915
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "تم الإنتهاء من تكوين رزمة البيانات لنشر اللعبة. بسبب اختلاف نظام الملفات في الأنظمة التشغيلية ماك و لينوكس, لا يمكن فك الضغط عن الرزمة الخاصة بتلك الأنظمة على نظام وندوز."
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "لم يتم اختيار اي حزمة, لم يحصل اي شيء."
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "فشل بناء ملفات النشر. build.directory_name يجب أن لا يحتوي على مساحات فارغة, فواصل, او فواصل منقوطة في إسم المجلد "
-
diff --git a/launcher/game/tl/arabic/distribute_gui.rpy b/launcher/game/tl/arabic/distribute_gui.rpy
deleted file mode 100644
index d7f34b9..0000000
--- a/launcher/game/tl/arabic/distribute_gui.rpy
+++ /dev/null
@@ -1,66 +0,0 @@
-
-translate arabic strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "تجميع الملفات تجهيزاً للنشر: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "اسم المجلد:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "اسم الملف التشغيلي:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "الأوامر:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "تحرير options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "إعادة تحميل"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "بناء الرزمة البيانية:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "بناء تحديثات:"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "بناء"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "تم ايجاد بعض الاخطاء في المشروع. الرجاء التأكد من خلو المشروع من الأخطاء قبل نشره بشكل نهائي."
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "مشروعك يخلو من معلومات النشر, هل ترغب في إضافة هذه المعلومات في نهاية ملف options.rpy؟"
-
-
-translate arabic strings:
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "إضافة بند 'مِن' إلى أمر الجلب, مرة واحدة"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "خيارات:"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "إضافة بنود 'مِن' إلى أمر الجلب"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "إضافة بنود 'مِن' إلى أوامر الجلب التي لا تحتوي عليها."
-
diff --git a/launcher/game/tl/arabic/editor.rpy b/launcher/game/tl/arabic/editor.rpy
deleted file mode 100644
index 43c69bd..0000000
--- a/launcher/game/tl/arabic/editor.rpy
+++ /dev/null
@@ -1,64 +0,0 @@
-#  Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية."
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية. على نظام لينوكس, Editra يحتاج wxPython."
-
-    # game/editor.rpy:137
-    old "The may have occured because wxPython is not installed on this system."
-    new "قد يكون السبب ان wxPython غير موجود على هذا الجهاز."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "مطلوب تحميل ملف بحجم  22 ميغا بايت."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "مطلوب تحميل ملف بحجم 1.8 ميغا بايت."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "قد يكون السبب ان الجافا غير موجوده على هذا الجهاز."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "حصل استثناء اثناء فتح المحرر: \n[exception!q]"
-
-    # game/editor.rpy:378
-    old "Select Editor"
-    new "الرجاء اختيار المحرر"
-
-    # game/editor.rpy:393
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "محرر النصوص هو برنامج يساعدك على تعديل ملفات رينباي البرمجية والحوار. هنا, يمكنك اختيار المحرر الذي سيستعلمه رينباي. إذا لم يكن لديك مسبقاً, سيتم تحميله و تنصيبه بشكل اوتوماتيكي."
-
-    # game/editor.rpy:415
-    old "Cancel"
-    new "إلغاء الامر"
-
-#  Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "قد يكون سبب ذلك ان wxPython غير موجود في نظام التشغيل لديك"
-
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "محرر متخصص يستعمل لغة جافا"
-
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "يقوم بفتح البرنامج المسؤول عن تحرير ملفات .rpy في نظامك التشغيلي"
-
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "يمنع رينباي من فتح اي محرر نصوص"
-
diff --git a/launcher/game/tl/arabic/error.rpy b/launcher/game/tl/arabic/error.rpy
new file mode 100644
index 0000000..3fce561
--- /dev/null
+++ b/launcher/game/tl/arabic/error.rpy
@@ -0,0 +1,179 @@
+
+translate arabic strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "تسريع الرسومات"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "إختيار اوتوماتيكي"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "فرض الزاوية/دايركت × ومحركاته"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "فرض محرك OpenGL"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "فرض محركات البرامج"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "التغييرات سيتم تطبيقها في المرة القادمة تفتح البرنامج"
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "تحذير تشغيلي"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "هذا الحاسوب يستعمل محركات البرامج software rendering"
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "هذا الحاسوب لا يستعمل اي shaders"
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "هذا الحاسوب يستعرض الرسوميات بشكل بطيء"
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "هذا الحاسوب يواجه مشكلة في عرض الرسوميات [problem]"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض, القيام بتحديث directX قد يساعد في حل المشكلة."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new " محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "تحديث DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "استمرار, الرجاء عرض هذا التحذير في المرة الثادمة ايضاً"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "استمرار, لا تعرض هذا التحذير مرة اخرى"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "يتم تحديث DirectX"
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "يتم الآن تنصيب DirectX, قد يبدأ ذلك بشكل مصغر في شريط المهام. الرجاء اتباع التعليمات لاكمال التنصيب."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}ملاحظة:{/b} مايكروسوفت دايركت أكس يقوم تلقائياً بتنصيب شريط بينق Bing toolbar. إذا لم ترغب بذلك الرجاء القيام بإلغاء تحديد خانة الاختيار"
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "حيثن ينتهي التنصيب, الرجاء الضغط ادناه لإعادة تشغيل البرنامج"
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "إعادة تشغيل"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "قراءة التقرير"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "يفتح تقرير الخطأ في برنامج الملفات النصية."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "حصل استثناء"
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "تراجع"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "يقوم بالتراجع لنقطة سابقة لكي تستطيع اختيار شيء آخر"
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "تجاهل"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "يتجاهل الاستثناء مما يستمح لك بالاستمرار. قد يسبب هذا المزيد من الاخطاء."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "إعادة المحاولة"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "يعيد تشغيل اللعبة من القرص الصلب, مع محاولة استعمادة آخر نقطة وحفظها عند الإستطاعة."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "يخرج من اللعبة."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "حصل خطأ أثناء تشغيل النص."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "يفتح قائمة اخطاء التشغيل."
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "يفتح ملف errors.txt في برنامج الملفات النصية"
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/arabic/front_page.rpy b/launcher/game/tl/arabic/front_page.rpy
deleted file mode 100644
index 41daf26..0000000
--- a/launcher/game/tl/arabic/front_page.rpy
+++ /dev/null
@@ -1,131 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/front_page.rpy:79
-    old "+ Create New Project"
-    new "+ إبدأ مشروعاً جديداً"
-
-    # game/front_page.rpy:90
-    old "Launch Project"
-    new "تشغيل المشروع"
-
-    # game/front_page.rpy:111
-    old "Tutorial"
-    new "الدليل العملي"
-
-    # game/front_page.rpy:112
-    old "The Question"
-    new "السؤال"
-
-    # game/front_page.rpy:128
-    old "Active Project"
-    new "المشروع الحالي"
-
-    # game/front_page.rpy:136
-    old "Open Directory"
-    new "فتح مجلد"
-
-    # game/front_page.rpy:141
-    old "game"
-    new "اللعبة"
-
-    # game/front_page.rpy:142
-    old "base"
-    new "المشروع كله"
-
-    # game/front_page.rpy:148
-    old "Edit File"
-    new "تحرير ملف"
-
-    # game/front_page.rpy:156
-    old "All script files"
-    new "جميع الملفات النصية"
-
-    # game/front_page.rpy:165
-    old "Navigate Script"
-    new "مهام إضافية"
-
-    # game/front_page.rpy:176
-    old "Check Script (Lint)"
-    new "فحص الملف (لينت)"
-
-    # game/front_page.rpy:177
-    old "Change Theme"
-    new "تغيير المظهر"
-
-    # game/front_page.rpy:178
-    old "Delete Persistent"
-    new "حذف الملفات المؤقتة"
-
-    # game/front_page.rpy:186
-    old "Build Distributions"
-    new "تجميع المشروع للنشر"
-
-    # game/front_page.rpy:188
-    old "Generate Translations"
-    new "تجهيز ملفات للترجمة"
-
-    # game/front_page.rpy:204
-    old "Checking script for potential problems..."
-    new "يتم فحص الملفات لأي اخطاء محتملة..."
-
-    # game/front_page.rpy:219
-    old "Deleting persistent data..."
-    new "يتم الآن حذف الملفات المؤقتة "
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "أندرويد"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "استخراج النص"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/front_page.rpy:144
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-#  Translation updated at 2014-09-30 23:01
-
-translate arabic strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "فتح المجلد [text]"
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "اختر المشروع [text]"
-
-    # game/front_page.rpy:234
-    old "Force Recompile"
-    new "إعادة حزم الملفات"
-
-    # game/front_page.rpy:285
-    old "Recompiling all rpy files into rpyc files..."
-    new "يتم إعادة حزم الملفات من صيغة rpy إلى rpyc..."
-
-
-translate arabic strings:
-
-    # game/front_page.rpy:246
-    old "iOS"
-    new "iOS نظام تشغيل"
-
-# Translation updated at 2015-06-19 08:55
-
-translate arabic strings:
-
-    # game/front_page.rpy:198
-    old "images"
-    new "الصور"
-
diff --git a/launcher/game/tl/arabic/gui.rpy b/launcher/game/tl/arabic/gui.rpy
new file mode 100644
index 0000000..161051d
--- /dev/null
+++ b/launcher/game/tl/arabic/gui.rpy
@@ -0,0 +1,411 @@
+
+translate arabic strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/arabic/interface.rpy b/launcher/game/tl/arabic/interface.rpy
deleted file mode 100644
index 094f995..0000000
--- a/launcher/game/tl/arabic/interface.rpy
+++ /dev/null
@@ -1,90 +0,0 @@
-
-translate arabic strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "المستندات المرفقة"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "موقع رينباي"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "قائمة ألعاب رينباي"
-
-    # game/interface.rpy:92
-    old "About"
-    new "معلومات"
-
-    # game/interface.rpy:99
-    old "update"
-    new "تحديث"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "خيارات"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "خروج"
-
-    # game/interface.rpy:149
-    old "Yes"
-    new "نعم"
-
-    # game/interface.rpy:151
-    old "No"
-    new "لا"
-
-    # game/interface.rpy:181
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "بسبب محدودية التجميع, الاحرف الغير لاتينيه غير مسموح بها في اسم الملف او المجلدات"
-
-    # game/interface.rpy:183
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:248
-    old "ERROR"
-    new "خطأ"
-
-    # game/interface.rpy:280
-    old "While [what!q], an error occured:"
-    new "حصل خطأ أثناء [what!q]"
-
-    # game/interface.rpy:281
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:298
-    old "Text input may not contain the {{ or [[ characters."
-    new "لا يمكن استعمال الرمزان {{ و ]] هنا"
-
-    # game/interface.rpy:303
-    old "File and directory names may not contain / or \\."
-    new "غير مسموح ان يحتوي اسم الملف او المجلد على الرمزان / أو \\"
-
-    # game/interface.rpy:309
-    old "File and directory names must consist of ASCII characters."
-    new "اسم الملف و المجلدات التي تحتويه يجب ان تكون مكتوبة بأحرف ASCII "
-
-    # game/interface.rpy:330
-    old "INFORMATION"
-    new "معلومات"
-
-    # game/interface.rpy:373
-    old "PROCESSING"
-    new "يتم إجراء العمليات"
-
-    # game/interface.rpy:390
-    old "QUESTION"
-    new "سؤال"
-
-
-translate arabic strings:
-
-    # game/interface.rpy:451
-    old "CHOICE"
-    new "إختيار"
-
diff --git a/launcher/game/tl/arabic/ios.rpy b/launcher/game/tl/arabic/ios.rpy
deleted file mode 100644
index 8389c50..0000000
--- a/launcher/game/tl/arabic/ios.rpy
+++ /dev/null
@@ -1,100 +0,0 @@
-#  Translation updated at 2015-03-22 20:50
-
-translate arabic strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "لبناء حزم الـ iOS, الرجاء تحميل البرنامج الخاص بذلك renios و فك الضغط عنه, ثم وضعه في مجلد رينباي الرئيسي. بعد ذلك قم بإعادة تشغيل رينباي."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "لم يتم اختيار المسار الذي سيتم وضع Xcode فيه. الرجاء ضغط زر اختيار المجلد لاختيار المكان الصحيح."
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "لا يوجد مشروع Xcode متطابق مع مشروع رينباي الحالي. الرجاء اختيار زر 'صنع مشروع Xcode' لبدء واحد."
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "يوجد مشروع Xcode. لتحديثه قم بضغط زر 'تحديث مشروع Xcode' ليصبح متطابقاً مع آخر التعديلات على اللعبة’ او قم باستعمال Xcode للبناء و التنصيب."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "إختر المجلد الذي سيكون فيه مشروع Xcode."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "يقوم بصنع مشروع Xcode متطابق مع مشروع رينباي الحالي."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "يقوم بتحديث مشروع Xcode ليصبح متطابقاً مع ملفات اللعبة. يجب أن يتم تكرار هذه العملية مع كل تغيير في اللعبة."
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "يقوم بفتح مشروع Xcode في Xcode."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "يقوم بفتح المجلد الموجود فيه مشاريع Xcode."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "مشروع Xcode موجود مسبقاً. هل تريد تغيير إسم المشروع القديم, و استبداله بالجديد؟"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:229
-    old "iPhone"
-    new "أيفون"
-
-    # game/ios.rpy:233
-    old "iPad"
-    new "أيباد"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "إختر مسار مشاريع Xcode"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "صنع مشروع Xcode"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "تحديث مشروع Xcode"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "إقلاع Xcode"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "فتح مجلد مشاريع Xcode"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "قبل صنع الحزم الخاصة ببرامج iOS يجب ان تقوم بتحميل برنامج renios المساند لرينباي على اجهزة أبل. هل تريد تحميل renios الآن؟"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "مسار مشاريع Xcode"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "الرجاء إختيار المجلد الذي سيتم وضع مشاريع Xcode فيه باستخدام نافذة اختيار المجلد. قد تكون النافذة مفتوحة خلف هذه النافذة."
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "رينباي قام بتحديد مجلد مشاريع Xcode إلى:"
-
diff --git a/launcher/game/tl/arabic/launcher.rpy b/launcher/game/tl/arabic/launcher.rpy
new file mode 100644
index 0000000..0e5a546
--- /dev/null
+++ b/launcher/game/tl/arabic/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate arabic strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "عرض الرخصة"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "اسم الملف"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "إختر اسم لملف الحوار الذي سيتم تكوينه"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "يجب ان ينتهي اسم الملف بالصيغة .rpy"
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "هذا الملف موجود مسبقاً"
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "رينباي يقوم بتشغيل الملفات المنتهية بـ .rpy تلقائياً. لكي تستعمل هذا الملف, اختر له تبويب وافتحه عبر ملف آخر."
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "لبناء ملفات الأندرويد, الرجاء تحميل RAPT, ثم فك الضغط عن الملف ووضعه في مجلد رينباي. قد تحتاج لإعادة تشغيل رينباي ليعمل بشكل صحيح."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "تحتاج لنسخة برمجية من جافا تعتمد الـ 32-بت لتستطيع إنشاء ملفات الأندرويد على نظام الوندوز. حزمة JDK تختلف عن JRE, قد تكون الجافا لديك موجوده لكنها تفتقد الـ JDK. \n\n الرجاء {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}تحميل و تنصيب JDK{/a} ثم إعادة تشغيل رينباي"
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "حزمة الاندرويد RAPT موجوده, لكنك تحتاج لتنصيب Android SDK قبل ان تبدأ بتجهيز حزم للعمل على اندرويد. الرجاء اختيار تنصيب Android SDK لتستطيع ذلك."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "حزمة اندرويد RAPT موجوده, لكن المفتاح لم يتم تجهيزه. الرجاء تكوين مفتاح جديد او استرجاع android.keystore"
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "المشروع الحالي لم يتم تجهيز إعدادته. الرجاء اختيار \"Configure\" لتقوم بتجهيزها قبل بناء الحزمة."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "قم باختيار زر \"Build\" لتقوم بتجهيز المشروع الحالي إلى حزمة قابلة للعمل على اندرويد. او قم بربط جهاز اندرويد و اختيار \"Build & Install\" ليتم تنصيبها مباشرة على الجهاز المطلوب."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "يقوم بمحاكاة جهاز اندرويد هاتفي محمول. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "يقوم بمحاكاة جهاز اندرويد تابلت. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء"
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "يحاول محاكاة نظام تلفزيوني للأندرويد مثل جهاز OUYA او Fire TV. \n\n يتم تخطيط الأزرار لعصا التحكم لتناسب ازرار جهاز التحكم عن بعد. Controller input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "يقوم بتحميل و تنصيب Android SDK والحزم المساندة لها. يعطيك خيار تكوين المفاتيح المطلوبة لتتمكن من استعمال الحزمة."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "يقوم بتجهيز إعدادات الحزمة, رقم النسخة, و معلومات أخرى تتعلق بهذا المشروع."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "يفتح الملف الخاص بمعلومات مفتاح Google Play في محرر النصوص. \n\n هذه الخطوة غير مطلوبة إلا لو كان البرنامج يحتاج إحدى الحوم المساندة expansion APK. الرجاء الإطلاع على ملفات المساعدة للحصول على المزيد من المعلومات."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "يقوم ببناء حزمة للأندرويد."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "يقوم ببناء حزمة للأندرويد, ثم يقوم بتنصيبها على جهاز أندرويد المتصل بحاسوبك."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "يبني الحزمة الخاصة بالأندرويد و يقوم بتنصيبها على جهاز أندرويد متصل بجهازك, ثم يقوم بإقلاع البرنامج على جهاز الأندرويد."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "يتصل بجهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "يفصل الاتصال عن جهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "يجلب قائمة المهام من جعاز الأندرويد و يكتبها في ملف."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "يتم الآن نسخ ملفات الأندرويد إلى المجلد الخاص بالنشر"
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "أندرويد: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "محاكاة"
+
+    # android.rpy:333
+    old "Phone"
+    new "هاتف"
+
+    # android.rpy:337
+    old "Tablet"
+    new "تابلت/ لوحي"
+
+    # android.rpy:341
+    old "Television"
+    new "تلفاز"
+
+    # android.rpy:353
+    old "Build:"
+    new "بناء"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "تنصيب SDK و اختلاق مفاتيح"
+
+    # android.rpy:365
+    old "Configure"
+    new "إعدادات"
+
+    # android.rpy:369
+    old "Build Package"
+    new "بناء الحزمة"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "بناء و تنصيب"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "بناء,تنصيب و إقلاع."
+
+    # android.rpy:388
+    old "Other:"
+    new "آخر:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "الإتصال عن بعد عن طريق ADB"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "قطع إتصال ADB عن بعد"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "قبل ان تصتطيع إنشاء ملفات للأندرويد, عليك ان تقوم بتحميل ملفات RAPT الخاصة بتحويل ملفات رينباي للأندرويد. هل تريد ان تقوم بتحميل الحزمة الآن؟"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "عنوان ADB عن بعد"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "الرجاء إدخال عنوان الأي بي ورقم المنفذ المطلوب للإتصال, على شكل \"192.168.1.143:5555\". الرجاء العودة لدليل المستخدم الخاص بجهازك لتعرف إن كان يدعم الإتصال عن بعد للـ ADB و إن كان قادراً على ذلك, ستجد العنوان و المنفذ المطلوبان."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "عنوان ِADB خاطيء"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "العنوان يجب ان يحتوي على علامة ':' واحده فقط لا غير"
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "الخادم يجب ان لا يحتوي على مساحات فارغة"
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "يجب ان يكون العنوان مكون من أرقام فقط"
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "يتم النسخ من الجهاز لمعلومات Logcat"
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "لم يتمكن رينباي من تشغيل بايثون باستخدام tkinter لاختيار المجلد. الرجال تنصيب حزمة tkinter أو python-tk."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "لم يتمكن رينباي من تغيير المظهر, ربما ملف options.rpy قد تغير بشكل كبير"
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "إختر المظهر"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "المظهر"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "توليفة الألوان"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "استمرار"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "معلومات"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "يتم فحص الملفات..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "فشل بناء ملفات النشر. build.directory_name يجب أن لا يحتوي على مساحات فارغة, فواصل, او فواصل منقوطة في إسم المجلد "
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "لم يتم اختيار اي حزمة, لم يحصل اي شيء."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "يتم فحص ملفات رينباي..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "تم الإنتهاء من تكوين رزمة البيانات لنشر اللعبة. بسبب اختلاف نظام الملفات في الأنظمة التشغيلية ماك و لينوكس, لا يمكن فك الضغط عن الرزمة الخاصة بتلك الأنظمة على نظام وندوز."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "يتم أرشفة الملفات..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "يتم كتابة ملفات [variant] [format]"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Making the [variant] update zsync file."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "تم انهاء {b}[complete]{/b} من عدد {b}[total]{/b} من الملفات."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "تجميع الملفات تجهيزاً للنشر: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "اسم المجلد:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "اسم الملف التشغيلي:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "الأوامر:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "تحرير options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "إضافة بند 'مِن' إلى أمر الجلب, مرة واحدة"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "إعادة تحميل"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "بناء الرزمة البيانية:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "خيارات:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "بناء تحديثات:"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "إضافة بنود 'مِن' إلى أمر الجلب"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "إعادة حزم الملفات"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "بناء"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "إضافة بنود 'مِن' إلى أوامر الجلب التي لا تحتوي عليها."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "تم ايجاد بعض الاخطاء في المشروع. الرجاء التأكد من خلو المشروع من الأخطاء قبل نشره بشكل نهائي."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "مشروعك يخلو من معلومات النشر, هل ترغب في إضافة هذه المعلومات في نهاية ملف options.rpy؟"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية. على نظام لينوكس, Editra يحتاج wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "قد يكون سبب ذلك ان wxPython غير موجود في نظام التشغيل لديك"
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "مطلوب تحميل ملف بحجم  22 ميغا بايت."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "محرر متخصص يستعمل لغة جافا"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "مطلوب تحميل ملف بحجم 1.8 ميغا بايت."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "قد يكون السبب ان الجافا غير موجوده على هذا الجهاز."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "يقوم بفتح البرنامج المسؤول عن تحرير ملفات .rpy في نظامك التشغيلي"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "يمنع رينباي من فتح اي محرر نصوص"
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "حصل استثناء اثناء فتح المحرر: \n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "الرجاء اختيار المحرر"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "محرر النصوص هو برنامج يساعدك على تعديل ملفات رينباي البرمجية والحوار. هنا, يمكنك اختيار المحرر الذي سيستعلمه رينباي. إذا لم يكن لديك مسبقاً, سيتم تحميله و تنصيبه بشكل اوتوماتيكي."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "إلغاء الأمر"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "فتح المجلد [text]"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "إعادة تحميل"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ إبدأ مشروعاً جديداً"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "تشغيل المشروع"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "اختر المشروع [text]"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "الدليل العملي"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "السؤال"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "المشروع الحالي"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "فتح مجلد"
+
+    # front_page.rpy:195
+    old "game"
+    new "اللعبة"
+
+    # front_page.rpy:196
+    old "base"
+    new "المشروع كله"
+
+    # front_page.rpy:197
+    old "images"
+    new "الصور"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "تحرير ملف"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "جميع الملفات النصية"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "مهام إضافية"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "فحص الملف (لينت)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "تغيير المظهر"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "حذف الملفات المؤقتة"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "تجميع المشروع للنشر"
+
+    # front_page.rpy:253
+    old "Android"
+    new "أندرويد"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS نظام تشغيل"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "تجهيز ملفات للترجمة"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "استخراج النص"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "يتم فحص الملفات لأي اخطاء محتملة..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "يتم الآن حذف الملفات المؤقتة "
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "يتم إعادة حزم الملفات من صيغة rpy إلى rpyc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "اسم المشروع"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "الرجاء اختيار اسم لمشروعك الجديد"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "لا يمكن ان يكون اسم المشروع فارغاً"
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "الاسم [project_name!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "المستندات المرفقة"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "موقع رينباي"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "قائمة ألعاب رينباي"
+
+    # interface.rpy:117
+    old "update"
+    new "تحديث"
+
+    # interface.rpy:119
+    old "preferences"
+    new "خيارات"
+
+    # interface.rpy:120
+    old "quit"
+    new "خروج"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "بسبب محدودية التجميع, الاحرف الغير لاتينيه غير مسموح بها في اسم الملف او المجلدات"
+
+    # interface.rpy:327
+    old "ERROR"
+    new "خطأ"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "حصل خطأ أثناء [what!q]"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "لا يمكن استعمال الرمزان {{ و ]] هنا"
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "غير مسموح ان يحتوي اسم الملف او المجلد على الرمزان / أو \\"
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "اسم الملف و المجلدات التي تحتويه يجب ان تكون مكتوبة بأحرف ASCII "
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "يتم إجراء العمليات"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "سؤال"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "إختيار"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "لبناء حزم الـ iOS, الرجاء تحميل البرنامج الخاص بذلك renios و فك الضغط عنه, ثم وضعه في مجلد رينباي الرئيسي. بعد ذلك قم بإعادة تشغيل رينباي."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "لم يتم اختيار المسار الذي سيتم وضع Xcode فيه. الرجاء ضغط زر اختيار المجلد لاختيار المكان الصحيح."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "لا يوجد مشروع Xcode متطابق مع مشروع رينباي الحالي. الرجاء اختيار زر 'صنع مشروع Xcode' لبدء واحد."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "يوجد مشروع Xcode. لتحديثه قم بضغط زر 'تحديث مشروع Xcode' ليصبح متطابقاً مع آخر التعديلات على اللعبة’ او قم باستعمال Xcode للبناء و التنصيب."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "إختر المجلد الذي سيكون فيه مشروع Xcode."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "يقوم بصنع مشروع Xcode متطابق مع مشروع رينباي الحالي."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "يقوم بتحديث مشروع Xcode ليصبح متطابقاً مع ملفات اللعبة. يجب أن يتم تكرار هذه العملية مع كل تغيير في اللعبة."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "يقوم بفتح مشروع Xcode في Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "يقوم بفتح المجلد الموجود فيه مشاريع Xcode."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "مشروع Xcode موجود مسبقاً. هل تريد تغيير إسم المشروع القديم, و استبداله بالجديد؟"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "أيفون"
+
+    # ios.rpy:244
+    old "iPad"
+    new "أيباد"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "إختر مسار مشاريع Xcode"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "صنع مشروع Xcode"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "تحديث مشروع Xcode"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "إقلاع Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "فتح مجلد مشاريع Xcode"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "قبل صنع الحزم الخاصة ببرامج iOS يجب ان تقوم بتحميل برنامج renios المساند لرينباي على اجهزة أبل. هل تريد تحميل renios الآن؟"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "مسار مشاريع Xcode"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "الرجاء إختيار المجلد الذي سيتم وضع مشاريع Xcode فيه باستخدام نافذة اختيار المجلد. قد تكون النافذة مفتوحة خلف هذه النافذة."
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "رينباي قام بتحديد مجلد مشاريع Xcode إلى:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "الذهاب إلى: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "الترتيب:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "أبجدي"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "ملف ملف"
+
+    # navigation.rpy:182
+    old "natural"
+    new "طبيعي"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "فئة:"
+
+    # navigation.rpy:196
+    old "files"
+    new "ملفات"
+
+    # navigation.rpy:197
+    old "labels"
+    new "وسم"
+
+    # navigation.rpy:198
+    old "defines"
+    new "تحديد"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "التحول"
+
+    # navigation.rpy:200
+    old "screens"
+    new "النوافذ"
+
+    # navigation.rpy:201
+    old "callables"
+    new "ما يمكن استجلابه"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODOs"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+إضافة ملف نص"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "قائمة الأسماء فارغة"
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "لم يتم تحديد مجلد المشاريع, سيتم الإلغاء"
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "الرجاء اختيار تصميم المظهر للمشروع"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "الرجاء اختيار القالب المطلوب للمشروع الجديد. هذه القوالب تقوم بتجهيز اتجاه النص و اللغه المستخدمة في الواجهة لتسهل عملية البدء. إذا لم تكن لغتك مدعومة الرجاء اختيار اللغة الانجليزية."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "خيارات برنامج التشغيل"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "دليل المشاريع:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "مجلد المشاريع [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "غير محدد"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "محرر الملفات النصية:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "محرر النصوص [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "مصدر التحديثات:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "خيارات استعراض المجلدات"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "تضمين الأسماء الخاصة"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "تضمين اسماء المكتبات"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "خيارات برنامج التشغيل:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "الإستعراض بواسطة قطع الجهاز الداخلية"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "عرض القوالب"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "عرض قسم تعديل الملف"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "خط كبير"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "الإستعراض بواسطة البرمجيات المتوفرة"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "فتح الواجهة التشغيلية كمشروع"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "اللغة:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "عند إجراء أي تغييرات في ملف الحوار, يمكنك ضغط shift+R لترى التغييرات داخل اللعبة"
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "إضغط shift+O للدخول على لوحة التحكم"
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "إضغط shift+D للدخول على لوحة تحكم المبرمج"
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "هل قمت بعمل نسخة احتياطية من مشاريعك مؤخراً؟"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "لم تنجح محاولة إقلاع المشروع"
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "الرجاء التأكد من سلامة إقلاع المشروع قبل تشغيل هذا الأمر البرمجي"
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "رينباي يقوم بفحص المشروع"
+
+    # project.rpy:568
+    old "Launching"
+    new "جاري الإقلاع"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "سياق مجلدات المشاريع"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "الرجاء اختيار نسق المشاريع من الصفحة الخاصة بذلك. \n{b}قد تكون النافذة ظهرت خلف هذه النافذة.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "سيقوم البرنامج بفحص المجلد هذا لإيجاد المشاريع السابقة, أو ليضع المشاريع الجديده فيه, و ايضاً لوضع المشاريع المنتهيه عند تجهيزها للنشر."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "رينباي قام بتحديد مجلد المشاريع إلى المكان التالي:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "صنع خانات فارغة للترجمات"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "يقوم رينباي بتصنيع ملفات الترجمة..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "انتهى رينباي من صناعة ملفات الترجمة إلى [language]"
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "رينباي يقوم باستخراج الحوار إلى ملف نص"
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "الرجاء اختيار طريقة التحديث"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "طريقة التحديث تحدد لبرنامج رينباي اي المواقع يستخدم لإيجاد النسخ الجديدة. الرجاء اختيار الطريقة التي تناسبك."
+
+    # updater.rpy:91
+    old "Release"
+    new "نسخة مكتملة"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}موصى به.{/b} نسخة رينباي التي يفضل استعمالها مع كل الالعاب الجديدة."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "نسخة مبدأية"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "عينة من نسخة رينباي القادمة تسمح لك بتجربة الإضافات الجديدة. لا ننصح باستعمالها لصناعة ألعاب معدة للنشر."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "نسخة تجريبية"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "النسخ التجريبية من رينباي. الأفضل ألا تستعمل هذه النسخ إلا لو طلب منك ذلك احد مبرمجي رينباي"
+
+    # updater.rpy:126
+    old "Nightly"
+    new "مسائي"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "أحدث نسخة طازجة من رينباي التجريبي, قد يحتوي على آخر مستجدات رينباي و قد لا يعمل مطلقاً"
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "حصل خطأ:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "جاري البحث عن تحديثات"
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "نسخة رينباي التي لديك هي الأحدث."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "يتم التجهيز لتنزيل التحديث."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "يتم تنزيل التحديث."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "يتم فك الضغط عن التحديث."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "يتم ختم العملية"
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "تم تنصيب التحديثات بنجاح, سيتم إعادة تشغيل رينباي الآن."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "تم تنصيب التحديثات."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "تم إلغاء التحديث."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "تحديثات رينباي."
+
+    # updater.rpy:195
+    old "Proceed"
+    new "استمرار"
+
diff --git a/launcher/game/tl/arabic/navigation.rpy b/launcher/game/tl/arabic/navigation.rpy
deleted file mode 100644
index e419e36..0000000
--- a/launcher/game/tl/arabic/navigation.rpy
+++ /dev/null
@@ -1,71 +0,0 @@
-
-translate arabic strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "الذهاب إلى: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "الترتيب:"
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "أبجدي"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "ملف ملف"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "طبيعي"
-
-    # game/navigation.rpy:168
-    old "refresh"
-    new "إعادة تحميل"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "فئة:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "ملفات"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "وسم"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "تحديد"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "التحول"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "النوافذ"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "ما يمكن استجلابه"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODOs"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+إضافة ملف نص"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "قائمة الأسماء فارغة"
-
diff --git a/launcher/game/tl/arabic/new_project.rpy b/launcher/game/tl/arabic/new_project.rpy
deleted file mode 100644
index 12d5a2b..0000000
--- a/launcher/game/tl/arabic/new_project.rpy
+++ /dev/null
@@ -1,48 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "الرجاء اختيار تصميم المظهر للمشروع"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
-    new "الرجاء اختيار التصميم الذي ترغبه لمشروعك الجديد. رينباي يأتي بعدة تصاميم قياسية يمكنك التعديل عليها لاحقاً."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "اسم المشروع"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "الرجاء اختيار اسم لمشروعك الجديد"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "لا يمكن ان يكون اسم المشروع فارغاً"
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "الاسم [project_name!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
-
-# : Translation updated at 2013-11-17 23:18
-
-translate arabic strings:
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "الرجاء اختيار القالب المطلوب للمشروع الجديد. هذه القوالب تقوم بتجهيز اتجاه النص و اللغه المستخدمة في الواجهة لتسهل عملية البدء. إذا لم تكن لغتك مدعومة الرجاء اختيار اللغة الانجليزية."
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "لم يتم تحديد مجلد المشاريع, سيتم الإلغاء"
-
diff --git a/launcher/game/tl/arabic/obsolete.rpy b/launcher/game/tl/arabic/obsolete.rpy
new file mode 100644
index 0000000..5b53ac7
--- /dev/null
+++ b/launcher/game/tl/arabic/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate arabic strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "خيارات عصى التحكم"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "خانة فارغة"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "السابق"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "التالي"
+
diff --git a/launcher/game/tl/arabic/options.rpy b/launcher/game/tl/arabic/options.rpy
new file mode 100644
index 0000000..fd65f14
--- /dev/null
+++ b/launcher/game/tl/arabic/options.rpy
@@ -0,0 +1,195 @@
+
+translate arabic strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/arabic/preferences.rpy b/launcher/game/tl/arabic/preferences.rpy
deleted file mode 100644
index 90f77de..0000000
--- a/launcher/game/tl/arabic/preferences.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "خيارات برنامج التشغيل"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "دليل المشاريع:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "غير محدد"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "محرر الملفات النصية:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "مصدر التحديثات:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "خيارات استعراض المجلدات"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "تضمين الأسماء الخاصة"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "تضمين اسماء المكتبات"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "خيارات برنامج التشغيل:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "الإستعراض بواسطة قطع الجهاز الداخلية"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "الإستعراض بواسطة البرمجيات المتوفرة"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "فتح الواجهة التشغيلية كمشروع"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "اللغة:"
-
-#  Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/preferences.rpy:164
-    old "Show templates"
-    new "عرض القوالب"
-
-#  Translation updated at 2014-09-30 23:01
-
-translate arabic strings:
-
-    # game/preferences.rpy:91
-    old "Projects directory: [text]"
-    new "مجلد المشاريع [text]"
-
-    # game/preferences.rpy:114
-    old "Text editor: [text]"
-    new "محرر النصوص [text]"
-
-    # game/preferences.rpy:171
-    old "Large fonts"
-    new "خط كبير"
-
-
-translate arabic strings:
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "عرض قسم تعديل الملف"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "صنع خانات فارغة للترجمات"
-
diff --git a/launcher/game/tl/arabic/project.rpy b/launcher/game/tl/arabic/project.rpy
deleted file mode 100644
index 805e42a..0000000
--- a/launcher/game/tl/arabic/project.rpy
+++ /dev/null
@@ -1,68 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/project.rpy:196
-    old "Ren'Py is scanning the project..."
-    new "رينباي يقوم بفحص المشروع"
-
-    # game/project.rpy:485
-    old "PROJECTS DIRECTORY"
-    new "سياق مجلدات المشاريع"
-
-    # game/project.rpy:485
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "الرجاء اختيار نسق المشاريع من الصفحة الخاصة بذلك. \n{b}قد تكون النافذة ظهرت خلف هذه النافذة.{/b}"
-
-    # game/project.rpy:485
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "سيقوم البرنامج بفحص المجلد هذا لإيجاد المشاريع السابقة, أو ليضع المشاريع الجديده فيه, و ايضاً لوضع المشاريع المنتهيه عند تجهيزها للنشر."
-
-    # game/project.rpy:525
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "رينباي لم يستطع تشغيل برمجيات بايثون للبحث عن مجلد المشاريع."
-
-    # game/project.rpy:529
-    old "Ren'Py has set the projects directory to:"
-    new "رينباي قام بتحديد مجلد المشاريع إلى المكان التالي:"
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/project.rpy:48
-    old "After making changes to the script, press shift+R to reload your game."
-    new "عند إجراء أي تغييرات في ملف الحوار, يمكنك ضغط shift+R لترى التغييرات داخل اللعبة"
-
-    # game/project.rpy:49
-    old "Press shift+O (the letter) to access the console."
-    new "إضغط shift+O للدخول على لوحة التحكم"
-
-    # game/project.rpy:50
-    old "Press shift+D to access the developer menu."
-    new "إضغط shift+D للدخول على لوحة تحكم المبرمج"
-
-    # game/project.rpy:219
-    old "Launching the project failed."
-    new "لم تنجح محاولة إقلاع المشروع"
-
-    # game/project.rpy:219
-    old "Please ensure that your project launches normally before running this command."
-    new "الرجاء التأكد من سلامة إقلاع المشروع قبل تشغيل هذا الأمر البرمجي"
-
-    # game/project.rpy:516
-    old "Launching"
-    new "جاري الإقلاع"
-
-    # game/project.rpy:585
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "رينباي لم يتمكن من تشغيل بايثون مع tkinter لكي يختار مجلد المشاريع, الرجاء تنصيب Python-tk او tkinter"
-
-# Translation updated at 2014-09-30 23:01
-
-translate arabic strings:
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "هل قمت بعمل نسخة احتياطية من مشاريعك مؤخراً؟"
-
diff --git a/launcher/game/tl/arabic/screens.rpy b/launcher/game/tl/arabic/screens.rpy
new file mode 100644
index 0000000..ad072ab
--- /dev/null
+++ b/launcher/game/tl/arabic/screens.rpy
@@ -0,0 +1,643 @@
+
+translate arabic strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "عودة"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "تخطي"
+
+    # screens.rpy:264
+    old "Auto"
+    new "تلقائي"
+
+    # screens.rpy:265
+    old "Save"
+    new "حفظ"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "حفظ سريع"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "استرجاع سريع"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "خيارات"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "خيارات"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "القائمة الرئيسية"
+
+    # screens.rpy:328
+    old "About"
+    new "معلومات"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "مساعدة"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "خروج"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "عودة"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "عرض"
+
+    # screens.rpy:739
+    old "Window"
+    new "نافذة"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "ملء الشاشة"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "بعد الإختيار"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "التأثيرات البصرية"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "سرعة النص"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "وقت التسريع التلقائي"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "مستوى الموسيقى"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "مستوى الأصوات"
+
+    # screens.rpy:791
+    old "Test"
+    new "تجربة"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "مستوى صوت الكلام"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "نعم"
+
+    # screens.rpy:1162
+    old "No"
+    new "لا"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/arabic/script.rpym b/launcher/game/tl/arabic/script.rpym
new file mode 100644
index 0000000..a083030
--- /dev/null
+++ b/launcher/game/tl/arabic/script.rpym
@@ -0,0 +1,21 @@
+# You can place the script of your game in this file.
+
+# Declare images below this line, using the image statement.
+# eg. image eileen happy = "eileen_happy.png"
+
+# Declare characters used by this game.
+define e = Character('إيلين', color="#c8ffc8")
+
+init python:
+    if not persistent.default_language_set:
+        persistent.default_language_set = True
+        _preferences.language = "arabic"
+
+# The game starts here.
+label start:
+
+    e "لقد بدأت حكاية رينباي جديدة."
+
+    e "كل ما عليك فعله هو إضافة نصوص و صور و إرسالها للعالم!"
+
+    return
diff --git a/launcher/game/tl/arabic/style.rpy b/launcher/game/tl/arabic/style.rpy
index 8b77c10..947681a 100644
--- a/launcher/game/tl/arabic/style.rpy
+++ b/launcher/game/tl/arabic/style.rpy
@@ -1,16 +1,10 @@
 translate arabic python:
-    al = "DejaVuSans.ttf"
-    style.l_default.font = al
-    style.l_default.size = 16
-    style.l_button_text.selected_font = al
-    style.l_button_text.selected_bold = True
-    style.l_link_text.font = al
-    style.l_alternate_text.font = al
-    style.l_navigation_button_text.font = al
-    style.l_navigation_text.font = al
-    style.l_navigation_text.bold = True
-    style.l_checkbox_text.selected_font = al
-    style.l_nonbox_text.selected_font = al
-    style.hyperlink_text.font = al
+    gui.REGULAR_FONT = "DejaVuSans.ttf"
+    gui.LIGHT_FONT = "DejaVuSans.ttf"
+    gui.FONT_SCALE = .9
+    gui.REGULAR_BOLD = True
 
     config.rtl = True
+
+init python:
+    translate_define("arabic", "config.rtl", "True")
diff --git a/launcher/game/tl/arabic/translations.rpy b/launcher/game/tl/arabic/translations.rpy
deleted file mode 100644
index 92436ab..0000000
--- a/launcher/game/tl/arabic/translations.rpy
+++ /dev/null
@@ -1,38 +0,0 @@
-
-translate arabic strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "صنع او تحديث الترجمات"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "الرجاء كتابة اسم اللغة التي ستقوم بالترجمة إليها و الضغط على زر انتر"
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "لا يمكن ان يكون اسم اللغة فارغاً"
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "يقوم رينباي بتصنيع ملفات الترجمة..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "انتهى رينباي من صناعة ملفات الترجمة إلى [language]"
-
-
-translate arabic strings:
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "ما هي الصيغة التي تريدها للنص المستخرج؟"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "رينباي يقوم باستخراج الحوار إلى ملف نص"
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "رينباي انتهى من استخراج الحوار. الحوار المستخرج يوجد الآن في [format] في المجلد الرئيسي"
-
diff --git a/launcher/game/tl/arabic/updater.rpy b/launcher/game/tl/arabic/updater.rpy
deleted file mode 100644
index a296907..0000000
--- a/launcher/game/tl/arabic/updater.rpy
+++ /dev/null
@@ -1,100 +0,0 @@
-# : Translation updated at 2013-04-30 07:54
-
-translate arabic strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "الرجاء اختيار طريقة التحديث"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "طريقة التحديث تحدد لبرنامج رينباي اي المواقع يستخدم لإيجاد النسخ الجديدة. الرجاء اختيار الطريقة التي تناسبك."
-
-    # game/updater.rpy:70
-    old "Release"
-    new "نسخة مكتملة"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}موصى به.{/b} نسخة رينباي التي يفضل استعمالها مع كل الالعاب الجديدة."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "نسخة مبدأية"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "عينة من نسخة رينباي القادمة تسمح لك بتجربة الإضافات الجديدة. لا ننصح باستعمالها لصناعة ألعاب معدة للنشر."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "نسخة تجريبية"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "النسخ التجريبية من رينباي. الأفضل ألا تستعمل هذه النسخ إلا لو طلب منك ذلك احد مبرمجي رينباي"
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "حصل خطأ:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "يتم البحث عن تحديثات."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "نسخة رينباي التي لديك هي الأحدث."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "يتم التجهيز لتنزيل التحديث."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "يتم تنزيل التحديث."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "يتم فك الضغط عن التحديث."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "اللمسات النهائية."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "تم تنصيب التحديثات بنجاح, سيتم إعادة تشغيل رينباي الآن."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "تم تنصيب التحديثات."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "تم إلغاء التحديث."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "تحديثات رينباي."
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "استمرار."
-
-# : Translation updated at 2014-04-17 13:01
-
-translate arabic strings:
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "مسائي"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "أحدث نسخة طازجة من رينباي التجريبي, قد يحتوي على آخر مستجدات رينباي و قد لا يعمل مطلقاً"
-
diff --git a/launcher/game/tl/finnish/about.rpy b/launcher/game/tl/finnish/about.rpy
deleted file mode 100644
index 515ec1c..0000000
--- a/launcher/game/tl/finnish/about.rpy
+++ /dev/null
@@ -1,14 +0,0 @@
-
-translate finnish strings:
-
-    # game/about.rpy:39
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:43
-    old "View license"
-    new "Näytä lisenssi"
-
-    # game/about.rpy:45
-    old "Back"
-    new "Takaisin"
diff --git a/launcher/game/tl/finnish/add_file.rpy b/launcher/game/tl/finnish/add_file.rpy
deleted file mode 100644
index 31da7fc..0000000
--- a/launcher/game/tl/finnish/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate finnish strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "TIEDOSTONIMI"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "Kirjoita skriptitiedoston nimi, jonka haluat luoda."
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "Tiedostolla on oltava .rpy-tunniste."
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "Tämänniminen tiedosto on jo olemassa."
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py lataa automaattisesti kaikki scriptitiedostot, joilla on .rpy pääte. Käyttääksesi tätä\n# tiedostoa, luo label ja hyppää siihen toisesta tiedostosta.\n"
-
diff --git a/launcher/game/tl/finnish/android.rpy b/launcher/game/tl/finnish/android.rpy
deleted file mode 100644
index 2046a41..0000000
--- a/launcher/game/tl/finnish/android.rpy
+++ /dev/null
@@ -1,171 +0,0 @@
-
-translate finnish strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Luodaksesi Android-sovelluksia, ole hyvä ja lataa RAPT, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "32-bittinen Javan kehitystyökalu vaaditaan Android-sovellusten luomiseen Windowsilla. JDK on erilainen kuin JRE, joten on mahdollista, että sinulla on Java ilman JDK:ta.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Lataa ja asenna JDK{/a}, ja sen jälkeen käynnistä Ren'Py uudelleen."
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT on asennettu, mutta sinun on asennettava Android SDK ennen kuin voit luoda Android-sovelluksia. Valitse 'Asenna SDK' tehdäksesi tämän."
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT on asennettu, mutta avainta ei ole konfiguroitu. Luo uusi avain, tai palauta android.keystore."
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Valittua projektia ei ole konfiguroitu. Käytä \"Konfigurointi\" -toimintoa konfiguroidaksesi sen ennen sovelluksen kokoamista."
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Valitse \"Kokoa\" kootaksesi projektin, tai kiinnitä Android-laite ja valitse \"Kokoa ja asenna\" kootaksesi ja asentaaksesi sen laitteeseen."
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Ren'Py pyrkii emuloimaan Android-puhelinta.\n\nKosketus valintaa emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Ren'Py pyrkii emuloimaan Android-tablettia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Ren'Py pyrkii emuloimaan televisiopohjaista Android-konsolia, kuten OUYA tai Fire TV.\n\nOhjainnäppäimet ovat nuolinäppäimet, Enter toimii valitsijana, Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Lataa ja asentaa Android SDK:n ja tarvittavat lisäpaketit. Lisäksi, voidaan käyttää avainten luomiseen."
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "Konfiguroi paketin nimen, version sekä kaiken muun projektia koskevan tiedon."
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Avaa tiedoston, joka sisältää Google Play -avaimet, editorissa.\n\nTätä tarvitaan vain, jos sovellus käyttää laajennus-APK:ta. Lue dokumentaatio saadaksesi lisätietoa."
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "Kokoaa Android-sovelluksen."
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Kokoaa Android-sovelluksen, ja asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen."
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Kokoaa Android-sovelluksen, asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen ja käynnistää sovelluksen laitteessa."
-
-    # game/android.rpy:48
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Yhdistää Android-laitteeseen, joka pyörittää ADB:tä TCP/IP -tilassa."
-
-    # game/android.rpy:49
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Katkaisee yhteyden Android-laitteeseen, joka pyörittää ADB:tä TCP/IP -tilassa."
-
-    # game/android.rpy:50
-    old "Retrieves the log from the Android device and writes it to a file."
-    new "Noutaa lokitiedot Android-laitteesta ja luo niistä tiedoston."
-
-    # game/android.rpy:240
-    old "Copying Android files to distributions directory."
-    new "Kopioidaan Android-tiedostoja jakelukansioon."
-
-    # game/android.rpy:304
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:324
-    old "Emulation:"
-    new "Emulointi:"
-
-    # game/android.rpy:333
-    old "Phone"
-    new "Puhelin"
-
-    # game/android.rpy:337
-    old "Tablet"
-    new "Tabletti"
-
-    # game/android.rpy:341
-    old "Television"
-    new "Televisio"
-
-    # game/android.rpy:353
-    old "Build:"
-    new "Kokoa:"
-
-    # game/android.rpy:361
-    old "Install SDK & Create Keys"
-    new "Asenna SDK & Luo avaimia"
-
-    # game/android.rpy:365
-    old "Configure"
-    new "Muokkaa asetuksia"
-
-    # game/android.rpy:369
-    old "Build Package"
-    new "Kokoa sovellus"
-
-    # game/android.rpy:373
-    old "Build & Install"
-    new "Kokoa & asenna"
-
-    # game/android.rpy:377
-    old "Build, Install & Launch"
-    new "Kokoa, asenna & käynnistä"
-
-    # game/android.rpy:388
-    old "Other:"
-    new "Muita:"
-
-    # game/android.rpy:396
-    old "Remote ADB Connect"
-    new "Langaton ADB-yhdistäminen"
-
-    # game/android.rpy:400
-    old "Remote ADB Disconnect"
-    new "Langaton ADB-katkaisu"
-
-    # game/android.rpy:404
-    old "Logcat"
-    new "Logcat"
-
-    # game/android.rpy:437
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Ennen Android-sovellusten kokoamista, sinun on ladattava RAPT (Ren'Py Android Packaging Tool). Haluatko ladata RAPT:in nyt?"
-
-    # game/android.rpy:490
-    old "Remote ADB Address"
-    new "Langaton ADB-osoite"
-
-    # game/android.rpy:490
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Syötä yhdistettävän kohteen IP-osoite ja porttinumero, esimerkin \"192.168.1.143:5555\" mukaisesti. Selvitä laitteesi tiedoista kykeneekö se langattomaan ADB:hen, ja jos näin on, käytettävä osoite ja portti."
-
-    # game/android.rpy:502
-    old "Invalid remote ADB address"
-    new "Virheellinen langaton ADB-osoite"
-
-    # game/android.rpy:502
-    old "The address must contain one exactly one ':'."
-    new "Osoitteeseen täytyy kuulua tasan yksi ':'."
-
-    # game/android.rpy:506
-    old "The host may not contain whitespace."
-    new "IP-osoite ei saa sisältää välilyöntejä."
-
-    # game/android.rpy:512
-    old "The port must be a number."
-    new "Portin on oltava numero."
-
-    # game/android.rpy:538
-    old "Retrieving logcat information from device."
-    new "Noudetaan logcat-tietoja laitteesta."
-
diff --git a/launcher/game/tl/finnish/choose_directory.rpy b/launcher/game/tl/finnish/choose_directory.rpy
deleted file mode 100644
index 7115233..0000000
--- a/launcher/game/tl/finnish/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate finnish strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py ei kyennyt suorittamaan pythonia tkinterillä valitakseen kansion. Ole hyvä ja asenna python-tk tai tkinter-paketti."
-
diff --git a/launcher/game/tl/finnish/choose_theme.rpy b/launcher/game/tl/finnish/choose_theme.rpy
deleted file mode 100644
index 7e8f67d..0000000
--- a/launcher/game/tl/finnish/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate finnish strings:
-
-    # game/choose_theme.rpy:303
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Teeman vaihto epäonnistui. Options.rpy-tiedostoa on ehkä muokattu liikaa."
-
-    # game/choose_theme.rpy:368
-    old "Display"
-    new "Näyttö"
-
-    # game/choose_theme.rpy:369
-    old "Window"
-    new "Ikkuna"
-
-    # game/choose_theme.rpy:370
-    old "Fullscreen"
-    new "Koko näyttö"
-
-    # game/choose_theme.rpy:371
-    old "Planetarium"
-    new "Planetaario"
-
-    # game/choose_theme.rpy:378
-    old "Sound Volume"
-    new "Äänenvoimakkuus"
-
-    # game/choose_theme.rpy:426
-    old "Choose Theme"
-    new "Valitse teema"
-
-    # game/choose_theme.rpy:439
-    old "Theme"
-    new "Teema"
-
-    # game/choose_theme.rpy:464
-    old "Color Scheme"
-    new "Väriskaala"
-
-    # game/choose_theme.rpy:496
-    old "Continue"
-    new "Jatka"
-
diff --git a/launcher/game/tl/finnish/common.rpy b/launcher/game/tl/finnish/common.rpy
index 4364fa3..07a9234 100644
--- a/launcher/game/tl/finnish/common.rpy
+++ b/launcher/game/tl/finnish/common.rpy
@@ -1,775 +1,335 @@
 
 translate finnish strings:
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Monday"
     new "{#weekday}Maanatai"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Tuesday"
     new "{#weekday}Tiistai"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Wednesday"
     new "{#weekday}Keskiviikko"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Thursday"
     new "{#weekday}Torstai"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Friday"
     new "{#weekday}Perjantai"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Saturday"
     new "{#weekday}Lauantai"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Sunday"
     new "{#weekday}Sunnuntai"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Mon"
     new "{#weekday_short}Ma"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Tue"
     new "{#weekday_short}Ti"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Wed"
     new "{#weekday_short}Ke"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Thu"
     new "{#weekday_short}To"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Fri"
     new "{#weekday_short}Pe"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sat"
     new "{#weekday_short}La"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sun"
     new "{#weekday_short}Su"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}January"
     new "{#month}Tammikuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}February"
     new "{#month}Helmikuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}March"
     new "{#month}Maaliskuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}April"
     new "{#month}Huhtikuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}May"
     new "{#month}Toukokuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}June"
     new "{#month}Kesäkuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}July"
     new "{#month}Heinäkuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}August"
     new "{#month}Elokuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}September"
     new "{#month}Syyskuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}October"
     new "{#month}Lokakuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}November"
     new "{#month}Marraskuu"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}December"
     new "{#month}Joulukuu"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jan"
     new "{#month_short}Tammi"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Feb"
     new "{#month_short}Helmi"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Mar"
     new "{#month_short}Maalis"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Apr"
     new "{#month_short}Huhti"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}May"
     new "{#month_short}Touko"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jun"
     new "{#month_short}Kesä"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jul"
     new "{#month_short}Heinä"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Aug"
     new "{#month_short}Elo"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Sep"
     new "{#month_short}Syys"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Oct"
     new "{#month_short}Loka"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Nov"
     new "{#month_short}Marras"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Dec"
     new "{#month_short}Joulu"
 
-    # renpy/common/00action_file.rpy:235
+    # 00action_file.rpy:235
     old "%b %d, %H:%M"
     new "%b %d, %H:%M"
 
-    # renpy/common/00action_file.rpy:550
-    old "Page {}"
-    new "Sivu {}"
-
-    # renpy/common/00action_file.rpy:550
-    old "Automatic saves"
-    new "Automaattiset tallennukset"
-
-    # renpy/common/00action_file.rpy:550
-    old "Quick saves"
-    new "Pikatallennukset"
-
-    # renpy/common/00action_file.rpy:793
+    # 00action_file.rpy:820
     old "Quick save complete."
     new "Pikatallennus suoritettu."
 
-translate finnish strings:
-
-    # renpy/common/00console.rpy:180
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)n konsoli, alunperin tehneet Shiz, C ja delta.\n"
-
-    # renpy/common/00console.rpy:181
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Paina <esc> poistuaksesi konsolista. Käytä komentoa help saadaksesi apua."
-
-    # renpy/common/00console.rpy:185
-    old "Ren'Py script enabled."
-    new "Ren'Py-skriptikieli käytössä."
-
-    # renpy/common/00console.rpy:187
-    old "Ren'Py script disabled."
-    new "Ren'Py-skriptikieli poissa käytöstä."
-
-    # renpy/common/00console.rpy:393
-    old "help: show this help"
-    new "help: näytä tämä apuviesti"
-
-    # renpy/common/00console.rpy:398
-    old "commands:\n"
-    new "komennot:\n"
-
-    # renpy/common/00console.rpy:408
-    old " <renpy script statement>: run the statement\n"
-    new " <renpy script-väite>: suorita väite\n"
-
-    # renpy/common/00console.rpy:410
-    old " <python expression or statement>: run the expression or statement"
-    new " <python-ekspressio tai väite>: suorita ekspressio tai väite"
-
-    # renpy/common/00console.rpy:418
-    old "clear: clear the console history"
-    new "clear: tyhjennä konsolin historia"
-
-    # renpy/common/00console.rpy:422
-    old "exit: exit the console"
-    new "exit: poistu konsolista"
-
-    # renpy/common/00console.rpy:430
-    old "load <slot>: loads the game from slot"
-    new "load <tallennuspaikka>: lataa pelin halutusta tallennuspaikasta"
-
-    # renpy/common/00console.rpy:443
-    old "save <slot>: saves the game in slot"
-    new "save <tallennuspaikka>: tallentaa pelin tallennuspaikkaan"
-
-    # renpy/common/00console.rpy:454
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: lataa pelin uudelleen, päivittäen skriptit"
-
-    # renpy/common/00console.rpy:462
-    old "watch <expression>: watch a python expression"
-    new "watch <ekspressio>: tarkkaile python-ekspressiota"
-
-    # renpy/common/00console.rpy:488
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <ekspressio>: lakkaa tarkkailemasta ekspressiota"
-
-    # renpy/common/00console.rpy:514
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: lopeta kaikkien ekspressioiden tarkkailu"
-
-    # renpy/common/00console.rpy:531
-    old "jump <label>: jumps to label"
-    new "jump <tunnus>: hyppää 'script.rpy'-tiedosto(i)ssa olevaan, tunnuksella merkittyyn kohtaan"
-
-translate finnish strings:
-
-    # renpy/common/00gallery.rpy:561
-    old "Image [index] of [count] locked."
-    new "[index]. kuva [count]:stä on lukittu"
-
-    # renpy/common/00gallery.rpy:581
-    old "prev"
-    new "edellinen"
-
-    # renpy/common/00gallery.rpy:582
-    old "next"
-    new "seuraava"
-
-    # renpy/common/00gallery.rpy:583
-    old "slideshow"
-    new "diaesitys"
-
-    # renpy/common/00gallery.rpy:584
-    old "return"
-    new "palaa"
-
-translate finnish strings:
-
-    # renpy/common/00gamepad.rpy:32
-    old "Select Gamepad to Calibrate"
-    new "Valitse kalibroitava peliohjain"
-
-    # renpy/common/00gamepad.rpy:35
-    old "No Gamepads Available"
-    new "Peliohjaimia ei havaittu"
-
-    # renpy/common/00gamepad.rpy:54
-    old "Calibrating [name] ([i]/[total])"
-    new "Kalibroidaan [name] ([i]/[total])"
-
-    # renpy/common/00gamepad.rpy:58
-    old "Press or move the [control!r] [kind]."
-    new "Paina tai liikuta [control!r] [kind]."
-
-    # renpy/common/00gamepad.rpy:66
-    old "Skip (A)"
-    new "Ohita (A)"
-
-    # renpy/common/00gamepad.rpy:69
-    old "Back (B)"
-    new "Takaisin (B)"
-
-translate finnish strings:
-
-    # renpy/common/00gltest.rpy:68
-    old "Graphics Acceleration"
-    new "Grafiikkakiihdytys"
-
-    # renpy/common/00gltest.rpy:72
-    old "Automatically Choose"
-    new "Valitse automaattisesti"
-
-    # renpy/common/00gltest.rpy:77
-    old "Force Angle/DirectX Renderer"
-    new "Pakota Angle/DirectX-renderöinti"
-
-    # renpy/common/00gltest.rpy:81
-    old "Force OpenGL Renderer"
-    new "Pakota OpenGL-renderöinti"
-
-    # renpy/common/00gltest.rpy:85
-    old "Force Software Renderer"
-    new "Pakota Software-renderöinti"
-
-    # renpy/common/00gltest.rpy:91
-    old "Gamepad"
-    new "Peliohjain"
-
-    # renpy/common/00gltest.rpy:95
-    old "Enable"
-    new "Ota käyttöön"
-
-    # renpy/common/00gltest.rpy:99
-    old "Disable"
-    new "Poista käytöstä"
-
-    # renpy/common/00gltest.rpy:105
-    old "Calibrate"
-    new "Kalibroi"
-
-    # renpy/common/00gltest.rpy:111
-    old "Changes will take effect the next time this program is run."
-    new "Muutokset tulevat voimaan, kun käynnistät ohjelman uudelleen."
-
-    # renpy/common/00gltest.rpy:115
-    old "Quit"
-    new "Poistu"
-
-    # renpy/common/00gltest.rpy:120
-    old "Return"
-    new "Palaa"
-
-    # renpy/common/00gltest.rpy:150
-    old "Performance Warning"
-    new "Suorituskyvyn varoitus"
-
-    # renpy/common/00gltest.rpy:155
-    old "This computer is using software rendering."
-    new "Tietokone käyttää software-renderöintiä."
-
-    # renpy/common/00gltest.rpy:157
-    old "This computer is not using shaders."
-    new "Tietokone ei käytä varjostuksia."
-
-    # renpy/common/00gltest.rpy:159
-    old "This computer is displaying graphics slowly."
-    new "Tietokone näyttää grafiikkaa hitaasti."
-
-    # renpy/common/00gltest.rpy:161
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Tietokoneella on ongelmia grafiikan näyttämisessä: [problem]."
-
-    # renpy/common/00gltest.rpy:166
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen. DirectX:n päivittäminen saattaa korjata ongelman."
-
-    # renpy/common/00gltest.rpy:168
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen."
-
-    # renpy/common/00gltest.rpy:173
-    old "Update DirectX"
-    new "Päivitä DirectX"
-
-    # renpy/common/00gltest.rpy:179
-    old "Continue, Show this warning again"
-    new "Jatka, näytä tämä varoitus uudelleen"
-
-    # renpy/common/00gltest.rpy:183
-    old "Continue, Don't show warning again"
-    new "Jatka, älä näytä tätä varoitusta enää uudelleen"
-
-    # renpy/common/00gltest.rpy:209
-    old "Updating DirectX."
-    new "Päivitetään DirectX:ää."
-
-    # renpy/common/00gltest.rpy:213
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "DirectX:n verkkoasennus on alkanut. Se voi olla aluksi minimisoituna työkalupalkilla. Seuraa ohjeita asentaaksesi DirectX:n."
-
-    # renpy/common/00gltest.rpy:217
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Huomaa:{/b} Microsoftin DirectX verkkoasennusohjelma asentaa, oletusarvoisesti, Bing-työkalupalkin. Jos et halua tätä työkalupalkkia, poista valinta oikeasta laatikosta."
-
-    # renpy/common/00gltest.rpy:221
-    old "When setup finishes, please click below to restart this program."
-    new "Kun asennus on valmis, klikkaa alhaalta käynnistääksesi tämän ohjelman uudelleen."
-
-    # renpy/common/00gltest.rpy:223
-    old "Restart"
-    new "Käynnistä uudelleen"
-
-translate finnish strings:
-
-    # renpy/common/00keymap.rpy:248
-    old "Saved screenshot as %s."
-    new "Näytönkaappaus tallennettu nimellä %s."
-
-translate finnish strings:
-
-    # renpy/common/00layout.rpy:450
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Oletko varma?"
 
-    # renpy/common/00layout.rpy:451
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Oletko varma, että haluat poistaa tämän tallennuksen?"
 
-    # renpy/common/00layout.rpy:452
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Oletko varma, että haluat korvata tallennuksen uudella?"
 
-    # renpy/common/00layout.rpy:453
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Lataamalla tallennuksen menetät tallentamattoman edistyksen.\nOletko varma, että haluat tehdä näin?"
 
-    # renpy/common/00layout.rpy:454
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Haluatko varmasti lopettaa?"
 
-    # renpy/common/00layout.rpy:455
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Haluatko varmasti palata päävalikkoon?\nMenetät kaikki tallentamattomat tiedot."
 
-    # renpy/common/00layout.rpy:456
+    # 00gui.rpy:233
     old "Are you sure you want to end the replay?"
     new "Oletko varma, että haluat lopettaa tämän uusinnan?"
 
-    # renpy/common/00layout.rpy:457
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Oletko varma, että haluat alkaa dialogin sivuuttamisen?"
 
-    # renpy/common/00layout.rpy:458
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Oletko varma, että haluat siirtyä suoraan seuraavaan valintaan?"
 
-    # renpy/common/00layout.rpy:459
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Oletko varma, että haluat siirtyä suoraan uuteen dialogiin tai seuraavaan valintaan?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-translate finnish strings:
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Näytönkaappaus tallennettu nimellä %s."
 
-    # renpy/common/00library.rpy:125
+    # 00library.rpy:142
     old "Self-voicing disabled."
     new "Tietokoneen ääninäyttely lopetettu."
 
-    # renpy/common/00library.rpy:126
+    # 00library.rpy:143
     old "Clipboard voicing enabled. "
     new "Leikepöydän ääneen toisto käytössä. "
 
-    # renpy/common/00library.rpy:127
+    # 00library.rpy:144
     old "Self-voicing enabled. "
     new "Ääneen toisto poissa käytöstä."
 
-    # renpy/common/00library.rpy:162
+    # 00library.rpy:179
     old "Skip Mode"
     new "Ylihyppäystila"
 
-    # renpy/common/00library.rpy:165
-    old "Fast Skip Mode"
-    new "Nopea ylihyppäystila"
-
-    # renpy/common/00library.rpy:248
-    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license/}here{/a}."
-    new "Tämä ohjelma sisältää ilmaisia ohjelmia useiden lisenssien alaisuudessa, mukaanlukien MIT-lisenssi ja GNU Lesser General Public License. Täysi lista ohjelmista, sekä linkit koko lähdekoodiin, voidaan löytää {a=https://www.renpy.org/l/license/}täältä{/a}."
-
-translate finnish strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:409
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "Leikepöydän ääneen toisto käytössä. Paina 'shift+C' lopettaaksesi."
 
-    # renpy/common/00preferences.rpy:411
+    # 00preferences.rpy:424
     old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
     new "Tietokoneen ääninäyttely sanoisi \"[renpy.display.tts.last]\". Paina 'alt+shift+V' lopettaaksesi."
 
-    # renpy/common/00preferences.rpy:413
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "Tietokoneen ääninäyttely käytössä. Paina 'v' lopettaaksesi."
 
-translate finnish strings:
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "Mobiililaitteet eivät tue Ren'Py Updater -toimintoa."
 
-    # renpy/common/00updater.rpy:481
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "Simuloidaan havaittua ongelmaa."
 
-    # renpy/common/00updater.rpy:657
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "Tämä projekti ei tue päivittämistä tai päivityksen statustiedosto poistettiin."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "Tällä käyttäjällä ei ole oikeutta päivityksen suorittamiseen."
 
-    # renpy/common/00updater.rpy:674
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "Tällä käyttäjällä ei ole oikeutta kirjoittaa dataa päivityslokiin."
 
-    # renpy/common/00updater.rpy:699
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "Päivityksen allekirjoitusta ei voitu vahvistaa."
 
-    # renpy/common/00updater.rpy:970
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "Päivitystiedostoa ei ladattu."
 
-    # renpy/common/00updater.rpy:988
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "Päivitystiedosto ei sisällä oikeaa tiivistelmää - se on saattanut korruptoitua."
 
-    # renpy/common/00updater.rpy:1044
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "Purettaessa {}, tuntematon tyyppi {}."
 
-    # renpy/common/00updater.rpy:1395
+    # 00updater.rpy:1393
     old "Updater"
     new "Päivittäjä"
 
-    # renpy/common/00updater.rpy:1404
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Käytät jo uuinta versiota."
 
-    # renpy/common/00updater.rpy:1406
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] on saatavilla. Haluatko asentaa sen?"
 
-    # renpy/common/00updater.rpy:1408
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Valmistellaan päivitysten lataamista."
 
-    # renpy/common/00updater.rpy:1410
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Ladataan päivityksiä."
 
-    # renpy/common/00updater.rpy:1412
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Puretaan päivityksiä."
 
-    # renpy/common/00updater.rpy:1416
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "Päivitykset on asennettu. Ohjelma käynnistyy nyt uudelleen."
 
-    # renpy/common/00updater.rpy:1418
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "Päivitykset on asennettu."
 
-    # renpy/common/00updater.rpy:1420
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "Päivitykset peruttiin."
 
-translate finnish strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "Tyhjä paikka."
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
-    new "Edellinen"
-
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
-    new "Seuraava"
-
-translate finnish strings:
-
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "Peliohjaimen näppäinten asetus"
-
-
-translate finnish strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "Kehittäjävalikko"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "Käynnistä peli uudelleen (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Konsoli (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "Muuttujat"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "Teematesti"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "Kuvan sijainnin selvitin"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "Tiedostonimilista"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Näytä kuvanlatausloki"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Piilota kuvanlatausloki"
-
-    # renpy/common/_developer/developer.rpym:150
-    old "No variables have changed since the game started."
-    new "Yksikään muuttuja ei ole muuttunut pelin alkamisen jälkeen."
-
-    # renpy/common/_developer/developer.rpym:153
-    old "Return to the developer menu"
-    new "Palaa kehittäjävalikkoon"
-
-    # renpy/common/_developer/developer.rpym:386
-    old "Rectangle: %r"
-    new "Suorakulmio: %r"
-
-    # renpy/common/_developer/developer.rpym:391
-    old "Mouse position: %r"
-    new "Hiiren sijainti: %r"
-
-    # renpy/common/_developer/developer.rpym:396
-    old "Right-click or escape to quit."
-    new "Paina Esc tai hiiren oikeaa näppäintä poistuaksesi."
-
-    # renpy/common/_developer/developer.rpym:425
-    old "Rectangle copied to clipboard."
-    new "Suorakulmio kopioitu leikepöydälle."
-
-    # renpy/common/_developer/developer.rpym:428
-    old "Position copied to clipboard."
-    new "Sijainti kopioitu leikepöydälle."
-
-    # renpy/common/_developer/developer.rpym:459
-    old "Done"
-    new "Valmis"
-
-translate finnish strings:
-
-    # renpy/common/_developer/inspector.rpym:46
-    old "Displayable Inspector"
-    new "Näkyvien objektien tutkija"
-
-    # renpy/common/_developer/inspector.rpym:52
-    old "Nothing to inspect."
-    new "Ei tutkittavaa."
-
-    # renpy/common/_developer/inspector.rpym:70
-    old "Size"
-    new "Koko"
-
-    # renpy/common/_developer/inspector.rpym:74
-    old "Style"
-    new "Tyyli"
-
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "Sijainti"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Tutkitaan [displayable_name!q]n tyylejä"
-
-    # renpy/common/_developer/inspector.rpym:155
-    old "displayable:"
-    new "näkyvä objekti:"
-
-    # renpy/common/_developer/inspector.rpym:162
-    old "        (no properties affect the displayable)"
-    new "        (mitkään ominaisuudet eivät vaikuta objektiin)"
-
-    # renpy/common/_developer/inspector.rpym:164
-    old "        (default properties omitted)"
-    new "        (perusominaisuudet sivuutettu)"
-
-    # renpy/common/_developer/inspector.rpym:206
-    old "<repr() failed>"
-    new "<repr() epäonnistui>"
-
-translate finnish strings:
-
-    # renpy/common/_errorhandling.rpym:502
-    old "An exception has occurred."
-    new "Odottamaton virhe on tapahtunut."
-
-    # renpy/common/_errorhandling.rpym:528
-    old "Rollback"
-    new "Palaa edelliseen tilaan"
-
-    # renpy/common/_errorhandling.rpym:530
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Yrittää palata aikaisempaan tilaan, antaen sinun tallentaa tai tehdä eri valinnan."
-
-    # renpy/common/_errorhandling.rpym:533
-    old "Ignore"
-    new "Sivuuta"
-
-    # renpy/common/_errorhandling.rpym:535
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Sivuuttaa poikkeuksen, antaen sinun jatkaa. Tämä johtaa usein uusiin virheisiin."
-
-    # renpy/common/_errorhandling.rpym:538
-    old "Reload"
-    new "Lataa uudelleen"
-
-    # renpy/common/_errorhandling.rpym:540
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Lataa pelin uudelleen muistista, tallentaen ja palauttaen pelitilan jos mahdollista."
-
-    # renpy/common/_errorhandling.rpym:542
-    old "Open Traceback"
-    new "Avaa virheenjäljitystoiminto"
-
-    # renpy/common/_errorhandling.rpym:544
-    old "Opens the traceback.txt file in a text editor."
-    new "Avaa traceback.txt-tiedoston tekstieditorissa."
-
-    # renpy/common/_errorhandling.rpym:547
-    old "Copy to Clipboard"
-    new "Kopioi leikepöydälle"
-
-    # renpy/common/_errorhandling.rpym:549
-    old "Copies the traceback.txt file to the clipboard."
-    new "Kopioi traceback.txt-tiedoston leikepöydälle."
-
-    # renpy/common/_errorhandling.rpym:555
-    old "Quits the game."
-    new "Lopettaa pelin."
-
-    # renpy/common/_errorhandling.rpym:582
-    old "Parsing the script failed."
-    new "Skriptin jäsennys epäonnistui."
-
-    # renpy/common/_errorhandling.rpym:609
-    old "Open Parse Errors"
-    new "Avaa jäsennysvirheet"
-
-    # renpy/common/_errorhandling.rpym:611
-    old "Opens the errors.txt file in a text editor."
-    new "Avaa errors.txt-tiedoston tekstieditorissa."
-
-    # renpy/common/_errorhandling.rpym:616
-    old "Copies the errors.txt file to the clipboard."
-    new "Kopioi errors.txt-tiedoston leikepöydälle."
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "[index]. kuva [count]:stä on lukittu"
 
+    # 00gallery.rpy:583
+    old "prev"
+    new "edellinen"
 
-translate finnish strings:
+    # 00gallery.rpy:584
+    old "next"
+    new "seuraava"
 
-    # renpy/common/_layout/classic_load_save.rpym:170
-    old "a"
-    new "a"
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "diaesitys"
 
-    # renpy/common/_layout/classic_load_save.rpym:179
-    old "q"
-    new "q"
+    # 00gallery.rpy:586
+    old "return"
+    new "palaa"
 
diff --git a/launcher/game/tl/finnish/developer.rpy b/launcher/game/tl/finnish/developer.rpy
new file mode 100644
index 0000000..cd878a4
--- /dev/null
+++ b/launcher/game/tl/finnish/developer.rpy
@@ -0,0 +1,179 @@
+
+translate finnish strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Kehittäjävalikko"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Käynnistä peli uudelleen (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Konsoli (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Muuttujat"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Teematesti"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Kuvan sijainnin selvitin"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Tiedostonimilista"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Näytä kuvanlatausloki"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Piilota kuvanlatausloki"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Ei tutkittavaa."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Palaa kehittäjävalikkoon"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Suorakulmio: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Hiiren sijainti: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Paina Esc tai hiiren oikeaa näppäintä poistuaksesi."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Suorakulmio kopioitu leikepöydälle."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Sijainti kopioitu leikepöydälle."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Näkyvien objektien tutkija"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Koko"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Tyyli"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Sijainti"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Tutkitaan [displayable_name!q]n tyylejä"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "näkyvä objekti:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (mitkään ominaisuudet eivät vaikuta objektiin)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (perusominaisuudet sivuutettu)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() epäonnistui>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Paina <esc> poistuaksesi konsolista. Käytä komentoa help saadaksesi apua."
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren'Py-skriptikieli käytössä."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren'Py-skriptikieli poissa käytöstä."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: näytä tämä apuviesti"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "komennot:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script-väite>: suorita väite\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python-ekspressio tai väite>: suorita ekspressio tai väite"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: tyhjennä konsolin historia"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: poistu konsolista"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <tallennuspaikka>: lataa pelin halutusta tallennuspaikasta"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <tallennuspaikka>: tallentaa pelin tallennuspaikkaan"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: lataa pelin uudelleen, päivittäen skriptit"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <ekspressio>: tarkkaile python-ekspressiota"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <ekspressio>: lakkaa tarkkailemasta ekspressiota"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: lopeta kaikkien ekspressioiden tarkkailu"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <tunnus>: hyppää 'script.rpy'-tiedosto(i)ssa olevaan, tunnuksella merkittyyn kohtaan"
+
diff --git a/launcher/game/tl/finnish/distribute.rpy b/launcher/game/tl/finnish/distribute.rpy
deleted file mode 100644
index fa44e0a..0000000
--- a/launcher/game/tl/finnish/distribute.rpy
+++ /dev/null
@@ -1,38 +0,0 @@
-
-translate finnish strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Ohjelman kokoaminen epäonnistui:\n\nbuild.directory_name -muuttuja ei saa sisältää välilyöntejä, pilkkuja tai puolipilkkuja."
-
-    # game/distribute.rpy:381
-    old "No packages are selected, so there's nothing to do."
-    new "Yhtäkään pakettia ei valittu, joten mitään ei ole tehtävissä."
-
-    # game/distribute.rpy:386
-    old "Scanning project files..."
-    new "Skannataan projektin tiedostoja..."
-
-    # game/distribute.rpy:396
-    old "Scanning Ren'Py files..."
-    new "Skannataan Ren'Py-tiedostoja..."
-
-    # game/distribute.rpy:444
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Kaikki paketit on koottu.\n\nLupainformaation läsnäolon vuoksi Linux- ja Macintosh-sovellusten pakkaamista Windows-järjestelmässä ei tueta."
-
-    # game/distribute.rpy:568
-    old "Archiving files..."
-    new "Arkistoidaan tiedostoja..."
-
-    # game/distribute.rpy:832
-    old "Writing the [variant] [format] package."
-    new "Kirjoitetaan [variant] [format]-pakettia."
-
-    # game/distribute.rpy:845
-    old "Making the [variant] update zsync file."
-    new "Luodaan [variant] zsync-päivitystiedostoa."
-
-    # game/distribute.rpy:941
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Käsitelty {b}[complete]{/b}/{b}[total]{/b}:sta tiedostosta."
diff --git a/launcher/game/tl/finnish/distribute_gui.rpy b/launcher/game/tl/finnish/distribute_gui.rpy
deleted file mode 100644
index 82f2d1d..0000000
--- a/launcher/game/tl/finnish/distribute_gui.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate finnish strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "Kokoa ohjelma levitykseen: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:171
-    old "Directory Name:"
-    new "Kansion nimi:"
-
-    # game/distribute_gui.rpy:175
-    old "Executable Name:"
-    new "Suoritettavan tiedoston nimi:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "Toimet:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "Muokkaa options.rpy-tiedostoa"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "Lisää from-ehdot kutsuihin, kerran"
-
-    # game/distribute_gui.rpy:195
-    old "Refresh"
-    new "Päivitä"
-
-    # game/distribute_gui.rpy:212
-    old "Build Packages:"
-    new "Kokoa sovelluksia:"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "Valinnat:"
-
-    # game/distribute_gui.rpy:236
-    old "Build Updates"
-    new "Kokoa päivityksiä"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "Lisää from-ehdot kutsuihin"
-
-    # game/distribute_gui.rpy:239
-    old "Force Recompile"
-    new "Pakota uudelleenkokoaminen"
-
-    # game/distribute_gui.rpy:243
-    old "Build"
-    new "Kokoa sovellus"
-
-    # game/distribute_gui.rpy:247
-    old "Adding from clauses to call statements that do not have them."
-    new "Lisätään from-ehtoja kutsuihin, joilla ei ole niitä."
-
-    # game/distribute_gui.rpy:268
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Virheitä havaittu projektia suoritettaessa. Varmista, että projekti toimii moitteetta ennen kuin kokoat ohjelman."
-
-    # game/distribute_gui.rpy:285
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Projektisi ei sisällä kokoamisinformaatiota. Haluatko lisätä kokoamisinormaation options.rpy-tiedoston loppuun?"
-
diff --git a/launcher/game/tl/finnish/editor.rpy b/launcher/game/tl/finnish/editor.rpy
deleted file mode 100644
index 5b67bc6..0000000
--- a/launcher/game/tl/finnish/editor.rpy
+++ /dev/null
@@ -1,55 +0,0 @@
-
-translate finnish strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "Tämä saattoi tapahtua, koska wxPythonia ei ole asennettu järjestelmään."
-
-    # game/editor.rpy:169
-    old "Up to 22 MB download required."
-    new "Noin 22 MB lataus vaaditaan"
-
-    # game/editor.rpy:182
-    old "A mature editor that requires Java."
-    new "Edistynyt editori, joka vaatii Javan."
-
-    # game/editor.rpy:182
-    old "1.8 MB download required."
-    new "1.8 MB lataus vaaditaan."
-
-    # game/editor.rpy:182
-    old "This may have occured because Java is not installed on this system."
-    new "Tämä saattoi tapahtua, koska Javaa ei ole asennettu."
-
-    # game/editor.rpy:191
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Käyttää editoria, jota käyttöjärjestelmäsi käyttää .rpy-tiedostojen kanssa."
-
-    # game/editor.rpy:207
-    old "Prevents Ren'Py from opening a text editor."
-    new "Estää Ren'Py-ohjelmaa avaamasta tekstieditoria."
-
-    # game/editor.rpy:359
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Virhe käynnistäessä tekstieditoria:\n[exception!q]"
-
-    # game/editor.rpy:457
-    old "Select Editor"
-    new "Valitse editori"
-
-    # game/editor.rpy:472
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Tekstieditori on ohjelma, jota käytät Ren'Py-skriptitiedostojen muokkaamiseen. Täällä voit valita, mitä editoria Ren'Py käyttää. Jos valitsemaasi editoria ei vielä ole asennettu, se ladataan ja asennetaan automaattisesti."
-
-    # game/editor.rpy:494
-    old "Cancel"
-    new "Peruuta"
-
diff --git a/launcher/game/tl/finnish/error.rpy b/launcher/game/tl/finnish/error.rpy
new file mode 100644
index 0000000..960cfc1
--- /dev/null
+++ b/launcher/game/tl/finnish/error.rpy
@@ -0,0 +1,179 @@
+
+translate finnish strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Grafiikkakiihdytys"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Valitse automaattisesti"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Pakota Angle/DirectX-renderöinti"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Pakota OpenGL-renderöinti"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Pakota Software-renderöinti"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Ota käyttöön"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Muutokset tulevat voimaan, kun käynnistät ohjelman uudelleen."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Suorituskyvyn varoitus"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Tietokone käyttää software-renderöintiä."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Tietokone ei käytä varjostuksia."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Tietokone näyttää grafiikkaa hitaasti."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Tietokoneella on ongelmia grafiikan näyttämisessä: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen. DirectX:n päivittäminen saattaa korjata ongelman."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Päivitä DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Jatka, näytä tämä varoitus uudelleen"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Jatka, älä näytä tätä varoitusta enää uudelleen"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Päivitetään DirectX:ää."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX:n verkkoasennus on alkanut. Se voi olla aluksi minimisoituna työkalupalkilla. Seuraa ohjeita asentaaksesi DirectX:n."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Huomaa:{/b} Microsoftin DirectX verkkoasennusohjelma asentaa, oletusarvoisesti, Bing-työkalupalkin. Jos et halua tätä työkalupalkkia, poista valinta oikeasta laatikosta."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Kun asennus on valmis, klikkaa alhaalta käynnistääksesi tämän ohjelman uudelleen."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Käynnistä uudelleen"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Valitse kalibroitava peliohjain"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "Peliohjaimia ei havaittu"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Kalibroidaan [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Paina tai liikuta [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Ohita (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Takaisin (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Avaa virheenjäljitystoiminto"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Avaa traceback.txt-tiedoston tekstieditorissa."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Kopioi leikepöydälle"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Kopioi traceback.txt-tiedoston leikepöydälle."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Odottamaton virhe on tapahtunut."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Palaa edelliseen tilaan"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Yrittää palata aikaisempaan tilaan, antaen sinun tallentaa tai tehdä eri valinnan."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Sivuuta"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Sivuuttaa poikkeuksen, antaen sinun jatkaa. Tämä johtaa usein uusiin virheisiin."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Lataa uudelleen"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Lataa pelin uudelleen muistista, tallentaen ja palauttaen pelitilan jos mahdollista."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Lopettaa pelin."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Skriptin jäsennys epäonnistui."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Avaa jäsennysvirheet"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Avaa errors.txt-tiedoston tekstieditorissa."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Kopioi errors.txt-tiedoston leikepöydälle."
+
diff --git a/launcher/game/tl/finnish/front_page.rpy b/launcher/game/tl/finnish/front_page.rpy
deleted file mode 100644
index ec51306..0000000
--- a/launcher/game/tl/finnish/front_page.rpy
+++ /dev/null
@@ -1,111 +0,0 @@
-
-translate finnish strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Avaa [text] kansio."
-
-    # game/front_page.rpy:93
-    old "refresh"
-    new "päivitä"
-
-    # game/front_page.rpy:120
-    old "+ Create New Project"
-    new "+ Luo uusi projekti"
-
-    # game/front_page.rpy:132
-    old "Launch Project"
-    new "Suorita projekti"
-
-    # game/front_page.rpy:149
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-    # game/front_page.rpy:151
-    old "Select project [text]."
-    new "Valitse projekti [text]."
-
-    # game/front_page.rpy:167
-    old "Tutorial"
-    new "Apukurssi"
-
-    # game/front_page.rpy:168
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:184
-    old "Active Project"
-    new "Aktiivinen projekti"
-
-    # game/front_page.rpy:192
-    old "Open Directory"
-    new "Avaa kansio"
-
-    # game/front_page.rpy:197
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:198
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:199
-    old "images"
-    new "images"
-
-    # game/front_page.rpy:205
-    old "Edit File"
-    new "Muokkaa tiedostoa"
-
-    # game/front_page.rpy:213
-    old "All script files"
-    new "Kaikki skriptitiedostot"
-
-    # game/front_page.rpy:222
-    old "Navigate Script"
-    new "Selaa skriptejä"
-
-    # game/front_page.rpy:233
-    old "Check Script (Lint)"
-    new "Tarkista skripti (Lint)"
-
-    # game/front_page.rpy:234
-    old "Change Theme"
-    new "Vaihda teemaa"
-
-    # game/front_page.rpy:235
-    old "Delete Persistent"
-    new "Poista pysyvästi tallennettu data"
-
-    # game/front_page.rpy:244
-    old "Build Distributions"
-    new "Kokoa jakeluun"
-
-    # game/front_page.rpy:246
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:247
-    old "iOS"
-    new "iOS"
-
-    # game/front_page.rpy:248
-    old "Generate Translations"
-    new "Luo käännöksiä"
-
-    # game/front_page.rpy:249
-    old "Extract Dialogue"
-    new "Kopioi dialogi"
-
-    # game/front_page.rpy:265
-    old "Checking script for potential problems..."
-    new "Tarkistetaan skriptiä mahdollisten ongelmien varalta..."
-
-    # game/front_page.rpy:280
-    old "Deleting persistent data..."
-    new "Poistetaan pysyvästi tallennettua dataa..."
-
-    # game/front_page.rpy:288
-    old "Recompiling all rpy files into rpyc files..."
-    new "Muodostetaan kaikista rpy-tiedostoista rpyc-tiedostoja..."
-
diff --git a/launcher/game/tl/finnish/gui.rpy b/launcher/game/tl/finnish/gui.rpy
new file mode 100644
index 0000000..bc4be38
--- /dev/null
+++ b/launcher/game/tl/finnish/gui.rpy
@@ -0,0 +1,411 @@
+
+translate finnish strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/finnish/interface.rpy b/launcher/game/tl/finnish/interface.rpy
deleted file mode 100644
index 24a460d..0000000
--- a/launcher/game/tl/finnish/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate finnish strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "Dokumentaatio"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "Ren'Py:n verkkosivut"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "Lista Ren'Py-peleistä"
-
-    # game/interface.rpy:110
-    old "About"
-    new "Tietoja"
-
-    # game/interface.rpy:117
-    old "update"
-    new "päivitä"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "asetukset"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "poistu"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "Kyllä"
-
-    # game/interface.rpy:194
-    old "No"
-    new "Ei"
-
-    # game/interface.rpy:230
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Pakkausformaatin rajoitusten vuoksi, ei-ASCII tiedostot ja kansion nimet eivät ole sallittuja."
-
-    # game/interface.rpy:322
-    old "ERROR"
-    new "VIRHE"
-
-    # game/interface.rpy:351
-    old "While [what!q], an error occured:"
-    new "Kun [what!q], tapahtui virhe:"
-
-    # game/interface.rpy:351
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:370
-    old "Text input may not contain the {{ or [[ characters."
-    new "Teksti ei saa sisältää {{ tai [[-merkkejä."
-
-    # game/interface.rpy:375
-    old "File and directory names may not contain / or \\."
-    new "Tiedostojen ja kansioiden nimet eivät saa sisältää / tai \\-merkkejä."
-
-    # game/interface.rpy:381
-    old "File and directory names must consist of ASCII characters."
-    new "Tiedostojen ja kansioiden nimet saavat koostua vain ASCII-merkeistä."
-
-    # game/interface.rpy:402
-    old "INFORMATION"
-    new "INFORMAATIO"
-
-    # game/interface.rpy:449
-    old "PROCESSING"
-    new "KÄSITELLÄÄN"
-
-    # game/interface.rpy:466
-    old "QUESTION"
-    new "KYSYMYS"
-
-    # game/interface.rpy:479
-    old "CHOICE"
-    new "VALINTA"
-
diff --git a/launcher/game/tl/finnish/ios.rpy b/launcher/game/tl/finnish/ios.rpy
deleted file mode 100644
index 458f5be..0000000
--- a/launcher/game/tl/finnish/ios.rpy
+++ /dev/null
@@ -1,98 +0,0 @@
-
-translate finnish strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Luodaksesi iOS-sovelluksia, ole hyvä ja lataa renios, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Kansiota, johon Xcode-projektit asetetaan, ei ole valittu. Klikkaa 'Valitse kansio' valitaksesi sen."
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "Nykyistä Ren'Py-projektia vastaavaa Xcode-projektia ei löydy. Klikkaa 'Luo Xcode-projekti' luodaksesi sellaisen."
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Xcode-projekti on jo olemassa. Klikkaa 'Päivitä Xcode-projekti' päivittääksesi sen uusimmilla pelin tiedostoilla, tai käytä Xcodea kootaksesi ja asentaaksesi sen."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Ren'Py pyrkii emuloimaan iPhonea.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Ren'Py pyrkii emuloimaan iPadia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Valitsee kansion, johon Xcode-projektit sijoitetaan."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "Luo Xcode-projektin tällä hetkellä valittuna olevasta Ren'Py-projektista."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Päivittää Xcode-projektin uusimmilla pelitiedostoilla. Tämä on tehtävä joka kerta Ren'Py-projektin muuttuessa."
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Avaa Xcode-projektin Xcodessa."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Avaa Xcode-projektit sisältävän kansion."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Tämänniminen Xcode-projekti on jo olemassa. Haluatko nimetä vanhan projektin uudelleen ja korvata sen uudella?"
-
-    # game/ios.rpy:211
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:240
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:244
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:264
-    old "Select Xcode Projects Directory"
-    new "Valitse Xcode-projektikansio"
-
-    # game/ios.rpy:268
-    old "Create Xcode Project"
-    new "Luo Xcode-projekti"
-
-    # game/ios.rpy:272
-    old "Update Xcode Project"
-    new "Päivitä Xcode-projekti"
-
-    # game/ios.rpy:277
-    old "Launch Xcode"
-    new "Käynnistä Xcode"
-
-    # game/ios.rpy:312
-    old "Open Xcode Projects Directory"
-    new "Avaa Xcode-projektikansio"
-
-    # game/ios.rpy:345
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "Ennen iOS-sovellusten pakkaamista sinun on ladattava renios, Ren'Py:n iOS-tuki. Haluaisitko ladata reniosin nyt?"
-
-    # game/ios.rpy:354
-    old "XCODE PROJECTS DIRECTORY"
-    new "XCODE-PROJEKTIKANSIO"
-
-    # game/ios.rpy:354
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Ole hyvä ja valitse Xcode-projektikansio käyttämällä resurssienhallintaa.\n{b}Kansion valinta on saattanut aueta tämän ikkunan taakse.{/b}"
-
-    # game/ios.rpy:359
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py on asettanut Xcode-projektikansioksi:"
diff --git a/launcher/game/tl/finnish/launcher.rpy b/launcher/game/tl/finnish/launcher.rpy
new file mode 100644
index 0000000..0d8fbcb
--- /dev/null
+++ b/launcher/game/tl/finnish/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate finnish strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Näytä lisenssi"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "TIEDOSTONIMI"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Kirjoita skriptitiedoston nimi, jonka haluat luoda."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Tiedostolla on oltava .rpy-tunniste."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Tämänniminen tiedosto on jo olemassa."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py lataa automaattisesti kaikki scriptitiedostot, joilla on .rpy pääte. Käyttääksesi tätä\n# tiedostoa, luo label ja hyppää siihen toisesta tiedostosta.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Luodaksesi Android-sovelluksia, ole hyvä ja lataa RAPT, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "32-bittinen Javan kehitystyökalu vaaditaan Android-sovellusten luomiseen Windowsilla. JDK on erilainen kuin JRE, joten on mahdollista, että sinulla on Java ilman JDK:ta.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Lataa ja asenna JDK{/a}, ja sen jälkeen käynnistä Ren'Py uudelleen."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT on asennettu, mutta sinun on asennettava Android SDK ennen kuin voit luoda Android-sovelluksia. Valitse 'Asenna SDK' tehdäksesi tämän."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT on asennettu, mutta avainta ei ole konfiguroitu. Luo uusi avain, tai palauta android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Valittua projektia ei ole konfiguroitu. Käytä \"Konfigurointi\" -toimintoa konfiguroidaksesi sen ennen sovelluksen kokoamista."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Valitse \"Kokoa\" kootaksesi projektin, tai kiinnitä Android-laite ja valitse \"Kokoa ja asenna\" kootaksesi ja asentaaksesi sen laitteeseen."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ren'Py pyrkii emuloimaan Android-puhelinta.\n\nKosketus valintaa emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ren'Py pyrkii emuloimaan Android-tablettia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ren'Py pyrkii emuloimaan televisiopohjaista Android-konsolia, kuten OUYA tai Fire TV.\n\nOhjainnäppäimet ovat nuolinäppäimet, Enter toimii valitsijana, Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Lataa ja asentaa Android SDK:n ja tarvittavat lisäpaketit. Lisäksi, voidaan käyttää avainten luomiseen."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Konfiguroi paketin nimen, version sekä kaiken muun projektia koskevan tiedon."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Avaa tiedoston, joka sisältää Google Play -avaimet, editorissa.\n\nTätä tarvitaan vain, jos sovellus käyttää laajennus-APK:ta. Lue dokumentaatio saadaksesi lisätietoa."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Kokoaa Android-sovelluksen."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Kokoaa Android-sovelluksen, ja asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Kokoaa Android-sovelluksen, asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen ja käynnistää sovelluksen laitteessa."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Yhdistää Android-laitteeseen, joka pyörittää ADB:tä TCP/IP -tilassa."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Katkaisee yhteyden Android-laitteeseen, joka pyörittää ADB:tä TCP/IP -tilassa."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Noutaa lokitiedot Android-laitteesta ja luo niistä tiedoston."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Kopioidaan Android-tiedostoja jakelukansioon."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Emulointi:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Puhelin"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tabletti"
+
+    # android.rpy:341
+    old "Television"
+    new "Televisio"
+
+    # android.rpy:353
+    old "Build:"
+    new "Kokoa:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Asenna SDK & Luo avaimia"
+
+    # android.rpy:365
+    old "Configure"
+    new "Muokkaa asetuksia"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Kokoa sovellus"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Kokoa & asenna"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Kokoa, asenna & käynnistä"
+
+    # android.rpy:388
+    old "Other:"
+    new "Muita:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Langaton ADB-yhdistäminen"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Langaton ADB-katkaisu"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Ennen Android-sovellusten kokoamista, sinun on ladattava RAPT (Ren'Py Android Packaging Tool). Haluatko ladata RAPT:in nyt?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Langaton ADB-osoite"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Syötä yhdistettävän kohteen IP-osoite ja porttinumero, esimerkin \"192.168.1.143:5555\" mukaisesti. Selvitä laitteesi tiedoista kykeneekö se langattomaan ADB:hen, ja jos näin on, käytettävä osoite ja portti."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Virheellinen langaton ADB-osoite"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Osoitteeseen täytyy kuulua tasan yksi ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "IP-osoite ei saa sisältää välilyöntejä."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Portin on oltava numero."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Noudetaan logcat-tietoja laitteesta."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py ei kyennyt suorittamaan pythonia tkinterillä valitakseen kansion. Ole hyvä ja asenna python-tk tai tkinter-paketti."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Teeman vaihto epäonnistui. Options.rpy-tiedostoa on ehkä muokattu liikaa."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetaario"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Valitse teema"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Teema"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Väriskaala"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Jatka"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMAATIO"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Skannataan projektin tiedostoja..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Ohjelman kokoaminen epäonnistui:\n\nbuild.directory_name -muuttuja ei saa sisältää välilyöntejä, pilkkuja tai puolipilkkuja."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Yhtäkään pakettia ei valittu, joten mitään ei ole tehtävissä."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Skannataan Ren'Py-tiedostoja..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Kaikki paketit on koottu.\n\nLupainformaation läsnäolon vuoksi Linux- ja Macintosh-sovellusten pakkaamista Windows-järjestelmässä ei tueta."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Arkistoidaan tiedostoja..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Kirjoitetaan [variant] [format]-pakettia."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Luodaan [variant] zsync-päivitystiedostoa."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Käsitelty {b}[complete]{/b}/{b}[total]{/b}:sta tiedostosta."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Kokoa ohjelma levitykseen: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Kansion nimi:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Suoritettavan tiedoston nimi:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Toimet:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Muokkaa options.rpy-tiedostoa"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Lisää from-ehdot kutsuihin, kerran"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Päivitä"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Kokoa sovelluksia:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Valinnat:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Kokoa päivityksiä"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Lisää from-ehdot kutsuihin"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Pakota uudelleenkokoaminen"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Kokoa sovellus"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Lisätään from-ehtoja kutsuihin, joilla ei ole niitä."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Virheitä havaittu projektia suoritettaessa. Varmista, että projekti toimii moitteetta ennen kuin kokoat ohjelman."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Projektisi ei sisällä kokoamisinformaatiota. Haluatko lisätä kokoamisinormaation options.rpy-tiedoston loppuun?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Tämä saattoi tapahtua, koska wxPythonia ei ole asennettu järjestelmään."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Noin 22 MB lataus vaaditaan"
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Edistynyt editori, joka vaatii Javan."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB lataus vaaditaan."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Tämä saattoi tapahtua, koska Javaa ei ole asennettu."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Käyttää editoria, jota käyttöjärjestelmäsi käyttää .rpy-tiedostojen kanssa."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Estää Ren'Py-ohjelmaa avaamasta tekstieditoria."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Virhe käynnistäessä tekstieditoria:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Valitse editori"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Tekstieditori on ohjelma, jota käytät Ren'Py-skriptitiedostojen muokkaamiseen. Täällä voit valita, mitä editoria Ren'Py käyttää. Jos valitsemaasi editoria ei vielä ole asennettu, se ladataan ja asennetaan automaattisesti."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Peruuta"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Avaa [text] kansio."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "päivitä"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Luo uusi projekti"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Suorita projekti"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Valitse projekti [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Apukurssi"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Aktiivinen projekti"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Avaa kansio"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Muokkaa tiedostoa"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Kaikki skriptitiedostot"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Selaa skriptejä"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Tarkista skripti (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Vaihda teemaa"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Poista pysyvästi tallennettu data"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Kokoa jakeluun"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Luo käännöksiä"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Kopioi dialogi"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Tarkistetaan skriptiä mahdollisten ongelmien varalta..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Poistetaan pysyvästi tallennettua dataa..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Muodostetaan kaikista rpy-tiedostoista rpyc-tiedostoja..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "PROJEKTIN NIMI"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Ole hyvä ja nimeä projektisi:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Projektin nimi ei voi olla tyhjä."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] on jo olemassa. Ole hyvä ja valitse toinen nimi projektillesi."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] on jo olemassa. Ole hyvä ja valitse toinen nimi projektillesi."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Dokumentaatio"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren'Py:n verkkosivut"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Lista Ren'Py-peleistä"
+
+    # interface.rpy:117
+    old "update"
+    new "päivitä"
+
+    # interface.rpy:119
+    old "preferences"
+    new "asetukset"
+
+    # interface.rpy:120
+    old "quit"
+    new "poistu"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Pakkausformaatin rajoitusten vuoksi, ei-ASCII tiedostot ja kansion nimet eivät ole sallittuja."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "VIRHE"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Kun [what!q], tapahtui virhe:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Teksti ei saa sisältää {{ tai [[-merkkejä."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Tiedostojen ja kansioiden nimet eivät saa sisältää / tai \\-merkkejä."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Tiedostojen ja kansioiden nimet saavat koostua vain ASCII-merkeistä."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "KÄSITELLÄÄN"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "KYSYMYS"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "VALINTA"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Luodaksesi iOS-sovelluksia, ole hyvä ja lataa renios, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Kansiota, johon Xcode-projektit asetetaan, ei ole valittu. Klikkaa 'Valitse kansio' valitaksesi sen."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "Nykyistä Ren'Py-projektia vastaavaa Xcode-projektia ei löydy. Klikkaa 'Luo Xcode-projekti' luodaksesi sellaisen."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Xcode-projekti on jo olemassa. Klikkaa 'Päivitä Xcode-projekti' päivittääksesi sen uusimmilla pelin tiedostoilla, tai käytä Xcodea kootaksesi ja asentaaksesi sen."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Ren'Py pyrkii emuloimaan iPhonea.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Ren'Py pyrkii emuloimaan iPadia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Valitsee kansion, johon Xcode-projektit sijoitetaan."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Luo Xcode-projektin tällä hetkellä valittuna olevasta Ren'Py-projektista."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Päivittää Xcode-projektin uusimmilla pelitiedostoilla. Tämä on tehtävä joka kerta Ren'Py-projektin muuttuessa."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Avaa Xcode-projektin Xcodessa."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Avaa Xcode-projektit sisältävän kansion."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Tämänniminen Xcode-projekti on jo olemassa. Haluatko nimetä vanhan projektin uudelleen ja korvata sen uudella?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Valitse Xcode-projektikansio"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Luo Xcode-projekti"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Päivitä Xcode-projekti"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Käynnistä Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Avaa Xcode-projektikansio"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Ennen iOS-sovellusten pakkaamista sinun on ladattava renios, Ren'Py:n iOS-tuki. Haluaisitko ladata reniosin nyt?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE-PROJEKTIKANSIO"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Ole hyvä ja valitse Xcode-projektikansio käyttämällä resurssienhallintaa.\n{b}Kansion valinta on saattanut aueta tämän ikkunan taakse.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py on asettanut Xcode-projektikansioksi:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navigoi: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Järjestys: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "aakkosellinen"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "tiedoston mukaan"
+
+    # navigation.rpy:182
+    old "natural"
+    new "luonnollinen"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Kategoria:"
+
+    # navigation.rpy:196
+    old "files"
+    new "tiedostot"
+
+    # navigation.rpy:197
+    old "labels"
+    new "tunnukset"
+
+    # navigation.rpy:198
+    old "defines"
+    new "määritelmät"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "muutokset"
+
+    # navigation.rpy:200
+    old "screens"
+    new "ikkunat"
+
+    # navigation.rpy:201
+    old "callables"
+    new "kutsuttavat"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODO:t"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Lisää skriptitiedosto"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "TODO-kommentteja ei löytynyt.\n\nLuodaksesi sellaisen, lisää \"# TODO\" skriptiisi."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Nimilista on tyhjä."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Projektikansion valinta epäonnistui."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Valitse projektipohja"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Valitse pohja käytettäväksi uudessa projektissasi. Se asettaa perusfontin ja kielen. Jos kieltäsi ei löydy, valitse englanti (English)."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Työkalun asetukset"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Projektien kansio"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Projektikansio: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Ei valittu"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Tekstieditori:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Tekstieditori: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Päivityskanava:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Hakuasetukset"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Sisällytä yksityiset nimet"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Sisällytä kirjastot"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Työkalun asetukset"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Laitteistorenderöinti"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Näytä esimerkkipohjat"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Näytä tiedostojen muokkausvalikko"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Suuret fontit"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Konsolisyöte"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Avaa työkaluprojekti"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Kieli:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Kun olet tehnyt muutoksia pelin tiedostoihin, paina shift+R käynnistääksesi pelisi automaattisesti uudelleen."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Paina shift+O (kirjain) päästäksesi käsiksi konsoliin."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Paina shift+D avataksesi kehittäjävalikon."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Oletko ottanut projekteistasi varmuuskopiot viime aikoina?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Projektin käynnistys epäonnistui."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Varmista, että projektisi käynnistyy normaalisti ennen kuin käytät tätä komentoa."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py skannaa projektia..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Käynnistetään..."
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "PROJEKTIKANSIO"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Ole hyvä ja valitse kansio, jota haluat käyttää projektiesi tallentamiseen.\n{b}Kansion valitsija on saattanut aueta tämän ikkunan taakse.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Tämä työkalu etsii, luo sekä muokkaa projekteja, jotka löytyvät tästä kansiosta."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py on valinnut projektikansioksi:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Luo tyhjiä merkkijonoja käännöksiä varten"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py luo käännöksiä...."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py on onnistuneesti luonut [language] käännöstiedostot."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Kopioi dialogi: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Formaatti:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Taulukkotiedosto (dialogi.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogi pelkkänä tekstinä (dialogi.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Kopioi tekstitägit dialogista."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Kaikki erikoismerkit."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Kopioi kaikki käännettävät sanat, ei pelkkää dialogia."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py kopioi dialogia...."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py on onnistuneesti kopioinut dialogin. Kopio löytyy tiedostosta dialogue.[persistent.dialogue_format] projektin kansiosta."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Valitse päivityskanava"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Päivityskanava vaikuttaa siihen, mihin versioon Ren'Py päivitetään. Valitse päivityskanava:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Vakaat versiot"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Suositeltu.{/b} Ren'Py:n uusin, vakaa versio, jota suositellaan käytettäväksi."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Esiversiot"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Ennakkoversio Ren'Py:n seuraavasta versiosta, jota voidaan käyttää uusien ominaisuuksien testaamiseen ja hyödyntämiseen. Ei suositella pelien julkaisemiseen."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Kokeelliset versiot"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Ren'Py:n kokeellisia versioita. Sinun ei kannata valita tätä, ellei joku Ren'Py:n kehittäjistä erikseen sitä pyydä."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Jokaöiset julkaisut"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Upouudet Ren'Py-kehitysjulkaisut. Voi sisältää uusimmat toiminnot, tai ei ehkä toimi lainkaan."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "On tapahtunut virhe:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Haetaan päivityksiä."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Käytät uusinta Ren'Py-versiota."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] on nyt saatavilla. Haluatko asentaa sen?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Valmistellaan päivityksen lataamista."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Ladataan päivitystä."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Puretaan päivitystä."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Viimeistellään asennusta."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Päivitys on nyt asennettu. Ren'Py käynnistyy nyt uudelleen."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Päivitys on asennettu."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Päivitys peruttiin."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ren'Py-päivitys"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Jatka"
+
diff --git a/launcher/game/tl/finnish/mobilebuild.rpy b/launcher/game/tl/finnish/mobilebuild.rpy
deleted file mode 100644
index e1803ed..0000000
--- a/launcher/game/tl/finnish/mobilebuild.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate finnish strings:
-
-    # game/mobilebuild.rpy:109
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
diff --git a/launcher/game/tl/finnish/navigation.rpy b/launcher/game/tl/finnish/navigation.rpy
deleted file mode 100644
index 12bd0db..0000000
--- a/launcher/game/tl/finnish/navigation.rpy
+++ /dev/null
@@ -1,66 +0,0 @@
-
-translate finnish strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "Navigoi: [project.current.name]"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "Järjestys: "
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "aakkosellinen"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "tiedoston mukaan"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "luonnollinen"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "Kategoria:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "tiedostot"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "tunnukset"
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "määritelmät"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "muutokset"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "ikkunat"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "kutsuttavat"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "TODO:t"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ Lisää skriptitiedosto"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "TODO-kommentteja ei löytynyt.\n\nLuodaksesi sellaisen, lisää \"# TODO\" skriptiisi."
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "Nimilista on tyhjä."
diff --git a/launcher/game/tl/finnish/new_project.rpy b/launcher/game/tl/finnish/new_project.rpy
deleted file mode 100644
index 566ee3d..0000000
--- a/launcher/game/tl/finnish/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate finnish strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "Valitse projektipohja"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Valitse pohja käytettäväksi uudessa projektissasi. Se asettaa perusfontin ja kielen. Jos kieltäsi ei löydy, valitse englanti (English)."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Projektikansion valinta epäonnistui."
-
-    # game/new_project.rpy:75
-    old "PROJECT NAME"
-    new "PROJEKTIN NIMI"
-
-    # game/new_project.rpy:75
-    old "Please enter the name of your project:"
-    new "Ole hyvä ja nimeä projektisi:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "Projektin nimi ei voi olla tyhjä."
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] on jo olemassa. Ole hyvä ja valitse toinen nimi projektillesi."
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] on jo olemassa. Ole hyvä ja valitse toinen nimi projektillesi."
-
diff --git a/launcher/game/tl/finnish/obsolete.rpy b/launcher/game/tl/finnish/obsolete.rpy
new file mode 100644
index 0000000..e368d17
--- /dev/null
+++ b/launcher/game/tl/finnish/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate finnish strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Peliohjaimen näppäinten asetus"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Tyhjä paikka."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Edellinen"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Seuraava"
+
diff --git a/launcher/game/tl/finnish/options.rpy b/launcher/game/tl/finnish/options.rpy
new file mode 100644
index 0000000..26ba360
--- /dev/null
+++ b/launcher/game/tl/finnish/options.rpy
@@ -0,0 +1,195 @@
+
+translate finnish strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/finnish/preferences.rpy b/launcher/game/tl/finnish/preferences.rpy
deleted file mode 100644
index 3da66f6..0000000
--- a/launcher/game/tl/finnish/preferences.rpy
+++ /dev/null
@@ -1,85 +0,0 @@
-
-translate finnish strings:
-
-    # game/preferences.rpy:61
-    old "Launcher Preferences"
-    new "Työkalun asetukset"
-
-    # game/preferences.rpy:82
-    old "Projects Directory:"
-    new "Projektien kansio"
-
-    # game/preferences.rpy:89
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:91
-    old "Projects directory: [text]"
-    new "Projektikansio: [text]"
-
-    # game/preferences.rpy:93
-    old "Not Set"
-    new "Ei valittu"
-
-    # game/preferences.rpy:108
-    old "Text Editor:"
-    new "Tekstieditori:"
-
-    # game/preferences.rpy:114
-    old "Text editor: [text]"
-    new "Tekstieditori: [text]"
-
-    # game/preferences.rpy:130
-    old "Update Channel:"
-    new "Päivityskanava:"
-
-    # game/preferences.rpy:150
-    old "Navigation Options:"
-    new "Hakuasetukset"
-
-    # game/preferences.rpy:154
-    old "Include private names"
-    new "Sisällytä yksityiset nimet"
-
-    # game/preferences.rpy:155
-    old "Include library names"
-    new "Sisällytä kirjastot"
-
-    # game/preferences.rpy:165
-    old "Launcher Options:"
-    new "Työkalun asetukset"
-
-    # game/preferences.rpy:169
-    old "Hardware rendering"
-    new "Laitteistorenderöinti"
-
-    # game/preferences.rpy:170
-    old "Show templates"
-    new "Näytä esimerkkipohjat"
-
-    # game/preferences.rpy:171
-    old "Large fonts"
-    new "Suuret fontit"
-
-    # game/preferences.rpy:174
-    old "Console output"
-    new "Konsolisyöte"
-
-    # game/preferences.rpy:195
-    old "Open launcher project"
-    new "Avaa työkaluprojekti"
-
-    # game/preferences.rpy:209
-    old "Language:"
-    new "Kieli:"
-
-
-translate finnish strings:
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "Näytä tiedostojen muokkausvalikko"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "Luo tyhjiä merkkijonoja käännöksiä varten"
diff --git a/launcher/game/tl/finnish/project.rpy b/launcher/game/tl/finnish/project.rpy
deleted file mode 100644
index 61f9261..0000000
--- a/launcher/game/tl/finnish/project.rpy
+++ /dev/null
@@ -1,54 +0,0 @@
-
-translate finnish strings:
-
-    # game/project.rpy:47
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Kun olet tehnyt muutoksia pelin tiedostoihin, paina shift+R käynnistääksesi pelisi automaattisesti uudelleen."
-
-    # game/project.rpy:47
-    old "Press shift+O (the letter) to access the console."
-    new "Paina shift+O (kirjain) päästäksesi käsiksi konsoliin."
-
-    # game/project.rpy:47
-    old "Press shift+D to access the developer menu."
-    new "Paina shift+D avataksesi kehittäjävalikon."
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "Oletko ottanut projekteistasi varmuuskopiot viime aikoina?"
-
-    # game/project.rpy:223
-    old "Launching the project failed."
-    new "Projektin käynnistys epäonnistui."
-
-    # game/project.rpy:223
-    old "Please ensure that your project launches normally before running this command."
-    new "Varmista, että projektisi käynnistyy normaalisti ennen kuin käytät tätä komentoa."
-
-    # game/project.rpy:236
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py skannaa projektia..."
-
-    # game/project.rpy:525
-    old "Launching"
-    new "Käynnistetään..."
-
-    # game/project.rpy:554
-    old "PROJECTS DIRECTORY"
-    new "PROJEKTIKANSIO"
-
-    # game/project.rpy:554
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Ole hyvä ja valitse kansio, jota haluat käyttää projektiesi tallentamiseen.\n{b}Kansion valitsija on saattanut aueta tämän ikkunan taakse.{/b}"
-
-    # game/project.rpy:554
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Tämä työkalu etsii, luo sekä muokkaa projekteja, jotka löytyvät tästä kansiosta."
-
-    # game/project.rpy:594
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren'Py ei kyennyt käyttämään pythonia tkinterillä valitakseen projektikansion. Ole hyvä ja asenna python-tk tai tkinter-paketti."
-
-    # game/project.rpy:604
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py on valinnut projektikansioksi:"
diff --git a/launcher/game/tl/finnish/screens.rpy b/launcher/game/tl/finnish/screens.rpy
new file mode 100644
index 0000000..4a93077
--- /dev/null
+++ b/launcher/game/tl/finnish/screens.rpy
@@ -0,0 +1,643 @@
+
+translate finnish strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Takaisin"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Skip"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Save"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.Save"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.Load"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Preferences"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Main Menu"
+
+    # screens.rpy:328
+    old "About"
+    new "Tietoja"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Help"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Poistu"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Palaa"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Sivu {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automaattiset tallennukset"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Pikatallennukset"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Näyttö"
+
+    # screens.rpy:739
+    old "Window"
+    new "Ikkuna"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Koko näyttö"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Poista käytöstä"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "After Choices"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transitions"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Text Speed"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Auto-Forward Time"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Music Volume"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Äänenvoimakkuus"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Voice Volume"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Peliohjain"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Kalibroi"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Kyllä"
+
+    # screens.rpy:1162
+    old "No"
+    new "Ei"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/finnish/style.rpy b/launcher/game/tl/finnish/style.rpy
index f501dba..e02abfc 100644
--- a/launcher/game/tl/finnish/style.rpy
+++ b/launcher/game/tl/finnish/style.rpy
@@ -1,2 +1 @@
-translate finnish python:
-    make_style_backup()
+
diff --git a/launcher/game/tl/finnish/translations.rpy b/launcher/game/tl/finnish/translations.rpy
deleted file mode 100644
index 4bed094..0000000
--- a/launcher/game/tl/finnish/translations.rpy
+++ /dev/null
@@ -1,59 +0,0 @@
-
-translate finnish strings:
-
-    # game/translations.rpy:34
-    old "Create or Update Translations"
-    new "Luo tai päivitä käännöksiä"
-
-    # game/translations.rpy:34
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Ole hyvä ja anna sen kielen nimi, jolle haluat luoda tai päivittää käännöksen."
-
-    # game/translations.rpy:39
-    old "The language name can not be the empty string."
-    new "Kielen nimi ei voi olla tyhjä."
-
-    # game/translations.rpy:50
-    old "Ren'Py is generating translations...."
-    new "Ren'Py luo käännöksiä...."
-
-    # game/translations.rpy:54
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py on onnistuneesti luonut [language] käännöstiedostot."
-
-    # game/translations.rpy:68
-    old "Extract Dialogue: [project.current.name!q]"
-    new "Kopioi dialogi: [project.current.name!q]"
-
-    # game/translations.rpy:84
-    old "Format:"
-    new "Formaatti:"
-
-    # game/translations.rpy:92
-    old "Tab-delimited Spreadsheet (dialogue.tab)"
-    new "Taulukkotiedosto (dialogi.tab)"
-
-    # game/translations.rpy:93
-    old "Dialogue Text Only (dialogue.txt)"
-    new "Dialogi pelkkänä tekstinä (dialogi.txt)"
-
-    # game/translations.rpy:106
-    old "Strip text tags from the dialogue."
-    new "Kopioi tekstitägit dialogista."
-
-    # game/translations.rpy:107
-    old "Escape quotes and other special characters."
-    new "Kaikki erikoismerkit."
-
-    # game/translations.rpy:108
-    old "Extract all translatable strings, not just dialogue."
-    new "Kopioi kaikki käännettävät sanat, ei pelkkää dialogia."
-
-    # game/translations.rpy:136
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py kopioi dialogia...."
-
-    # game/translations.rpy:140
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
-    new "Ren'Py on onnistuneesti kopioinut dialogin. Kopio löytyy tiedostosta dialogue.[persistent.dialogue_format] projektin kansiosta."
-
diff --git a/launcher/game/tl/finnish/updater.rpy b/launcher/game/tl/finnish/updater.rpy
deleted file mode 100644
index 71d7ab0..0000000
--- a/launcher/game/tl/finnish/updater.rpy
+++ /dev/null
@@ -1,94 +0,0 @@
-
-translate finnish strings:
-
-    # game/updater.rpy:78
-    old "Select Update Channel"
-    new "Valitse päivityskanava"
-
-    # game/updater.rpy:89
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Päivityskanava vaikuttaa siihen, mihin versioon Ren'Py päivitetään. Valitse päivityskanava:"
-
-    # game/updater.rpy:94
-    old "Release"
-    new "Vakaat versiot"
-
-    # game/updater.rpy:100
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Suositeltu.{/b} Ren'Py:n uusin, vakaa versio, jota suositellaan käytettäväksi."
-
-    # game/updater.rpy:105
-    old "Prerelease"
-    new "Esiversiot"
-
-    # game/updater.rpy:111
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Ennakkoversio Ren'Py:n seuraavasta versiosta, jota voidaan käyttää uusien ominaisuuksien testaamiseen ja hyödyntämiseen. Ei suositella pelien julkaisemiseen."
-
-    # game/updater.rpy:117
-    old "Experimental"
-    new "Kokeelliset versiot"
-
-    # game/updater.rpy:123
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Ren'Py:n kokeellisia versioita. Sinun ei kannata valita tätä, ellei joku Ren'Py:n kehittäjistä erikseen sitä pyydä."
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "Jokaöiset julkaisut"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Upouudet Ren'Py-kehitysjulkaisut. Voi sisältää uusimmat toiminnot, tai ei ehkä toimi lainkaan."
-
-    # game/updater.rpy:155
-    old "An error has occured:"
-    new "On tapahtunut virhe:"
-
-    # game/updater.rpy:157
-    old "Checking for updates."
-    new "Haetaan päivityksiä."
-
-    # game/updater.rpy:159
-    old "Ren'Py is up to date."
-    new "Käytät uusinta Ren'Py-versiota."
-
-    # game/updater.rpy:161
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] on nyt saatavilla. Haluatko asentaa sen?"
-
-    # game/updater.rpy:163
-    old "Preparing to download the update."
-    new "Valmistellaan päivityksen lataamista."
-
-    # game/updater.rpy:165
-    old "Downloading the update."
-    new "Ladataan päivitystä."
-
-    # game/updater.rpy:167
-    old "Unpacking the update."
-    new "Puretaan päivitystä."
-
-    # game/updater.rpy:169
-    old "Finishing up."
-    new "Viimeistellään asennusta."
-
-    # game/updater.rpy:171
-    old "The update has been installed. Ren'Py will restart."
-    new "Päivitys on nyt asennettu. Ren'Py käynnistyy nyt uudelleen."
-
-    # game/updater.rpy:173
-    old "The update has been installed."
-    new "Päivitys on asennettu."
-
-    # game/updater.rpy:175
-    old "The update was cancelled."
-    new "Päivitys peruttiin."
-
-    # game/updater.rpy:192
-    old "Ren'Py Update"
-    new "Ren'Py-päivitys"
-
-    # game/updater.rpy:198
-    old "Proceed"
-    new "Jatka"
diff --git a/launcher/game/tl/french/about.rpy b/launcher/game/tl/french/about.rpy
deleted file mode 100644
index f75b14a..0000000
--- a/launcher/game/tl/french/about.rpy
+++ /dev/null
@@ -1,10 +0,0 @@
-translate french strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "Voir la licence"
-
diff --git a/launcher/game/tl/french/add_file.rpy b/launcher/game/tl/french/add_file.rpy
deleted file mode 100644
index 7e23fbb..0000000
--- a/launcher/game/tl/french/add_file.rpy
+++ /dev/null
@@ -1,22 +0,0 @@
-translate french strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "NOM DU FICHIER"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Entrez le nom du fichier de script à créer."
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "Le fichier doit avoir l'extension .rpy."
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "Le fichier éxiste déjà."
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "Ren'Py charge automatiquement tous les fichiers de script finissant par .rpy. Pour utiliser ce ficher\n#, définissez un label et faites un «jump» vers lui depuis un autre fichier.\n"
-
diff --git a/launcher/game/tl/french/android.rpy b/launcher/game/tl/french/android.rpy
deleted file mode 100644
index 0f874e3..0000000
--- a/launcher/game/tl/french/android.rpy
+++ /dev/null
@@ -1,101 +0,0 @@
-translate french strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Pour construire les paquets Android, téléchargez RAPT (depuis {a=http://www.renpy.org/dl/android}here{/a}), dézippé le, et placez le dans le répertoire de Ren'Py. Puis, redémarrez Ren'Py."
-
-    # game/android.rpy:13
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT a été installé, mais vous devez installer le kit de développement Android pour pouvoir construire les paquets Android. Choisissez \"installer le kit de développement et créer les clés\" pour cela"
-
-    # game/android.rpy:14
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT a été installé, mais aucune clé n'a été configurée. Créez une nouvelle clé, ou restaurez android.keystore."
-
-    # game/android.rpy:15
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Le projet courant n'a pas été configuré. Choisissez \"Configurer\' pour effectuer la configuration."
-
-    # game/android.rpy:16
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Choisissez \"Construire\" pour construire le projet courant, ou connecté un appareil Android et choisissez \"Construire et Installer\" pour l'installer sur l'appareil."
-
-    # game/android.rpy:18
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Tentative d'émulation d'un téléphone Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
-
-    # game/android.rpy:19
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Tentative d'émulation d'une tablette Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Tentative d'émulation d'une console OUYA.\n\nLe pad est émulé via les flèches du clavier. La touche Entrée correspond au bouton select, la barre d'espace au bouton menu, et la touche PageUp correspond au bouton retour."
-
-    # game/android.rpy:22
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Télécharge et installe le kit de développement Android et les paquets supportés. Optionnellement, génère les clés requises pour signer le paquet."
-
-    # game/android.rpy:23
-    old "Configures the package name, version, and other information about this project."
-    new "Configure le nom du packet, sa version et d'autres informations à propos de ce projet."
-
-    # game/android.rpy:24
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Ouvre le fichier contenant les clés Google Play dans l'éditeur.\n\nCela est nécessaire uniquement si l'application utilise une expansion APK. Référez-vous à la documentation pour plus d'informations."
-
-    # game/android.rpy:25
-    old "Builds the Android package."
-    new "Construire le paquet Android."
-
-    # game/android.rpy:26
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Construire le paquet Android, et l'installer sur l'appareil Android connecté à votre ordinateur."
-
-    # game/android.rpy:142
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:361
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:381
-    old "Emulation:"
-    new "Émulateur:"
-
-    # game/android.rpy:389
-    old "Phone"
-    new "Téléphone"
-
-    # game/android.rpy:393
-    old "Tablet"
-    new "Tablette"
-
-    # game/android.rpy:397
-    old "Television / OUYA"
-    new "Télévision / OUYA"
-
-    # game/android.rpy:409
-    old "Build:"
-    new "Construire:"
-
-    # game/android.rpy:417
-    old "Install SDK & Create Keys"
-    new "Installer le kit de développement et créer les clés"
-
-    # game/android.rpy:421
-    old "Configure"
-    new "Configurer"
-
-    # game/android.rpy:425
-    old "Build Package"
-    new "Construire le paquet"
-
-    # game/android.rpy:429
-    old "Build & Install"
-    new "Construire et installer"
-
-    # game/android.rpy:13
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Un Kit de Développement Java (JDK) 32 bits est nécessaire pour construire les paquets pour Android depuis Windows. Le JDK n'est pas la même chose que le JRE, il est possible que Java soit installé sur votre machine sans le JDK.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Téléchargez et installez le JDK{/a}, puis relancer le lanceur Ren'Py."
diff --git a/launcher/game/tl/french/choose_theme.rpy b/launcher/game/tl/french/choose_theme.rpy
deleted file mode 100644
index 741ffc5..0000000
--- a/launcher/game/tl/french/choose_theme.rpy
+++ /dev/null
@@ -1,41 +0,0 @@
-translate french strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Impossible de changer le thème. Peut être que options.rpy a été trop modifié."
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Affichage"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Fenêtre"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Plein écran"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Volume sonore"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Choisir un thème"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "Thème"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "Agencement des couleurs"
-
-    # game/choose_theme.rpy:444
-    old "Continue"
-    new "Continuer"
diff --git a/launcher/game/tl/french/common.rpy b/launcher/game/tl/french/common.rpy
index 4cc734e..d1e481a 100644
--- a/launcher/game/tl/french/common.rpy
+++ b/launcher/game/tl/french/common.rpy
@@ -1,281 +1,335 @@
-translate french strings:
+
+translate french strings:
 
-    # renpy/common/00updater.rpy:1258
-    old "Updater"
-    new "Programme de mise à jour"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00updater.rpy:1267
-    old "This program is up to date."
-    new "Ce programme est à jour."
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-    # renpy/common/00updater.rpy:1269
-    old "[u.version] is available. Do you want to install it?"
-    new "La version [u.version]. Voulez-vous l'installer ?"
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00updater.rpy:1271
-    old "Preparing to download the updates."
-    new "Préparation du téléchargement de la mise à jour."
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00updater.rpy:1273
-    old "Downloading the updates."
-    new "Téléchargement de la mise à jour."
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00updater.rpy:1275
-    old "Unpacking the updates."
-    new "Dépaquetage de la mise à jour."
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00updater.rpy:1279
-    old "The updates have been installed. The program will restart."
-    new "La mise à jour a bien été effectuée. Le programme va redémarrer."
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00updater.rpy:1281
-    old "The updates have been installed."
-    new "La mise à jour a bien été effectuée."
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-    # renpy/common/00updater.rpy:1283
-    old "The updates were cancelled."
-    new "La mise à jour a été annullée."
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-    # renpy/common/_layout/classic_load_save.rpym:120
-    old "Empty Slot."
-    new "Emplacement vide."
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/_layout/classic_joystick_preferences.rpym:76
-    old "Joystick Mapping"
-    new "Joystick"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00layout.rpy:421
-    old "Are you sure?"
-    new "Êtes-vous sûr ?"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00layout.rpy:422
-    old "Are you sure you want to delete this save?"
-    new "Êtes-vous sûr de vouloir supprimer cette sauvegarde ?"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00layout.rpy:423
-    old "Are you sure you want to overwrite your save?"
-    new "Êtes-vous sûr de vouloir écraser cette sauvegarde ?"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00layout.rpy:424
-    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
-    new "En effectuant ce chargement, vous perderez votre avancement non sauvegardé.\nÊtes-vous sûr de vouloire faire ça ?"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00layout.rpy:425
-    old "Are you sure you want to quit?"
-    new "Êtes-vous sûr de vouloir quitter ?"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00layout.rpy:426
-    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
-    new "Êtes-vous sûr de vouloir retourner au menu principal ?\nVous perdrez votre avancement non sauvegardé."
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00keymap.rpy:167
-    old "Saved screenshot as %s."
-    new "La capture d'écran a été enregistrée en tant que %s"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
+
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Accélération graphique"
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Choix automatique"
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d, %H:%M"
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Forcer le rendu Angle/DirectX"
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Sauvegarde rapide effectuée."
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "Forcer le rendu OpenGL"
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "Êtes-vous sûr ?"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Forcer le rendu logiciel"
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "Êtes-vous sûr de vouloir supprimer cette sauvegarde ?"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Les changement seront pris en compte au prochin démarrage du programme."
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "Êtes-vous sûr de vouloir écraser cette sauvegarde ?"
 
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "Quitter"
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "Le chargement entraînera la perte des données non sauvegardées.\nÊtes-vous sûr de vouloir faire cela ?"
 
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Retour"
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "Êtes-vous sûr de vouloir quitter ?"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Avertissement sur les performances"
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "Êtes-vous sûr de vouloir retourner au menu principal ?\nVous perdrez les données non sauvegardées."
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Cet ordinateur utilise le rendu logiciel."
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Cet ordinateur n'utilise pas les shaders."
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "Êtes-vous sûr de vouloir commencer à sauter ?"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Cet ordinateur affiche lentement les graphismes."
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "Êtes-vous sûr de vouloir sauter jusqu'au prochain choix ?"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Cet ordinateur rencontre des difficultés à afficher les graphismes: [problem]."
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Les pilotes graphiques ne semblent pas à jour ou dysfonctionnent. Cela peut entraîner des ralentissements ou de mauvais affichages. Mettre à jour DirectX pourraît régler ce problème."
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Sauvez cette capture d'écran sous le nom %s."
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Les pilotes graphiques ne semblent pas à jour ou dysfonctionnent. Cela peut entraîner des ralentissements ou de mauvais affichages."
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "Mettre à jour DirectX"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Continer, Afficher cet avertissement la prochaine fois."
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Continer, Ne plus afficher cet avertissement."
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Mode saut"
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "Mettre à jour de DirectX en cours"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "La mise à jour de DirectX a débutée. Elle est sans doute minimisée dans la bare de tâche. Merci de suivre les instructions pour installer DirectX."
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Clipboard voicing enabled. Press 'shift+C' to disable."
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Note:{/b} le programme d'installation de Microsoft's DirectX va, par defaut, installer la barre d'outils Bing. Si vous ne voulez pas de cette barre, décochez la case appropriée."
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "Lorsque l'instllation sera terminée, cliquez ci-dessous pour redémarrer ce programme."
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Self-voicing enabled. Press 'v' to disable."
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Redémarrer"
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "Une exception a été levée."
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "The Ren'Py Updater is not supported on mobile devices."
 
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Revenir en arrière"
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "An error is being simulated."
 
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Tenter de revenir en arrière, vous permet de sauvegarder ou de faire un autre choix."
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Either this project does not support updating, or the update status file was deleted."
 
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "Ignorer"
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "This account does not have permission to perform an update."
 
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Ignorer l'exception vous permet de continuer. Cela entraîne généralement des erreurs additionelles."
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "This account does not have permission to write the update log."
 
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "Recharger"
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "Could not verify update signature."
 
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Recharger le jeu depuis le disque dur and tenter de restaurer le jeu dans l'état actuel."
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "The update file was not downloaded."
 
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "Ouvrir la pile d'appel"
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "The update file does not have the correct digest - it may have been corrupted."
 
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Ouvrir traceback.txt dans un éditeur de texte."
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "While unpacking {}, unknown type {}."
 
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "Quitter le jeu."
+    # 00updater.rpy:1393
+    old "Updater"
+    new "Mise à jour"
 
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "L'analyse du script a échouée."
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "Ce programme est à jour."
 
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Ouvrir les erreurs d'analyse."
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] est disponible. Voulez-vous l'installer ?"
 
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Ouvrir errors.txt dans un éditeur de texte."
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "Préparation au téléchargement de la mise à jour."
 
-    # renpy/common/00action_file.rpy:118
-    old "%b %d, %H:%M"
-    new "%b %d, %H:%M"
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "Téléchargement de la mise à jour."
 
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Précédent"
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "Dépaquetage de la mise à jour."
 
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Suivant"
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "La mise à jour a été installée. Le programme va redémarrer."
 
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "Mode rapide"
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "La mise à jour a été installée."
 
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Mode très rapide"
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "La mise à jour a été annulée."
 
-    # renpy/common/00gallery.rpy:521
+    # 00gallery.rpy:563
     old "Image [index] of [count] locked."
-    new "Image [index] sur [count] verrouillée."
+    new "Image [index] sur [count] bloquée."
 
-    # renpy/common/00gallery.rpy:539
+    # 00gallery.rpy:583
     old "prev"
-    new "précédent"
+    new "prec."
 
-    # renpy/common/00gallery.rpy:540
+    # 00gallery.rpy:584
     old "next"
-    new "suivant"
+    new "suiv."
 
-    # renpy/common/00gallery.rpy:541
+    # 00gallery.rpy:585
     old "slideshow"
     new "diaporama"
 
-    # renpy/common/00gallery.rpy:542
+    # 00gallery.rpy:586
     old "return"
     new "retour"
 
-    # renpy/common/00layout.rpy:427
-    old "Are you sure you want to begin skipping?"
-    new "Êtes-vous sûr de vouloir commencer à sauter certaines étapes ?"
-
-    # renpy/common/00layout.rpy:428
-    old "Are you sure you want to skip to the next choice?"
-    new "Êtes-vous sûr de vouloir sauter le prochain choix ?"
-
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Êtes-vous sûr de vouloir sauter des dialogues non lus or le prochain choix ?"
-
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "Sauvegarde rapide effectuée."
diff --git a/launcher/game/tl/french/developer.rpy b/launcher/game/tl/french/developer.rpy
new file mode 100644
index 0000000..fa9130c
--- /dev/null
+++ b/launcher/game/tl/french/developer.rpy
@@ -0,0 +1,179 @@
+
+translate french strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Developer Menu"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Reload Game (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Console (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Variable Viewer"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Theme Test"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Image Location Picker"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Filename List"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Show Image Load Log"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Hide Image Load Log"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Nothing to inspect."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Return to the developer menu"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rectangle: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Mouse position: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Right-click or escape to quit."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectangle copied to clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Position copied to clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable Inspector"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Size"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Style"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Location"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Inspecting Styles of [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (no properties affect the displayable)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (default properties omitted)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Press <esc> to exit console. Type help for help.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren'Py script enabled."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren'Py script disabled."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: show this help"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "commands:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: run the statement\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: run the expression or statement"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: clear the console history"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: exit the console"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: loads the game from slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: saves the game in slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: reloads the game, refreshing the scripts"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: watch a python expression"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: stop watching an expression"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: stop watching all expressions"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: jumps to label"
+
diff --git a/launcher/game/tl/french/distribute.rpy b/launcher/game/tl/french/distribute.rpy
deleted file mode 100644
index f8865e8..0000000
--- a/launcher/game/tl/french/distribute.rpy
+++ /dev/null
@@ -1,37 +0,0 @@
-translate french strings:
-
-    # game/distribute.rpy:333
-    old "Nothing to do."
-    new "Rien à faire."
-
-    # game/distribute.rpy:337
-    old "Scanning project files..."
-    new "Scan des fichiers du projet..."
-
-    # game/distribute.rpy:344
-    old "Scanning Ren'Py files..."
-    new "Scan des fichiers Ren'Py..."
-
-    # game/distribute.rpy:494
-    old "Archiving files..."
-    new "Archivage des fichiers..."
-
-    # game/distribute.rpy:745
-    old "Writing the [variant] [format] package."
-    new "Écriture du paquet [variant] [format]."
-
-    # game/distribute.rpy:758
-    old "Making the [variant] update zsync file."
-    new "Création du fichier de mise à jour zsync [variant]."
-
-    # game/distribute.rpy:854
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Traitement du fichier {b}[complete]{/b} sur {b}[total]{/b}."
-
-    # game/distribute.rpy:915
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Tous les paquets ont été contruits.\n\nDu fait de la présence des systèmes de permissions, il n'est pas possible de reconstruire les paquets construits sur GNU-Linux ou Mac OS sur Windows."
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Aucun paquet sélectionné, il n'y a donc rien à faire."
diff --git a/launcher/game/tl/french/distribute_gui.rpy b/launcher/game/tl/french/distribute_gui.rpy
deleted file mode 100644
index 98012b4..0000000
--- a/launcher/game/tl/french/distribute_gui.rpy
+++ /dev/null
@@ -1,41 +0,0 @@
-translate french strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Construction des packets: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Nom du répertoire:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Nom de l'exécutable:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "Éditer options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Rafraichir"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Construire les packets:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "Construire les mises à jour"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "Construire"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Des erreurs ont été détectées lors de l'utilisation du projet. Assurez-vous qu'il n'y ait plus d'erreur avant de construire les packets."
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Votre projet ne contient pas d'information pour la construction. Voulez-vous ajouter ces informations à la fin de options.rpy ?"
diff --git a/launcher/game/tl/french/editor.rpy b/launcher/game/tl/french/editor.rpy
deleted file mode 100644
index 59bdd2a..0000000
--- a/launcher/game/tl/french/editor.rpy
+++ /dev/null
@@ -1,57 +0,0 @@
-translate french strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen."
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen. Sur GNU-Linux, Editra nécessite wxPython."
-
-    # game/editor.rpy:137
-    old "The may have occured because wxPython is not installed on this system."
-    new "Cela est sans doute arrivé car wxPython n'est pas installé sur ce système."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Jusqu'à 22 MB de téléchargement requis."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "1.8 MB de réléchargement requis."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Cela est sans doute arrivé car Java n'est pas installé sur ce système."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Une exception a été levée lors du lancement de l'édieteur de texte :\n[exception!q]"
-
-    # game/editor.rpy:378
-    old "Select Editor"
-    new "Sélectionnez un éditeur"
-
-    # game/editor.rpy:393
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Un éditeur de texte est un logiciel que vous utilisez pour éditer les fichiers de script Ren'Py. Vous pouvez choisir l'édteur que Ren'Py utilise. Si ce n'est pas déjà le cas, l'éditeur sera automatiquement téléchargé et installé."
-
-    # game/editor.rpy:415
-    old "Cancel"
-    new "Annuler"
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Cela est sans doute dû au fait que wxPython n'est pas installé sur votre système."
-
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Un éditeur éprouvé nécessitant Java."
-
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Lance l'éditeur associé par votre systèmes aux fichiers .rpy."
-
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Empêche Ren'Py d'ouvrir un éditeur de texte."
diff --git a/launcher/game/tl/french/error.rpy b/launcher/game/tl/french/error.rpy
new file mode 100644
index 0000000..069cb96
--- /dev/null
+++ b/launcher/game/tl/french/error.rpy
@@ -0,0 +1,179 @@
+
+translate french strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Accélération graphique"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Choix automatique"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Forcer le rendu 'Angle/DirectX'"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Forcer le rendu 'OpenGL'"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Forcer le rendu logiciel"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Les changements prendront effet au prochain démarrage du programme."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Avertissement concernant les performances."
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Cet ordinateur utilise le rendu logiciel."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Cet ordinateur n'utilise pas les 'shaders'."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Cet ordinateur affiche lentement les graphismes."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Cet ordinateur a un problème pour afficher les graphismes: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Les pilotes graphiques sont peut être pas à jour ou n'oppèrent pas correctement. Cela peut entraîner des lenteurs ou des erreurs d'affichage. Mettre à jour DirectX pourrait résoudre ce problème."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Les pilotes graphiques sont peut être pas à jour ou n'opèrent pas correctement. Cela peut entraîner des lenteurs ou des erreurs d'affichage."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Mettre à jour DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Continuer. Montrer cet avertissement à chaque fois."
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Continuer. Ne plus montrer cet avertissement."
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Mise à jour de DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "La page Web d'installation de DirectX a été lancé. Il se peut que la page soit minimisée. Suivez les instructions pour installer DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Note:{/b} la page web d'installation de Microsoft DirectX va, par défaut, installer le barre d'outils Bing. Décochez la case appropriée si vous ne voulez pas de cette barre d'outils."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Quand l'installation est terminée, cliquez ci-dessous pour redémarrer ce programme."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Redémarrer"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Ouvrir le fichier de déboguage."
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Ouvrir le fichier 'traceback.txt' dans un éditeur de texte."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Une exception est apparue."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Retour arrière"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Essai de retour arrière, permettant de sauvegarder ou de faire un choix différent."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Ignorer"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Ignorer l'exception, et continuer. Cela amène souvent à de nouvelles erreurs."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Recharger"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Recharger le jeu depuis le disque, sauvegarder et restaurer le jeu dans son état actuel si possible."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Quitter le jeu."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Échec dans l'interprétation du jeu."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Ouvrir les erreurs d'interprétation"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Ouvrir le fihchier 'errors.txt' dans un éditeur de texte."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/french/front_page.rpy b/launcher/game/tl/french/front_page.rpy
deleted file mode 100644
index 7374937..0000000
--- a/launcher/game/tl/french/front_page.rpy
+++ /dev/null
@@ -1,81 +0,0 @@
-translate french strings:
-
-    # game/front_page.rpy:79
-    old "+ Create New Project"
-    new "+ Créer un nouveau projet"
-
-    # game/front_page.rpy:111
-    old "Tutorial"
-    new "Tutoriel"
-
-    # game/front_page.rpy:112
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:128
-    old "Active Project"
-    new "Projet actif"
-
-    # game/front_page.rpy:136
-    old "Open Directory"
-    new "Ouvrir le répertoire"
-
-    # game/front_page.rpy:141
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:142
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:148
-    old "Edit File"
-    new "Éditer le fichier"
-
-    # game/front_page.rpy:156
-    old "All script files"
-    new "Tous les fichiers de script"
-
-    # game/front_page.rpy:165
-    old "Navigate Script"
-    new "Naviguer dans le script"
-
-    # game/front_page.rpy:176
-    old "Check Script (Lint)"
-    new "Vérifier le script (Lint)"
-
-    # game/front_page.rpy:177
-    old "Change Theme"
-    new "Changer de thème"
-
-    # game/front_page.rpy:178
-    old "Delete Persistent"
-    new "Supprimer persistant"
-
-    # game/front_page.rpy:186
-    old "Build Distributions"
-    new "Construire les packets"
-
-    # game/front_page.rpy:188
-    old "Generate Translations"
-    new "Générer fichiers de traduction"
-
-    # game/front_page.rpy:204
-    old "Checking script for potential problems..."
-    new "Vérifier le script vis à vis des problèmes potentiels..."
-
-    # game/front_page.rpy:219
-    old "Deleting persistent data..."
-    new "Supprimer les données persistantes..."
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "Extraire dialogue"
-
-    # game/front_page.rpy:126
-    old "[p.name!q] (template)"
-    new "[p.name!q] (gabarit)"
diff --git a/launcher/game/tl/french/gui.rpy b/launcher/game/tl/french/gui.rpy
new file mode 100644
index 0000000..57f51a5
--- /dev/null
+++ b/launcher/game/tl/french/gui.rpy
@@ -0,0 +1,411 @@
+
+translate french strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/french/interface.rpy b/launcher/game/tl/french/interface.rpy
deleted file mode 100644
index 9d95f5e..0000000
--- a/launcher/game/tl/french/interface.rpy
+++ /dev/null
@@ -1,85 +0,0 @@
-translate french strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Documentation"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Site Web de Ren'Py"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Liste des jeux Ren'Py"
-
-    # game/interface.rpy:92
-    old "About"
-    new "À propos"
-
-    # game/interface.rpy:99
-    old "update"
-    new "mise à jour"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "préférences"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "quitter"
-
-    # game/interface.rpy:149
-    old "Yes"
-    new "Oui"
-
-    # game/interface.rpy:151
-    old "No"
-    new "Non"
-
-    # game/interface.rpy:181
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Les caractères non-ASCII ne sont pas autorisés pour les noms de fichiers et répertoires."
-
-    # game/interface.rpy:183
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:248
-    old "ERROR"
-    new "ERREUR"
-
-    # game/interface.rpy:280
-    old "While [what!q], an error occured:"
-    new "Pendant que [what!q], une erreur est arrivée:"
-
-    # game/interface.rpy:281
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:298
-    old "Text input may not contain the {{ or [[ characters."
-    new "Le texte ne devrait pas contenir les caractères {{ ou [[."
-
-    # game/interface.rpy:303
-    old "File and directory names may not contain / or \\."
-    new "Les noms de fichiers et répertoires ne devrait pas contenir / ou \\."
-
-    # game/interface.rpy:309
-    old "File and directory names must consist of ASCII characters."
-    new "Les noms de fichiers et de répertoires doivent contenir uniquement des caractères ASCII."
-
-    # game/interface.rpy:330
-    old "INFORMATION"
-    new "INFORMATION"
-
-    # game/interface.rpy:373
-    old "PROCESSING"
-    new "TRAITEMENT"
-
-    # game/interface.rpy:390
-    old "QUESTION"
-    new "QUESTION"
-
-    # game/interface.rpy:451
-    old "CHOICE"
-    new "CHOIX"
diff --git a/launcher/game/tl/french/launcher.rpy b/launcher/game/tl/french/launcher.rpy
new file mode 100644
index 0000000..d5fe904
--- /dev/null
+++ b/launcher/game/tl/french/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate french strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Voir la licence"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "NOM DU FICHIER"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Entrez le nom du fichier de script à créer."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Le fichier doit avoir l'extension .rpy."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Le fichier éxiste déjà."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "Ren'Py charge automatiquement tous les fichiers de script finissant par .rpy. Pour utiliser ce ficher\n#, définissez un label et faites un «jump» vers lui depuis un autre fichier.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Un Kit de Développement Java (JDK) 32 bits est nécessaire pour construire les paquets pour Android depuis Windows. Le JDK n'est pas la même chose que le JRE, il est possible que Java soit installé sur votre machine sans le JDK.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Téléchargez et installez le JDK{/a}, puis relancer le lanceur Ren'Py."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT a été installé, mais vous devez installer le kit de développement Android pour pouvoir construire les paquets Android. Choisissez \"installer le kit de développement et créer les clés\" pour cela"
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT a été installé, mais aucune clé n'a été configurée. Créez une nouvelle clé, ou restaurez android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Le projet courant n'a pas été configuré. Choisissez \"Configurer' pour effectuer la configuration."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Choisissez \"Construire\" pour construire le projet courant, ou connecté un appareil Android et choisissez \"Construire et Installer\" pour l'installer sur l'appareil."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Tentative d'émulation d'un téléphone Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Tentative d'émulation d'une tablette Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Télécharge et installe le kit de développement Android et les paquets supportés. Optionnellement, génère les clés requises pour signer le paquet."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Configure le nom du packet, sa version et d'autres informations à propos de ce projet."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Ouvre le fichier contenant les clés Google Play dans l'éditeur.\n\nCela est nécessaire uniquement si l'application utilise une expansion APK. Référez-vous à la documentation pour plus d'informations."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Construire le paquet Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Construire le paquet Android, et l'installer sur l'appareil Android connecté à votre ordinateur."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Connects to an Android device running ADB in TCP/IP mode."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Disconnects from an Android device running ADB in TCP/IP mode."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Émulateur:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Téléphone"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablette"
+
+    # android.rpy:341
+    old "Television"
+    new "Television"
+
+    # android.rpy:353
+    old "Build:"
+    new "Construire:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Installer le kit de développement et créer les clés"
+
+    # android.rpy:365
+    old "Configure"
+    new "Configurer"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Construire le paquet"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Construire et installer"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Build, Install & Launch"
+
+    # android.rpy:388
+    old "Other:"
+    new "Other:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Remote ADB Connect"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Remote ADB Disconnect"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Remote ADB Address"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Invalid remote ADB address"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "The address must contain one exactly one ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "The host may not contain whitespace."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "The port must be a number."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Impossible de changer le thème. Peut être que options.rpy a été trop modifié."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Choisir un thème"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Thème"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Agencement des couleurs"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Continuer"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMATION"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Scan des fichiers du projet..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Aucun paquet sélectionné, il n'y a donc rien à faire."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Scan des fichiers Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Tous les paquets ont été contruits.\n\nDu fait de la présence des systèmes de permissions, il n'est pas possible de reconstruire les paquets construits sur GNU-Linux ou Mac OS sur Windows."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Archivage des fichiers..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Écriture du paquet [variant] [format]."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Création du fichier de mise à jour zsync [variant]."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Traitement du fichier {b}[complete]{/b} sur {b}[total]{/b}."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Construction des packets: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Nom du répertoire:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Nom de l'exécutable:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Actions:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Éditer options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Add from clauses to calls, once"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Rafraichir"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Construire les packets:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Options:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Construire les mises à jour"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Add from clauses to calls"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Force Recompile"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Construire"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Adding from clauses to call statements that do not have them."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Des erreurs ont été détectées lors de l'utilisation du projet. Assurez-vous qu'il n'y ait plus d'erreur avant de construire les packets."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Votre projet ne contient pas d'information pour la construction. Voulez-vous ajouter ces informations à la fin de options.rpy ?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen. Sur GNU-Linux, Editra nécessite wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Cela est sans doute dû au fait que wxPython n'est pas installé sur votre système."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Jusqu'à 22 MB de téléchargement requis."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Un éditeur éprouvé nécessitant Java."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB de réléchargement requis."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Cela est sans doute arrivé car Java n'est pas installé sur ce système."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Lance l'éditeur associé par votre systèmes aux fichiers .rpy."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Empêche Ren'Py d'ouvrir un éditeur de texte."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Une exception a été levée lors du lancement de l'édieteur de texte :\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Sélectionnez un éditeur"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Un éditeur de texte est un logiciel que vous utilisez pour éditer les fichiers de script Ren'Py. Vous pouvez choisir l'édteur que Ren'Py utilise. Si ce n'est pas déjà le cas, l'éditeur sera automatiquement téléchargé et installé."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Annuler"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Open [text] directory."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "rafraichir"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Créer un nouveau projet"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Lancer le projet"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (gabarit)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Select project [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutoriel"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Projet actif"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Ouvrir le répertoire"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Éditer le fichier"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Tous les fichiers de script"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Naviguer dans le script"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Vérifier le script (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Changer de thème"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Supprimer persistant"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Construire les packets"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Générer fichiers de traduction"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Extraire dialogue"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Vérifier le script vis à vis des problèmes potentiels..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Supprimer les données persistantes..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Recompiling all rpy files into rpyc files..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "NOM DU PROJET"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Entrez le nom de votre projet:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Le nom du projet ne doit pas être vide."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Documentation"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Site Web de Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Liste des jeux Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "mise à jour"
+
+    # interface.rpy:119
+    old "preferences"
+    new "préférences"
+
+    # interface.rpy:120
+    old "quit"
+    new "quitter"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Les caractères non-ASCII ne sont pas autorisés pour les noms de fichiers et répertoires."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ERREUR"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Pendant que [what!q], une erreur est arrivée:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Le texte ne devrait pas contenir les caractères {{ ou [[."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Les noms de fichiers et répertoires ne devrait pas contenir / ou \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Les noms de fichiers et de répertoires doivent contenir uniquement des caractères ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "TRAITEMENT"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "QUESTION"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "CHOIX"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Selects the directory where Xcode projects will be placed."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Creates an Xcode project corresponding to the current Ren'Py project."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Opens the Xcode project in Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Opens the directory containing Xcode projects."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Select Xcode Projects Directory"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Create Xcode Project"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Update Xcode Project"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Launch Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Open Xcode Projects Directory"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py has set the Xcode Projects Directory to:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navigation: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Ordre:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "alphabétique"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "par fichier"
+
+    # navigation.rpy:182
+    old "natural"
+    new "naturel"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Catégorie:"
+
+    # navigation.rpy:196
+    old "files"
+    new "fichiers"
+
+    # navigation.rpy:197
+    old "labels"
+    new "labels"
+
+    # navigation.rpy:198
+    old "defines"
+    new "définitions"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "transformations"
+
+    # navigation.rpy:200
+    old "screens"
+    new "écrans"
+
+    # navigation.rpy:201
+    old "callables"
+    new "appelables"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODOs"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Ajouter un fichier de script"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Aucun commentaire «TODO» trouvé.\n\nPour un créer un, écrivez \"# TODO\" dans le script."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "La liste des noms est vide."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "The projects directory could not be set. Giving up."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Choisissez un patron de projet"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Sélectionnez un gabarit pour votre nouveau projet. Le gabarit définit la police par défaut, ainsi que la langue de l'interface. Si votre langue n'est pas supportée, sélectionnez 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Préférence du lanceur"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Répertoire des projets:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Projects directory: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Non précisé"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Éditeur:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Text editor: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Version"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Options de navigation:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Inclure les noms privés"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Inclure les noms des bibliothèques"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Options du lanceur:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Rendu matériel"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Montrer les gabarits"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Show edit file section"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Large fonts"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Sortie console"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Ouvrir le projet lanceur"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Langue:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "After making changes to the script, press shift+R to reload your game."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Press shift+O (the letter) to access the console."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Press shift+D to access the developer menu."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Have you backed up your projects recently?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Launching the project failed."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Please ensure that your project launches normally before running this command."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py est en train de scanner le projet..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Launching"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "RÉPERTOIRE DES PROJETS"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Choisissez le répertoire des projets avec le sélecteur de fichier.\n{b}Il se peut que le sélecteur de fichier s'ouvre derière cette fenêtre.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Ce lanceur va scanner ce répertoire pour trouver des projets éxistants, créra les nouveaux projets dans ce répertoire, et placera les projets construits dans ce répertoire."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Le répertoire des projets vient d'être établit:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Generate empty strings for translations"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py est en train de générer les traductions..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py a fini de générer les fichiers de traductions pour [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py est en train d'extraire le dialogue...."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Choisissez une version."
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Le canal de mise à jour détermine la version de Ren'Py qui sera téléchargée. S'il vous plaît, sélectionnez un canal de mise à jour."
+
+    # updater.rpy:91
+    old "Release"
+    new "version courrante."
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Recommendé.{/b} La version de Ren'Py qui devrait être utilisée pour créer de nouveaux jeux."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Version de test"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Un aperçu de la prochaine version de Ren'Py qui peut être utilisée pour faire des tests et profiter de toutes nouvelles fonctionnalitées, mais par pour créer de nouveaux jeux."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Expérimental"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Version expérimentale de Ren'Py. Vous ne devriez pas choisir cette version, à moins qu'un développeur de Ren'Py ne vous y invite."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Une erreur est apparue :"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Vérification des mises à jour."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py est à jour."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "La version [u.version] est disponible. Voulez-vous l'installer ?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Préparation du téléchargement de la mise à jour."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Téléchargement de la mise à jour."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Dépaquetage de la mise à jour."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Finalisation."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "La mise à jour a bien été effectuée. Ren'Py va redémarrer."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "La mise à jour a bien été effectuée."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "La mise à jour a été annulée."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Mise à jour de Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Continuer"
+
diff --git a/launcher/game/tl/french/navigation.rpy b/launcher/game/tl/french/navigation.rpy
deleted file mode 100644
index 92c8e9d..0000000
--- a/launcher/game/tl/french/navigation.rpy
+++ /dev/null
@@ -1,73 +0,0 @@
-translate french strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Navigation: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Ordre:"
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "alphabétique"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "par fichier"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "naturel"
-
-    # game/navigation.rpy:168
-    old "refresh"
-    new "rafraichir"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Catégorie:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "fichiers"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "labels"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "définitions"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "transformations"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "écrans"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "appelables"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODOs"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Ajouter un fichier de script"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Aucun commentaire «TODO» trouvé.\n\nPour un créer un, écrivez \"# TODO\" dans le script."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "La liste des noms est vide."
-
-    # game/navigation.rpy:243
-    old "Launch Project"
-    new "Lancer le projet"
diff --git a/launcher/game/tl/french/new_project.rpy b/launcher/game/tl/french/new_project.rpy
deleted file mode 100644
index b45c192..0000000
--- a/launcher/game/tl/french/new_project.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate french strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Choisissez un patron de projet"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
-    new "Merci de sélectioner un patron à utiliser pour votre nouveau projet. Ren'Py est livré avec un patron par défaut qui créé un jeu en anglais avec des écrans standards."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "NOM DU PROJET"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Entrez le nom de votre projet:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "Le nom du projet ne doit pas être vide."
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Sélectionnez un gabarit pour votre nouveau projet. Le gabarit définit la police par défaut, ainsi que la langue de l'interface. Si votre langue n'est pas supportée, sélectionnez 'english'."
diff --git a/launcher/game/tl/french/obsolete.rpy b/launcher/game/tl/french/obsolete.rpy
new file mode 100644
index 0000000..9151257
--- /dev/null
+++ b/launcher/game/tl/french/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate french strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Mapping du Joystick"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Emplacement vide."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Précédent"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Suivant"
+
diff --git a/launcher/game/tl/french/options.rpy b/launcher/game/tl/french/options.rpy
new file mode 100644
index 0000000..9d79572
--- /dev/null
+++ b/launcher/game/tl/french/options.rpy
@@ -0,0 +1,195 @@
+
+translate french strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/french/preferences.rpy b/launcher/game/tl/french/preferences.rpy
deleted file mode 100644
index 70e1b91..0000000
--- a/launcher/game/tl/french/preferences.rpy
+++ /dev/null
@@ -1,69 +0,0 @@
-translate french strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Préférence du lanceur"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Répertoire des projets:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "Non précisé"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Éditeur:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Version"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Options de navigation:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Inclure les noms privés"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Inclure les noms des bibliothèques"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Options du lanceur:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Rendu matériel"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "Sortie console"
-
-    # game/preferences.rpy:165
-    old "Actions:"
-    new "Actions:"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "Ouvrir le projet lanceur"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "Langue:"
-
-    # game/preferences.rpy:193
-    old "Back"
-    new "Retour"
-
-    # game/preferences.rpy:146
-    old "Show templates"
-    new "Montrer les gabarits"
diff --git a/launcher/game/tl/french/project.rpy b/launcher/game/tl/french/project.rpy
deleted file mode 100644
index 2398a23..0000000
--- a/launcher/game/tl/french/project.rpy
+++ /dev/null
@@ -1,25 +0,0 @@
-translate french strings:
-
-    # game/project.rpy:196
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py est en train de scanner le projet..."
-
-    # game/project.rpy:485
-    old "PROJECTS DIRECTORY"
-    new "RÉPERTOIRE DES PROJETS"
-
-    # game/project.rpy:485
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Choisissez le répertoire des projets avec le sélecteur de fichier.\n{b}Il se peut que le sélecteur de fichier s'ouvre derière cette fenêtre.{/b}"
-
-    # game/project.rpy:485
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Ce lanceur va scanner ce répertoire pour trouver des projets éxistants, créra les nouveaux projets dans ce répertoire, et placera les projets construits dans ce répertoire."
-
-    # game/project.rpy:525
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py n'a pas pu lancer python avec le module tkinker pout choisir le répertoire des projets."
-
-    # game/project.rpy:529
-    old "Ren'Py has set the projects directory to:"
-    new "Le répertoire des projets vient d'être établit:"
diff --git a/launcher/game/tl/french/screens.rpy b/launcher/game/tl/french/screens.rpy
new file mode 100644
index 0000000..b68d9a6
--- /dev/null
+++ b/launcher/game/tl/french/screens.rpy
@@ -0,0 +1,643 @@
+
+translate french strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Retour"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Saut"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Sauvegarder"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Sauvegarde R."
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Chargement R."
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs."
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Préférences"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Menu principal"
+
+    # screens.rpy:328
+    old "About"
+    new "À propos"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Aide"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Quitter"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Retour"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Affichage"
+
+    # screens.rpy:739
+    old "Window"
+    new "Fenêtre"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Plein écran"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Après les choix"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transitions"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Vitesse du texte"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Avancement automatique"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Volume de la musique"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Volume des sons"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Volume des voix"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Oui"
+
+    # screens.rpy:1162
+    old "No"
+    new "Non"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/french/script.rpym b/launcher/game/tl/french/script.rpym
new file mode 100644
index 0000000..dead92f
--- /dev/null
+++ b/launcher/game/tl/french/script.rpym
@@ -0,0 +1,17 @@
+# Vous pouvez placer le script de votre jeu dans ce fichier.
+
+# Déclarez sous cette ligne les images, avec l'instruction 'image'
+# ex: image eileen heureuse = "eileen_heureuse.png"
+
+# Déclarez les personnages utilisés dans le jeu.
+define e = Character('Eileen', color="#c8ffc8")
+
+
+# Le jeu commence ici
+label start:
+
+    e "Vous venez de créer un nouveau jeu Ren'Py."
+
+    e "Après avoir ajouté une histoire, des images et de la musique, vous pouvez le présenter au monde entier!"
+
+    return
diff --git a/launcher/game/tl/french/style.rpy b/launcher/game/tl/french/style.rpy
index a582c75..054d043 100644
--- a/launcher/game/tl/french/style.rpy
+++ b/launcher/game/tl/french/style.rpy
@@ -1,6 +1,3 @@
 translate french python:
-    style.l_default.size = 16
-    style.l_button_text.selected_bold = True
-    style.l_navigation_text.bold = False
-
+    gui.FONT_SCALE = .9
 
diff --git a/launcher/game/tl/french/translations.rpy b/launcher/game/tl/french/translations.rpy
deleted file mode 100644
index db2d488..0000000
--- a/launcher/game/tl/french/translations.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate french strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Créer ou mettre à jour les traductions"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Entrez le nom de la langue pour laquelle vous voullez créer ou mettre à jour les traductions."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "La langue ne peut pas être une chaîne vide."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Py est en train de générer les traductions..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py a fini de générer les fichiers de traductions pour [language]."
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "Dans quel format souhaitez vous que le dialogue soit extrait ?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py est en train d'extraire le dialogue...."
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py a fini d'extraire le dialogue. Le dialogue extrait est disponible dans dialogue.[format] dans le répertoire de base."
diff --git a/launcher/game/tl/french/updater.rpy b/launcher/game/tl/french/updater.rpy
deleted file mode 100644
index fcf6878..0000000
--- a/launcher/game/tl/french/updater.rpy
+++ /dev/null
@@ -1,85 +0,0 @@
-translate french strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Choisissez une version."
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Le canal de mise à jour détermine la version de Ren'Py qui sera téléchargée. S'il vous plaît, sélectionnez un canal de mise à jour."
-
-    # game/updater.rpy:70
-    old "Release"
-    new "version courrante."
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Recommendé.{/b} La version de Ren'Py qui devrait être utilisée pour créer de nouveaux jeux."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Version de test"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Un aperçu de la prochaine version de Ren'Py qui peut être utilisée pour faire des tests et profiter de toutes nouvelles fonctionnalitées, mais par pour créer de nouveaux jeux."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Expérimental"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Version expérimentale de Ren'Py. Vous ne devriez pas choisir cette version, à moins qu'un développeur de Ren'Py ne vous y invite."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Une erreur est apparue."
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Vérifier les mises à jour."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren'Py est à jour."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "La version [u.version] est disponible. Voulez-vous l'installer ?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Préparation du téléchargement de la mise à jour."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Téléchargement de la mise à jour."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Dépaquetage de la mise à jour."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Dernier réglages."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "La mise à jour a bien été effectuée. Ren'Py va redémarrer."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "La mise à jour a bien été effectuée."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "La mise à jour a été annulée."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Mise à jour de Ren'Py"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Continuer"
diff --git a/launcher/game/tl/german/about.rpy b/launcher/game/tl/german/about.rpy
deleted file mode 100644
index 1bb8792..0000000
--- a/launcher/game/tl/german/about.rpy
+++ /dev/null
@@ -1,13 +0,0 @@
-translate german strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "Lizenz ansehen"
-
-    # game/about.rpy:27
-    old "Back"
-    new "Zurück"
diff --git a/launcher/game/tl/german/add_file.rpy b/launcher/game/tl/german/add_file.rpy
deleted file mode 100644
index d916f8a..0000000
--- a/launcher/game/tl/german/add_file.rpy
+++ /dev/null
@@ -1,21 +0,0 @@
-translate german strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "DATEINAME"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Geben Sie den Namen der Script-Datei ein, um sie zu erstellen."
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "Der Dateiname muss die Endung .rpy haben."
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "Die Datei existiert bereits."
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren’Py lädt automatisch alle Skript-Dateien, die auf .rpy enden. Um diese\n# Datei zu verwenden, setzen sie ein Label und springen sie aus einer anderen Datei dorthin.\n"
diff --git a/launcher/game/tl/german/android.rpy b/launcher/game/tl/german/android.rpy
deleted file mode 100644
index 7528daa..0000000
--- a/launcher/game/tl/german/android.rpy
+++ /dev/null
@@ -1,160 +0,0 @@
-translate german strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Um eine Android-Datei zu erstellen, laden Sie bitte RAPT ({a=http://www.renpy.org/dl/android}hier{/a}) herunter, entpacken Sie es und platzieren Sie es im Ren’Py Verzeichnis. Starten Sie dann bitte Ren’Py neu."
-
-    # game/android.rpy:13
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT wurde installiert, aber Sie müssen das Android-SDK installieren, bevor Sie Android-Dateien erstellen können. Wählen Sie „SDK Installieren“, um dies zu tun."
-
-    # game/android.rpy:14
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT wurde installiert, aber ein Key wurde nicht eingestellt. Bitte erstellen Sie einen neuen Key oder stellen Sie android.keystore wieder her."
-
-    # game/android.rpy:15
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Das aktuelle Projekt wurde nicht eingestellt. Verwenden Sie „Einstellen“, um es vor der Erstellung anzupassen."
-
-    # game/android.rpy:16
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Wählen Sie „Erstellen“, um das aktuelle Projekt zu erstellen oder schließen Sie ein Android-Gerät an und wählen Sie „Erstellen und installieren“, um es zu erstellen und auf dem Gerät zu installieren."
-
-    # game/android.rpy:18
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Emuliert ein Android-Handy.\n\nDie Berührungseingabe wird mithilfe der Maus emuliert, aber nur, wenn die Schaltfläche gedrückt wird. „Escape“ fungiert als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
-
-    # game/android.rpy:19
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Emuliert ein Android-Tablet.\n\nDie Berührungseingabe wird mithilfe der Maus emuliert, aber nur, wenn die Schaltfläche gedrückt wird. „Escape“ fungiert als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Emuliert eine OUYA-Konsole.\n\nDie Contollereingabe wird mithilfe der Pfeiltasten emuliert, „Enter“ fungiert als Auswahlschaltfläche, „Escape“ als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
-
-    # game/android.rpy:22
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Lädt das Android SDK herunter und installiert es. Generiert optional die Keys, die für die Authentifizierung der Datei benötigt werden."
-
-    # game/android.rpy:23
-    old "Configures the package name, version, and other information about this project."
-    new "Stellt Dateinamen, Version und andere Informationen über dieses Projekt ein."
-
-    # game/android.rpy:24
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Öffnet die Datei mit den Google-Play-Keys im Editor.\n\nDies ist nur nötig, wenn die Anwendung ein Expansion-APK verwendet. Lesen Sie die Dokumentation für weitere Details."
-
-    # game/android.rpy:25
-    old "Builds the Android package."
-    new "Erstellt die Android-Datei."
-
-    # game/android.rpy:26
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Erstellt die Android-Datei und installiert es auf ein Android-Gerät, das mit Ihrem Computer verbunden ist."
-
-    # game/android.rpy:142
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:361
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:381
-    old "Emulation:"
-    new "Emulation:"
-
-    # game/android.rpy:389
-    old "Phone"
-    new "Handy"
-
-    # game/android.rpy:393
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:397
-    old "Television / OUYA"
-    new "Fernseher / OUYA"
-
-    # game/android.rpy:409
-    old "Build:"
-    new "Erstellen:"
-
-    # game/android.rpy:417
-    old "Install SDK & Create Keys"
-    new "SDK installieren und Keys erstellen"
-
-    # game/android.rpy:421
-    old "Configure"
-    new "Einstellen"
-
-    # game/android.rpy:425
-    old "Build Package"
-    new "Datei erstellen"
-
-    # game/android.rpy:429
-    old "Build & Install"
-    new "Erstellen und installieren"
-
-translate german strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Um eine Android-Datei zu erstellen, laden Sie bitte RAPT herunter, entpacken Sie es und platzieren Sie es im Ren’Py Verzeichnis. Starten Sie dann bitte Ren’Py neu."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Ein 32-bit Java-Development-Kit wird benötigt, um Android-Packages auf Windows zu erstellen. Das JDK unterscheidet sich vom JRE, daher ist es möglich, dass Sie Java ohne das JDK installiert haben.\n\nBitte {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}laden Sie das JDK herunter und installieren Sie es{/a}, dann starten Sie den Ren’Py-Launcher neu."
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Emuliert eine Fernseher-Android-Konsole wie die OUYA oder Fire TV.\n\nDie Contollereingabe wird mithilfe der Pfeiltasten emuliert, „Enter“ fungiert als Auswahlschaltfläche, „Escape“ als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Verbindet mit einem Android-Gerät, das auf ADB im TCP/IP-Modus läuft."
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Trennt Verbindung von einem Android-Gerät, das auf ADB im TCP/IP-Modus läuft."
-
-    # game/android.rpy:516
-    old "Other:"
-    new "Anderes:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "Remote-ADB verbinden"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "Remote-ADB trennen"
-
-    # game/android.rpy:561
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Bevor Sie Android-Apps erstellen können, müssen Sie RAPT herunterladen, das Ren’Py-Android-Packaging-Tool. Möchten Sie RAPT jetzt herunterladen?"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "Remote-ADB-Adresse"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Bitte geben Sie die IP-Adresse und die Port-Nummer zum Verbinden ein, Beispiel: „192.168.1.143:5555“. Schauen Sie im Handbuch ihres Geräts nach, um festzustellen, ob es Remote-ADB unterstützt, und wenn ja, schauen Sie die Adresse und den Port nach."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "Ungültige Remote-ADB-Adresse"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "Die Adresse muss exakt ein „:“ beinhalten."
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "Der Host darf keine Leerzeichen enthalten."
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "Der Port muss eine Nummer sein."
-
diff --git a/launcher/game/tl/german/choose_theme.rpy b/launcher/game/tl/german/choose_theme.rpy
deleted file mode 100644
index 576c515..0000000
--- a/launcher/game/tl/german/choose_theme.rpy
+++ /dev/null
@@ -1,41 +0,0 @@
-translate german strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Konnte Theme nicht ändern. Vielleicht wurde options.rpy zu stark verändert."
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Anzeige"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Fenster"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Vollbild"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Soundlautstärke"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Theme auswählen"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "Theme"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "Farbschema"
-
-    # game/choose_theme.rpy:444
-    old "Continue"
-    new "Weiter"
diff --git a/launcher/game/tl/german/common.rpy b/launcher/game/tl/german/common.rpy
index 1ae49bd..0152382 100644
--- a/launcher/game/tl/german/common.rpy
+++ b/launcher/game/tl/german/common.rpy
@@ -1,458 +1,335 @@
-translate german strings:
+
+translate german strings:
 
-    # renpy/common/00action_file.rpy:118
-    old "%b %d, %H:%M"
-    new "%d. %b,  %H:%M"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "Schnellspeicherung erfolgreich."
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-translate german strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "Grafik [index] von [count] gesperrt."
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "vor"
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "weiter"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "slideshow"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "zurück"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-translate german strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Grafikbeschleuniger"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Automatisch auswählen"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Angle/DirectX-Darstellung erzwingen"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "OpenGL-Darstellung erzwingen"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Software-Darstellung erzwingen"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Die Änderungen werden beim nächsten Neustart des Programms übernommen."
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Zurück"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Performance Warnung"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Dieser Computer verwendet Software-Darstellung."
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Dieser Computer verwendet keine Shader."
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Dieser Computer zeigt Grafiken langsam an."
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Dieser Computer hat ein Problem, Grafiken anzuzeigen: [problem]."
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Die Grafiktreiber könnten nicht mehr aktuell sein oder nicht korrekt funktionieren. Dies kann zu langsamer oder inkorrekter Grafikanzeige führen. Das Aktualisieren von DirectX könnte dieses Problem beheben."
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Die Grafiktreiber könnten nicht mehr aktuell sein oder nicht korrekt funktionieren. Dies kann zu langsamer oder inkorrekter Grafikanzeige führen."
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "DirectX aktualisieren"
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Fortsetzen, diese Warnung wieder anzeigen"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Fortsetzen, diese Warnung nicht mehr anzeigen"
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "DirectX aktualisieren."
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "DirectX Websetup wurde gestartet. Es könnte minimiert in der Taskleiste starten. Bitte folgen Sie den Anweisungen, um DirectX zu installieren."
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Anmerkung:{/b} Microsofts DirectX Websetup-Programm installiert automatisch die Bing-Toolbar. Wenn Sie diese Toolbar nicht möchten, entfernen Sie das Häkchen bei der entsprechenden Schaltfläche."
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "Wenn die Installation abgeschlossen ist, klicken Sie bitte unten, um dieses Programm neuzustarten."
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Neustart"
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
 
-translate german strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
 
-    # renpy/common/00keymap.rpy:167
-    old "Saved screenshot as %s."
-    new "Screenshot unter %s gespeichert."
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-translate german strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
-    # renpy/common/00layout.rpy:421
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%d. %b, %H:%M"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Schnellspeicherung erfolgreich."
+
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Sind Sie sicher?"
 
-    # renpy/common/00layout.rpy:422
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Sind Sie sicher, dass Sie diese Datei löschen möchten?"
 
-    # renpy/common/00layout.rpy:423
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Sind Sie sicher, dass Sie diese Datei überschreiben möchten?"
 
-    # renpy/common/00layout.rpy:424
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Beim Laden geht ungespeicherter Fortschritt verloren.\nSind Sie sicher, dass Sie das tun möchten?"
 
-    # renpy/common/00layout.rpy:425
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Sind Sie sicher, dass Sie beenden möchten?"
 
-    # renpy/common/00layout.rpy:426
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Sind Sie sicher, dass Sie zurück zum Hauptmenü möchten?\nUngespeicherter Fortschritt geht dabei verloren."
 
-    # renpy/common/00layout.rpy:427
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Sind Sie sicher, dass Sie vorspulen möchten?"
 
-    # renpy/common/00layout.rpy:428
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Sind Sie sicher, dass Sie zur nächsten Auswahl vorspulen möchten?"
 
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Sind Sie sicher, dass Sie zum nächsten ungelesenen Dialog oder zur nächsten Auswahl vorspulen möchten?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-translate german strings:
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Screenshot unter %s gespeichert."
+
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
+
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
+
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
-    # renpy/common/00library.rpy:77
+    # 00library.rpy:179
     old "Skip Mode"
     new "Vorspulen"
 
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Schnell vorspulen"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-translate german strings:
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Clipboard voicing enabled. Press 'shift+C' to disable."
+
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Self-voicing enabled. Press 'v' to disable."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
+
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "The Ren'Py Updater is not supported on mobile devices."
+
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "An error is being simulated."
+
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Either this project does not support updating, or the update status file was deleted."
+
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "This account does not have permission to perform an update."
+
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "This account does not have permission to write the update log."
+
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "Could not verify update signature."
+
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "The update file was not downloaded."
+
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "The update file does not have the correct digest - it may have been corrupted."
 
-    # renpy/common/00updater.rpy:1255
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "While unpacking {}, unknown type {}."
+
+    # 00updater.rpy:1393
     old "Updater"
     new "Aktualisieren"
 
-    # renpy/common/00updater.rpy:1264
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Dieses Programm ist aktuell."
 
-    # renpy/common/00updater.rpy:1266
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] ist verfügbar. Möchten Sie sie installieren?"
 
-    # renpy/common/00updater.rpy:1268
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Vorbereiten, um die Aktualisierungen herunterzuladen."
 
-    # renpy/common/00updater.rpy:1270
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Aktualisierungen werden heruntergeladen."
 
-    # renpy/common/00updater.rpy:1272
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Aktualisierungen werden entpackt."
 
-    # renpy/common/00updater.rpy:1276
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "Die Aktualisierungen wurden installiert. Das Programm wird nun neustarten."
 
-    # renpy/common/00updater.rpy:1278
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "Die Aktualisierungen wurden installiert."
 
-    # renpy/common/00updater.rpy:1280
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "Die Aktualisierungen wurden abgebrochen."
 
-translate german strings:
-
-    # renpy/common/_compat/gamemenu.rpym:180
-    old "Empty Slot."
-    new "Leerer Speicherplatz."
-
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Vorige"
-
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Nächste"
-
-translate german strings:
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "Joystickbelegung"
-
-translate german strings:
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Zurückscrollen"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Versucht zu einem früheren Zeitpunkt zu gehen und ermöglicht es zu speichern oder eine andere Auswahl zu treffen."
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Ignoriert den Fehler und ermöglicht es, fortzufahren. Dies führt oft zu weiteren Fehlern."
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Startet das Spiel neu und stellt den Spielstand wieder her, wenn möglich."
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Öffnet die traceback.txt Datei in einem Texteditor."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "Syntaxanalyse gescheitert."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Fehleranalyse öffnen"
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Öffnet die errors.txt Datei in einem Texteditor."
-
-translate german strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "s"
-
-translate german strings:
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)s Konsole, ursprünglich von Shiz, C und delta.\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Drücken Sie <esc>, um die Konsole zu schließen. Geben Sie „help“ ein, um die Hilfe anzuzeigen.\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "Ren’Py Skript aktiviert."
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "Ren’Py Skript deaktiviert."
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: zeigt diese Hilfe an"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "Befehle:\n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new " <renpy script statement>: startet die Anweisung\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <python expression or statement>: startet den Ausdruck oder die Anweisung"
-
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: leert das Konsolenprotokoll"
-
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: schließt die Konsole"
-
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: lädt das Spiel aus dem Speicherplatz"
-
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: speichert das Spiel im Speicherplatz"
-
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: startet das Spiel neu und erneuert die Skripte"
-
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <expression>: beobachtet einen Python-Ausdruck"
-
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expression>: beendet das Beobachten eines Ausdrucks"
-
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: beendet das Beobachten aller Ausdrücke"
-
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: springt zum Label"
-
-translate german strings:
-
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "Autoneustart"
-
-translate german strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "Entwicklermenü"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "Spiel neustarten (Shift + R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Konsole (Shift + O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "Variablen anzeigen"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "Themetest"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "Grafikposition auswählen"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "Liste der Dateinamen"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Grafiklog anzeigen"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Grafiklog verbergen"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "Keine Variablen wurden geändert, seit das Spiel gestartet wurde."
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "Zurück zum Entwicklermenü"
-
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}Fehlende Grafiken{/b}"
-
-    # renpy/common/_developer/developer.rpym:424
-    old "Rectangle: %r"
-    new "Rechteck: %r"
-
-    # renpy/common/_developer/developer.rpym:429
-    old "Mouse position: %r"
-    new "Mausposition: %r"
-
-    # renpy/common/_developer/developer.rpym:431
-    old "Right-click or escape to quit."
-    new "Rechtsklick oder Escape, um zu beenden."
-
-    # renpy/common/_developer/developer.rpym:482
-    old "Done"
-    new "Fertig"
-
-translate german strings:
-
-    # renpy/common/_developer/inspector.rpym:43
-    old "Displayable Inspector"
-    new "Darstellungen prüfen"
-
-    # renpy/common/_developer/inspector.rpym:49
-    old "Nothing to inspect."
-    new "Nichts zum Prüfen verfügbar"
-
-    # renpy/common/_developer/inspector.rpym:58
-    old "Size"
-    new "Größe"
-
-    # renpy/common/_developer/inspector.rpym:63
-    old "Style"
-    new "Stil"
-
-    # renpy/common/_developer/inspector.rpym:123
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Prüft Stile von [displayable_name!q]"
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Grafik [index] von [count] gesperrt."
 
-    # renpy/common/_developer/inspector.rpym:135
-    old "displayable:"
-    new "Darstellungen:"
+    # 00gallery.rpy:583
+    old "prev"
+    new "vor"
 
-    # renpy/common/_developer/inspector.rpym:142
-    old "        (no properties affect the displayable)"
-    new "        (keine Eigenschaften beeinflussen diese Darstellung)"
+    # 00gallery.rpy:584
+    old "next"
+    new "weiter"
 
-    # renpy/common/_developer/inspector.rpym:144
-    old "        (default properties omitted)"
-    new "        (Standardeigenschaften entfallen)"
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "slideshow"
 
-    # renpy/common/_developer/inspector.rpym:174
-    old "<repr() failed>"
-    new "<repr() gescheitert>"
+    # 00gallery.rpy:586
+    old "return"
+    new "zurück"
 
diff --git a/launcher/game/tl/german/developer.rpy b/launcher/game/tl/german/developer.rpy
new file mode 100644
index 0000000..d340de0
--- /dev/null
+++ b/launcher/game/tl/german/developer.rpy
@@ -0,0 +1,179 @@
+
+translate german strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Entwicklermenü"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Spiel neustarten (Shift + R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Konsole (Shift + O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Variablen anzeigen"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Themetest"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Grafikposition auswählen"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Liste der Dateinamen"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Grafiklog anzeigen"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Grafiklog verbergen"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Nichts zum Prüfen verfügbar"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Zurück zum Entwicklermenü"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rechteck: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Mausposition: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Rechtsklick oder Escape, um zu beenden."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectangle copied to clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Position copied to clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Darstellungen prüfen"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Größe"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Stil"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Location"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Prüft Stile von [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "Darstellungen:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (keine Eigenschaften beeinflussen diese Darstellung)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (Standardeigenschaften entfallen)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() gescheitert>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Drücken Sie <esc>, um die Konsole zu schließen. Geben Sie „help“ ein, um die Hilfe anzuzeigen.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren’Py Skript aktiviert."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren’Py Skript deaktiviert."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: zeigt diese Hilfe an"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "Befehle:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: startet die Anweisung\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: startet den Ausdruck oder die Anweisung"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: leert das Konsolenprotokoll"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: schließt die Konsole"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: lädt das Spiel aus dem Speicherplatz"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: speichert das Spiel im Speicherplatz"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: startet das Spiel neu und erneuert die Skripte"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: beobachtet einen Python-Ausdruck"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: beendet das Beobachten eines Ausdrucks"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: beendet das Beobachten aller Ausdrücke"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: springt zum Label"
+
diff --git a/launcher/game/tl/german/distribute.rpy b/launcher/game/tl/german/distribute.rpy
deleted file mode 100644
index ca0a708..0000000
--- a/launcher/game/tl/german/distribute.rpy
+++ /dev/null
@@ -1,42 +0,0 @@
-translate german strings:
-
-    # game/distribute.rpy:313
-    old "Nothing to do."
-    new "Nichts zu tun."
-
-    # game/distribute.rpy:317
-    old "Scanning project files..."
-    new "Projektdateien werden geprüft …"
-
-    # game/distribute.rpy:324
-    old "Scanning Ren'Py files..."
-    new "Ren’Py-Dateien werden geprüft …"
-
-    # game/distribute.rpy:474
-    old "Archiving files..."
-    new "Dateien werden archiviert …"
-
-    # game/distribute.rpy:722
-    old "Writing the [variant] [format] package."
-    new "Das [variant] [format] Package wird erstellt."
-
-    # game/distribute.rpy:735
-    old "Making the [variant] update zsync file."
-    new "Die [variant] Update-zsync-Datei wird erstellt."
-
-    # game/distribute.rpy:831
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "{b}[complete]{/b} von {b}[total]{/b} Dateien verarbeitet."
-
-    # game/distribute.rpy:892
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Alle Packages wurden erstellt.\n\nAufgrund von Zugriffsinformationen ist das Entpacken und Neupacken der Linux und Macintosh Veröffentlichungen unter Windows nicht unterstützt."
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Keine Packages wurden ausgewählt."
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Erstellen von Veröffentlichungen gescheiter:\n\nDie build.directory_name Variable darf keine Leerzeichen, Doppelpunkte oder Semikolons enthalten."
-
diff --git a/launcher/game/tl/german/distribute_gui.rpy b/launcher/game/tl/german/distribute_gui.rpy
deleted file mode 100644
index 3dedaad..0000000
--- a/launcher/game/tl/german/distribute_gui.rpy
+++ /dev/null
@@ -1,45 +0,0 @@
-translate german strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Erstellt Veröffentlichung: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Verzeichnisname:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Programmdateiname:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "Aktionen:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "options.rpy bearbeiten"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Aktualisieren"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Packages erstellen:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "Aktualisierungen erstellen"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "Erstellen"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Fehler wurden beim Starten des Projekts gefunden. Bitte stellen Sie sicher, dass das Projekt ohne Fehler läuft, bevor Sie Veröffentlichungen erstellen."
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Ihr Projekt enthält keine Erstellinformationen. Würden Sie gerne Erstellinformationen am Ende der options.rpy-Datei einfügen?"
diff --git a/launcher/game/tl/german/editor.rpy b/launcher/game/tl/german/editor.rpy
deleted file mode 100644
index 3594e6f..0000000
--- a/launcher/game/tl/german/editor.rpy
+++ /dev/null
@@ -1,56 +0,0 @@
-translate german strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Empfohlen.{/b} Ein Betaeditor mit einer leichten Benutzeroberfläche und Funktionen, die bei der Entwicklung helfen, wie eine Rechtschreibprüfung. Editra fehlt derzeit die Eingabemethode, die für Chinesisch, Japanisch und Koreanisch benötigt wird."
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Empfohlen.{/b} Ein Betaeditor mit einer leichten Benutzeroberfläche und Funktionen, die bei der Entwicklung helfen, wie eine Rechtschreibprüfung. Editra fehlt derzeit die Eingabemethode, die für Chinesisch, Japanisch und Koreanisch benötigt wird. Unter Linux benötigt Editra wxPython."
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Dies ist vermutlich passiert, weil wxPython nicht auf Ihrem System installiert ist."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Etwa 22 MB benötigt."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "1,8 MB benötigt."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Dies ist vermutlich passiert, weil Java nicht auf Ihrem System installiert ist."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Ein Fehler ist beim Starten des Texteditors aufgetreten:\n[exception!q]"
-
-    # game/editor.rpy:378
-    old "Select Editor"
-    new "Editor auswählen"
-
-    # game/editor.rpy:393
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Ein Texeditor ist ein Programm, das verwendet wird, um Ren’Py Skript-Dateien zu bearbeiten. Hier können Sie den Editor auswählen, den Ren’Py verwenden soll. Wenn dieser noch nicht installiert ist, wird er automatisch heruntergeladen und installiert."
-
-    # game/editor.rpy:415
-    old "Cancel"
-    new "Abbrechen"
-
-    old "A mature editor that requires Java."
-    new "Ein fortgeschrittener Editor, der Java benötigt."
-
-    old "System Editor"
-    new "Systemeditor"
-
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Startet den Editor, den dein Betriebssystem mit .rpy-Dateien assoziiert."
-
-    old "None"
-    new "Keinen"
-
-    old "Prevents Ren'Py from opening a text editor."
-    new "Verhindert, dass Ren’Py einen Texteditor öffnet."
diff --git a/launcher/game/tl/german/error.rpy b/launcher/game/tl/german/error.rpy
new file mode 100644
index 0000000..515e4e3
--- /dev/null
+++ b/launcher/game/tl/german/error.rpy
@@ -0,0 +1,179 @@
+
+translate german strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Grafikbeschleuniger"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Automatisch auswählen"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Angle/DirectX Renderer erzwingen"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "OpenGL Renderer erzwingen"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Software Renderer erzwingen"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Die Änderungen werden beim nächsten Neustart des Programms übernommen."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Performance Warnung"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Dieser Computer verwendet Software Rendering."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Dieser Computer verwendet keine Shaders."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Dieser Computer zeigt Grafiken langsam an."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Dieser Computer hat ein Problem, Grafiken anzuzeigen: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Die Grafiktreiber könnten nicht mehr aktuell sein oder nicht korrekt funktionieren. Dies kann zu langsamer oder inkorrekter Grafikanzeige führen. Das Aktualisieren von DirectX könnte dieses Problem beheben."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Die Grafiktreiber könnten nicht mehr aktuell sein oder nicht korrekt funktionieren. Dies kann zu langsamer oder inkorrekter Grafikanzeige führen."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "DirectX aktualisieren"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Fortsetzen, diese Warnung wieder anzeigen"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Fortsetzen, diese Warnung nicht mehr anzeigen"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "DirectX aktualisieren."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX Websetup wurde gestartet. Es könnte minimiert in der Taskleiste starten. Bitte folgen Sie den Anweisungen, um DirectX zu installieren."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Anmerkung:{/b} Microsofts DirectX Websetup-Programm installiert automatisch die Bing-Toolbar. Wenn Sie diese Toolbar nicht möchten, entfernen Sie das Häkchen bei der entsprechenden Schaltfläche."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Wenn die Installation abgeschlossen ist, klicken Sie bitte unten, um dieses Programm neuzustarten."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Neustart"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Traceback öffnen"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Öffnet die traceback.txt Datei in einem Texteditor."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Ein Fehler ist aufgetreten."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Zurückscrollen"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Versucht zu einem früheren Zeitpunkt zu gehen und ermöglicht es zu speichern oder eine andere Auswahl zu treffen."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Ignorieren"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Ignoriert den Fehler und ermöglicht es, fortzusetzen. Dies führt oft zu weiteren Fehlern."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Neustarten"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Startet das Spiel neu, rettet und stellt den Spielstand wieder her, wenn möglich."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Beendet das Spiel."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Syntaxanalyse gescheitert."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Parse Errors öffnen"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Öffnet die errors.txt Datei in einem Texteditor."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/german/front_page.rpy b/launcher/game/tl/german/front_page.rpy
deleted file mode 100644
index cfaf708..0000000
--- a/launcher/game/tl/german/front_page.rpy
+++ /dev/null
@@ -1,26 +0,0 @@
-translate german strings:
-
-    # game/front_page.rpy:90
-    old "Launch Project"
-    new "Projekt starten"
-
-    # game/front_page.rpy:204
-    old "Checking script for potential problems..."
-    new "Überprüft Script auf potentielle Probleme …"
-
-    # game/front_page.rpy:219
-    old "Deleting persistent data..."
-    new "Löscht Persistent-Dateien …"
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "Dialoge extrahieren"
-
-    # game/front_page.rpy:144
-    old "[p.name!q] (template)"
-    new "[p.name!q] (Vorlage)"
-
diff --git a/launcher/game/tl/german/gui.rpy b/launcher/game/tl/german/gui.rpy
new file mode 100644
index 0000000..d12e984
--- /dev/null
+++ b/launcher/game/tl/german/gui.rpy
@@ -0,0 +1,411 @@
+
+translate german strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/german/interface.rpy b/launcher/game/tl/german/interface.rpy
deleted file mode 100644
index 5855ac5..0000000
--- a/launcher/game/tl/german/interface.rpy
+++ /dev/null
@@ -1,85 +0,0 @@
-translate german strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Dokumentation"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Ren’Py Webseite"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Ren’Py Spieleliste"
-
-    # game/interface.rpy:92
-    old "About"
-    new "Über"
-
-    # game/interface.rpy:99
-    old "update"
-    new "Aktualisieren"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "Einstellungen"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "Beenden"
-
-    # game/interface.rpy:149
-    old "Yes"
-    new "Ja"
-
-    # game/interface.rpy:151
-    old "No"
-    new "Nein"
-
-    # game/interface.rpy:181
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Aufgrund von Formateinschränkungen sind nicht-ASCII Datei- und Verzeichnisnamen nicht erlaubt."
-
-    # game/interface.rpy:183
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:248
-    old "ERROR"
-    new "FEHLER"
-
-    # game/interface.rpy:280
-    old "While [what!q], an error occured:"
-    new "Während [what!q] ist ein Fehler aufgetreten:"
-
-    # game/interface.rpy:281
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:298
-    old "Text input may not contain the {{ or [[ characters."
-    new "Die Texteingabe darf keine {{ oder [[ enthalten."
-
-    # game/interface.rpy:303
-    old "File and directory names may not contain / or \\."
-    new "Datei- und Verzeichnisnamen dürfen keine / oder \\ enthalten."
-
-    # game/interface.rpy:309
-    old "File and directory names must consist of ASCII characters."
-    new "Datei- und Verzeichnisnamen müssen aus ASCII-Buchstaben bestehen."
-
-    # game/interface.rpy:330
-    old "INFORMATION"
-    new "INFORMATION"
-
-    # game/interface.rpy:373
-    old "PROCESSING"
-    new "VERARBEITUNG"
-
-    # game/interface.rpy:390
-    old "QUESTION"
-    new "FRAGE"
-
-    # game/interface.rpy:451
-    old "CHOICE"
-    new "AUSWAHL"
diff --git a/launcher/game/tl/german/launcher.rpy b/launcher/game/tl/german/launcher.rpy
new file mode 100644
index 0000000..cdaa102
--- /dev/null
+++ b/launcher/game/tl/german/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate german strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Lizenz ansehen"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "DATEINAME"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Geben Sie den Namen der Script-Datei ein, um sie zu erstellen."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Der Dateiname muss die Endung .rpy haben."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Die Datei existiert bereits."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren’Py lädt automatisch alle Skript-Dateien, die auf .rpy enden. Um diese\n# Datei zu verwenden, setzen sie ein Label und springen sie aus einer anderen Datei dorthin.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Um eine Android-Datei zu erstellen, laden Sie bitte RAPT herunter, entpacken Sie es und platzieren Sie es im Ren’Py Verzeichnis. Starten Sie dann bitte Ren’Py neu."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Ein 32-bit Java-Development-Kit wird benötigt, um Android-Packages auf Windows zu erstellen. Das JDK unterscheidet sich vom JRE, daher ist es möglich, dass Sie Java ohne das JDK installiert haben.\n\nBitte {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}laden Sie das JDK herunter und installieren Sie es{/a}, dann starten Sie den Ren’Py-Launcher neu."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT wurde installiert, aber Sie müssen das Android-SDK installieren, bevor Sie Android-Dateien erstellen können. Wählen Sie „SDK Installieren“, um dies zu tun."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT wurde installiert, aber ein Key wurde nicht eingestellt. Bitte erstellen Sie einen neuen Key oder stellen Sie android.keystore wieder her."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Das aktuelle Projekt wurde nicht eingestellt. Verwenden Sie „Einstellen“, um es vor der Erstellung anzupassen."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Wählen Sie „Erstellen“, um das aktuelle Projekt zu erstellen oder schließen Sie ein Android-Gerät an und wählen Sie „Erstellen und installieren“, um es zu erstellen und auf dem Gerät zu installieren."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Emuliert ein Android-Handy.\n\nDie Berührungseingabe wird mithilfe der Maus emuliert, aber nur, wenn die Schaltfläche gedrückt wird. „Escape“ fungiert als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Emuliert ein Android-Tablet.\n\nDie Berührungseingabe wird mithilfe der Maus emuliert, aber nur, wenn die Schaltfläche gedrückt wird. „Escape“ fungiert als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Emuliert eine Fernseher-Android-Konsole wie die OUYA oder Fire TV.\n\nDie Contollereingabe wird mithilfe der Pfeiltasten emuliert, „Enter“ fungiert als Auswahlschaltfläche, „Escape“ als Menüschaltfläche und „Bild rauf“ als „Zurück-Schaltfläche“."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Lädt das Android SDK herunter und installiert es. Generiert optional die Keys, die für die Authentifizierung der Datei benötigt werden."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Stellt Dateinamen, Version und andere Informationen über dieses Projekt ein."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Öffnet die Datei mit den Google-Play-Keys im Editor.\n\nDies ist nur nötig, wenn die Anwendung ein Expansion-APK verwendet. Lesen Sie die Dokumentation für weitere Details."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Erstellt die Android-Datei."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Erstellt die Android-Datei und installiert es auf ein Android-Gerät, das mit Ihrem Computer verbunden ist."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Verbindet mit einem Android-Gerät, das auf ADB im TCP/IP-Modus läuft."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Trennt Verbindung von einem Android-Gerät, das auf ADB im TCP/IP-Modus läuft."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Emulation:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Handy"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Television"
+
+    # android.rpy:353
+    old "Build:"
+    new "Erstellen:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "SDK installieren und Keys erstellen"
+
+    # android.rpy:365
+    old "Configure"
+    new "Einstellen"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Datei erstellen"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Erstellen und installieren"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Build, Install & Launch"
+
+    # android.rpy:388
+    old "Other:"
+    new "Anderes:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Remote-ADB verbinden"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Remote-ADB trennen"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Bevor Sie Android-Apps erstellen können, müssen Sie RAPT herunterladen, das Ren’Py-Android-Packaging-Tool. Möchten Sie RAPT jetzt herunterladen?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Remote-ADB-Adresse"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Bitte geben Sie die IP-Adresse und die Port-Nummer zum Verbinden ein, Beispiel: „192.168.1.143:5555“. Schauen Sie im Handbuch ihres Geräts nach, um festzustellen, ob es Remote-ADB unterstützt, und wenn ja, schauen Sie die Adresse und den Port nach."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Ungültige Remote-ADB-Adresse"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Die Adresse muss exakt ein „:“ beinhalten."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "Der Host darf keine Leerzeichen enthalten."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Der Port muss eine Nummer sein."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Konnte Theme nicht ändern. Vielleicht wurde options.rpy zu stark verändert."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Theme auswählen"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Theme"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Farbschema"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Weiter"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMATION"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Projektdateien werden geprüft …"
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Erstellen von Veröffentlichungen gescheiter:\n\nDie build.directory_name Variable darf keine Leerzeichen, Doppelpunkte oder Semikolons enthalten."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Keine Packages wurden ausgewählt."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Ren’Py-Dateien werden geprüft …"
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Alle Packages wurden erstellt.\n\nAufgrund von Zugriffsinformationen ist das Entpacken und Neupacken der Linux und Macintosh Veröffentlichungen unter Windows nicht unterstützt."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Dateien werden archiviert …"
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Das [variant] [format] Package wird erstellt."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Die [variant] Update-zsync-Datei wird erstellt."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "{b}[complete]{/b} von {b}[total]{/b} Dateien verarbeitet."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Erstellt Veröffentlichung: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Verzeichnisname:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Programmdateiname:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Aktionen:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "options.rpy bearbeiten"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Add from clauses to calls, once"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Aktualisieren"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Packages erstellen:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Options:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Aktualisierungen erstellen"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Add from clauses to calls"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Force Recompile"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Erstellen"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Adding from clauses to call statements that do not have them."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Fehler wurden beim Starten des Projekts gefunden. Bitte stellen Sie sicher, dass das Projekt ohne Fehler läuft, bevor Sie Veröffentlichungen erstellen."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Ihr Projekt enthält keine Erstellinformationen. Würden Sie gerne Erstellinformationen am Ende der options.rpy-Datei einfügen?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Empfohlen.{/b} Ein Betaeditor mit einer leichten Benutzeroberfläche und Funktionen, die bei der Entwicklung helfen, wie eine Rechtschreibprüfung. Editra fehlt derzeit die Eingabemethode, die für Chinesisch, Japanisch und Koreanisch benötigt wird."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Empfohlen.{/b} Ein Betaeditor mit einer leichten Benutzeroberfläche und Funktionen, die bei der Entwicklung helfen, wie eine Rechtschreibprüfung. Editra fehlt derzeit die Eingabemethode, die für Chinesisch, Japanisch und Koreanisch benötigt wird. Unter Linux benötigt Editra wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Dies ist vermutlich passiert, weil wxPython nicht auf Ihrem System installiert ist."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Etwa 22 MB benötigt."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Ein fortgeschrittener Editor, der Java benötigt."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1,8 MB benötigt."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Dies ist vermutlich passiert, weil Java nicht auf Ihrem System installiert ist."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Startet den Editor, den dein Betriebssystem mit .rpy-Dateien assoziiert."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Verhindert, dass Ren’Py einen Texteditor öffnet."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Ein Fehler ist beim Starten des Texteditors aufgetreten:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Editor auswählen"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Ein Texeditor ist ein Programm, das verwendet wird, um Ren’Py Skript-Dateien zu bearbeiten. Hier können Sie den Editor auswählen, den Ren’Py verwenden soll. Wenn dieser noch nicht installiert ist, wird er automatisch heruntergeladen und installiert."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Abbrechen"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Open [text] directory."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "Aktualisieren"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Neues Projekt erstellen"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Projekt starten"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (Vorlage)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Select project [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Aktives Projekt"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Verzeichnis öffnen"
+
+    # front_page.rpy:195
+    old "game"
+    new "Spielverzeichnis"
+
+    # front_page.rpy:196
+    old "base"
+    new "Hauptverzeichnis"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Dateien bearbeiten"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Alle Dateien"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Skript navigieren"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Skript überprüfen (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Theme ändern"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Persistent-Dateien löschen"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Veröffentlichungen erstellen"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Übersetzungen generieren"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Dialoge extrahieren"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Überprüft Script auf potentielle Probleme …"
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Löscht Persistent-Dateien …"
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Recompiling all rpy files into rpyc files..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "PROJEKT NAME"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Bitte geben Sie den Namen Ihres Projekts ein:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Der Projektname kann nicht leer sein."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] existiert bereits. Bitte wählen Sie einen anderen Projektnamen."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] existiert bereits. Bitte wählen Sie einen anderen Projektnamen."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Dokumentation"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren’Py Webseite"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Ren’Py Spieleliste"
+
+    # interface.rpy:117
+    old "update"
+    new "Aktualisieren"
+
+    # interface.rpy:119
+    old "preferences"
+    new "Einstellungen"
+
+    # interface.rpy:120
+    old "quit"
+    new "Beenden"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Aufgrund von Formateinschränkungen sind nicht-ASCII Datei- und Verzeichnisnamen nicht erlaubt."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "FEHLER"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Während [what!q] ist ein Fehler aufgetreten:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Die Texteingabe darf keine {{ oder [[ enthalten."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Datei- und Verzeichnisnamen dürfen keine / oder \\ enthalten."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Datei- und Verzeichnisnamen müssen aus ASCII-Buchstaben bestehen."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "VERARBEITUNG"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "FRAGE"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "AUSWAHL"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Selects the directory where Xcode projects will be placed."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Creates an Xcode project corresponding to the current Ren'Py project."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Opens the Xcode project in Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Opens the directory containing Xcode projects."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Select Xcode Projects Directory"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Create Xcode Project"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Update Xcode Project"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Launch Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Open Xcode Projects Directory"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py has set the Xcode Projects Directory to:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navigieren: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Reihenfolge:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "Alphabetisch"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "Nach Datei"
+
+    # navigation.rpy:182
+    old "natural"
+    new "Natürlich"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Kategorie"
+
+    # navigation.rpy:196
+    old "files"
+    new "Dateien"
+
+    # navigation.rpy:197
+    old "labels"
+    new "Labels"
+
+    # navigation.rpy:198
+    old "defines"
+    new "Defines"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "Transforms"
+
+    # navigation.rpy:200
+    old "screens"
+    new "Bildschirme"
+
+    # navigation.rpy:201
+    old "callables"
+    new "Callables"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODOs"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Script-Datei hinzufügen"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Keine TODO-Kommentare gefunden.\n\nUm einen zu erstellen, bauen Sie „# TODO“ in Ihr Script ein."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Die Namensliste ist leer."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Das Projektverzeichnis konnte nicht festgelegt werden."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Projektvorlage auswählen"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Bitte wählen Sie eine Vorlage für Ihr neues Projekt. Die Vorlage legt die Standard-Schriftart fest und die Sprache der Benutzeroberfläche. Wenn Ihre Sprache nicht verfügbar ist, wählen Sie bitte 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Launcher Einstellungen"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Projektverzeichnis:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Projects directory: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Nicht eingestellt"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Texteditor:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Text editor: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Aktualisierungskanal:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Navigationsoptionen:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Vertrauliche Namen einschließen"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Programmnamen einschließen"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Launcher Optionen:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Hardware Wiedergabe"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Vorlagen anzeigen"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Show edit file section"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Large fonts"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Konsolenausgabe"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Launcherprojekt öffnen"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Sprache:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Nachdem Sie das Skript verändert haben, drücken Sie Shift + R, um Ihr Spiel neuzustarten."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Drücken Sie Shift + O, um die Konsole aufzurufen."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Drücken Sie Shift + D, um das Entwicklermenü aufzurufen."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Have you backed up your projects recently?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Starten des Projekts gescheitert."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Bitte stellen Sie sicher, dass Ihr Projekt normal startet, bevor Sie diesen Befehl ausführen."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren’Py scannt das Projekt …"
+
+    # project.rpy:568
+    old "Launching"
+    new "Startet"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "PROJEKTVERZEICHNIS"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Bitte wählen Sie das Projektverzeichnis mit dem Verzeichnisauswähler.\n{b}Der Verzeichnisauswähler könnte hinter diesem Fenster geöffnet sein.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Dieser Launcher scannt nach Projekten in diesem Verzeichnis, erstellt neue Projekte und platziert erstellte Projekte dort."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren’Py hat das Projektverzeichnis verschoben in:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Generate empty strings for translations"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren’Py erstellt Übersetzungen …"
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren’Py hat die Übersetzungen für [language] erstellt."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren’Py extrahiert Dialoge …"
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Aktualisierungskanal auswählen"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Der Aktualisierungskanal kontrolliert die Version, die Ren’py herunterlädt. Bitte wählen Sie einen Aktualisierungskanal:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Veröffentlichungen"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Empfohlen.{/b} Die Version von Ren’Py, die für alle neuen Spielveröffentlichungen verwendet werden sollte."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Vorveröffentlichungen"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Eine Vorschau auf die nächste Version von Ren’Py, die zu Testzwecken und mit neuen Funktionen verwendet werden kann, jedoch nicht für Veröffentlichung von Spielen geeignet ist."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Experimentell"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Experimentelle Versionen von Ren’Py. Sie sollten diesen Kanal nur auswählen, wenn Sie von einem Ren’Py-Entwickler dazu aufgefordert werden."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Die allerneuste Ren’Py Version. Diese enthält die neusten Funktionen, könnte aber auch überhaupt nicht funktionieren."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Ein Fehler ist aufgetreten:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Auf Aktualisierungen prüfen."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren’Py ist aktuell"
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] ist nun verfügbar. Möchten Sie sie installieren?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Vorbereiten, um die Aktualisierungen herunterzuladen."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Aktualisierungen werden heruntergeladen."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Aktualisierungen werden entpackt."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Abschließen."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Die Aktualisierungen wurden installiert. Ren’Py startet neu."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Die Aktualisierungen wurden installiert."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Die Aktualisierungen wurde abgebrochen."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ren’Py aktualisieren"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Fortsetzen"
+
diff --git a/launcher/game/tl/german/navigation.rpy b/launcher/game/tl/german/navigation.rpy
deleted file mode 100644
index 0b82cb7..0000000
--- a/launcher/game/tl/german/navigation.rpy
+++ /dev/null
@@ -1,69 +0,0 @@
-translate german strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Navigieren: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Reihenfolge:"
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "Alphabetisch"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "Nach Datei"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "Natürlich"
-
-    # game/navigation.rpy:168
-    old "refresh"
-    new "Aktualisieren"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Kategorie"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "Dateien"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "Labels"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "Defines"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "Transforms"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "Bildschirme"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "Callables"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODOs"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Script-Datei hinzufügen"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Keine TODO-Kommentare gefunden.\n\nUm einen zu erstellen, bauen Sie „# TODO“ in Ihr Script ein."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "Die Namensliste ist leer."
diff --git a/launcher/game/tl/german/new_project.rpy b/launcher/game/tl/german/new_project.rpy
deleted file mode 100644
index 7ef0cfe..0000000
--- a/launcher/game/tl/german/new_project.rpy
+++ /dev/null
@@ -1,38 +0,0 @@
-translate german strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Projektvorlage auswählen"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
-    new "Bitte wählen Sie eine Vorlage für Ihr neues Projekt. Ren’Py hat eine Standard-Vorlage, die ein englischsprachiges Spiel mit Standardmenüs erstellt."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "PROJEKT NAME"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Bitte geben Sie den Namen Ihres Projekts ein:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "Der Projektname kann nicht leer sein."
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] existiert bereits. Bitte wählen Sie einen anderen Projektnamen."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] existiert bereits. Bitte wählen Sie einen anderen Projektnamen."
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Bitte wählen Sie eine Vorlage für Ihr neues Projekt. Die Vorlage legt die Standard-Schriftart fest und die Sprache der Benutzeroberfläche. Wenn Ihre Sprache nicht verfügbar ist, wählen Sie bitte 'english'."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Das Projektverzeichnis konnte nicht festgelegt werden."
-
diff --git a/launcher/game/tl/german/obsolete.rpy b/launcher/game/tl/german/obsolete.rpy
new file mode 100644
index 0000000..3c8de03
--- /dev/null
+++ b/launcher/game/tl/german/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate german strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Joystickbelegung"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Leerer Speicherplatz."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "s"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Vorige"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Nächste"
+
diff --git a/launcher/game/tl/german/options.rpy b/launcher/game/tl/german/options.rpy
new file mode 100644
index 0000000..9862092
--- /dev/null
+++ b/launcher/game/tl/german/options.rpy
@@ -0,0 +1,195 @@
+
+translate german strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/german/preferences.rpy b/launcher/game/tl/german/preferences.rpy
deleted file mode 100644
index 8d9d9ba..0000000
--- a/launcher/game/tl/german/preferences.rpy
+++ /dev/null
@@ -1,57 +0,0 @@
-translate german strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Launcher Einstellungen"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Projektverzeichnis:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "Nicht eingestellt"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Texteditor:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Aktualisierungskanal:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Navigationsoptionen:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Vertrauliche Namen einschließen"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Programmnamen einschließen"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Launcher Optionen:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Hardware Wiedergabe"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "Konsolenausgabe"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "Launcherprojekt öffnen"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "Sprache:"
diff --git a/launcher/game/tl/german/project.rpy b/launcher/game/tl/german/project.rpy
deleted file mode 100644
index 934d0fb..0000000
--- a/launcher/game/tl/german/project.rpy
+++ /dev/null
@@ -1,54 +0,0 @@
-translate german strings:
-
-    # game/project.rpy:199
-    old "Ren'Py is scanning the project..."
-    new "Ren’Py scannt das Projekt …"
-
-    # game/project.rpy:488
-    old "PROJECTS DIRECTORY"
-    new "PROJEKTVERZEICHNIS"
-
-    # game/project.rpy:488
-    old "Please choose the projects directory."
-    new "Bitte wählen Sie das Projektverzeichnis."
-
-    # game/project.rpy:488
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Dieser Launcher scannt nach Projekten in diesem Verzeichnis, erstellt neue Projekte und platziert erstellte Projekte dort."
-
-    # game/project.rpy:536
-    old "Ren'Py was unable to run zenity to choose the projects directory."
-    new "Ren’Py konnte Zenity nicht starten, um das Projektverzeichnis auszuwählen."
-
-    # game/project.rpy:540
-    old "Ren'Py has set the projects directory to:"
-    new "Ren’Py hat das Projektverzeichnis verschoben in:"
-
-    # game/project.rpy:485
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Bitte wählen Sie das Projektverzeichnis mit dem Verzeichnisauswähler.\n{b}Der Verzeichnisauswähler könnte hinter diesem Fenster geöffnet sein.{/b}"
-
-    # game/project.rpy:525
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren’Py konnte Python mit tkinter zur Projektsverzeichniswahl nicht starten."
-
-    # game/project.rpy:48
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Nachdem Sie das Skript verändert haben, drücken Sie Shift + R, um Ihr Spiel neuzustarten."
-
-    # game/project.rpy:50
-    old "Press shift+D to access the developer menu."
-    new "Drücken Sie Shift + D, um das Entwicklermenü aufzurufen."
-
-    # game/project.rpy:219
-    old "Launching the project failed."
-    new "Starten des Projekts gescheitert."
-
-    # game/project.rpy:219
-    old "Please ensure that your project launches normally before running this command."
-    new "Bitte stellen Sie sicher, dass Ihr Projekt normal startet, bevor Sie diesen Befehl ausführen."
-
-    # game/project.rpy:585
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren’Py konnte Python mit tkinter zur Projektsverzeichniswahl nicht starten. Bitte installieren Sie python-tk oder tkinter."
-
diff --git a/launcher/game/tl/german/screens.rpy b/launcher/game/tl/german/screens.rpy
new file mode 100644
index 0000000..128d33c
--- /dev/null
+++ b/launcher/game/tl/german/screens.rpy
@@ -0,0 +1,643 @@
+
+translate german strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Zurück"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Spulen"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Speichern"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "S.Speichern"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "S. Laden"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Optionen"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Einstellungen"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Hauptmenü"
+
+    # screens.rpy:328
+    old "About"
+    new "Über"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Hilfe"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Beenden"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Zurück"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Anzeige"
+
+    # screens.rpy:739
+    old "Window"
+    new "Fenster"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Vollbild"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Nach Auswahl"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Übergänge"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Textgeschwindigkeit"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Automatischer Vorlauf"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Musiklautstärke"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Soundlautstärke"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Sprachlautstärke"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Ja"
+
+    # screens.rpy:1162
+    old "No"
+    new "Nein"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/german/script.rpym b/launcher/game/tl/german/script.rpym
new file mode 100644
index 0000000..3b78353
--- /dev/null
+++ b/launcher/game/tl/german/script.rpym
@@ -0,0 +1,17 @@
+# Sie können das Skript Ihres Spiels in dieser Datei platzieren.
+
+# Bestimmen Sie Grafiken unterhalb dieser Zeile, indem Sie die "Image-Statements" verwenden.
+# z. B. image eileen happy = "eileen_happy.png"
+
+# Bestimmen Sie Charaktere, die in diesem Spiel verwendet werden.
+define e = Character('Eileen', color="#c8ffc8")
+
+
+# Hier beginnt das Spiel.
+label start:
+
+    e "Du hast ein neues Ren'Py Spiel erstellt."
+
+    e "Sobald du eine Geschichte, Bilder und Musik hinzufügst, kannst du es für alle veröffentlichen!"
+
+    return
diff --git a/launcher/game/tl/german/strings.rpy b/launcher/game/tl/german/strings.rpy
deleted file mode 100644
index 7aa0c3a..0000000
--- a/launcher/game/tl/german/strings.rpy
+++ /dev/null
@@ -1,195 +0,0 @@
-translate german strings:
-
-    old "PROJECTS:"
-    new "PROJEKTE:"
-
-    old "[p.name!q]"
-    new "[p.name!q]"
-
-    old "An exception has occurred."
-    new "Ein Fehler ist aufgetreten."
-
-    old "Ignore"
-    new "Ignorieren"
-
-translate german strings:
-
-    old "Tutorial"
-    new "Tutorial"
-
-    old "The Question"
-    new "The Question"
-
-    old "Reload"
-    new "Neustarten"
-
-    old "Open Traceback"
-    new "Traceback öffnen"
-
-translate german strings:
-
-    old "+ Create New Project"
-    new "+ Neues Projekt erstellen"
-
-    old "Active Project"
-    new "Aktives Projekt"
-
-    old "Quit"
-    new "Beenden"
-
-    old ""
-    new ""
-
-translate german strings:
-
-    old "Open Directory"
-    new "Verzeichnis öffnen"
-
-    old "game"
-    new "Spielverzeichnis"
-
-    old "Quits the game."
-    new "Beendet das Spiel."
-
-translate german strings:
-
-    old "base"
-    new "Hauptverzeichnis"
-
-    old "Edit File"
-    new "Dateien bearbeiten"
-
-translate german strings:
-
-    old "script.rpy"
-    new "script.rpy"
-
-    old "options.rpy"
-    new "options.rpy"
-
-translate german strings:
-
-    old "screens.rpy"
-    new "screens.rpy"
-
-    old "All script files"
-    new "Alle Dateien"
-
-translate german strings:
-
-    old "Navigate Script"
-    new "Skript navigieren"
-
-    old "Check Script (Lint)"
-    new "Skript überprüfen (Lint)"
-
-translate german strings:
-
-    old "Change Theme"
-    new "Theme ändern"
-
-    old "Delete Persistent"
-    new "Persistent-Dateien löschen"
-
-translate german strings:
-
-    old "Build Distributions"
-    new "Veröffentlichungen erstellen"
-
-    old "Generate Translations"
-    new "Übersetzungen generieren"
-
-translate german strings:
-
-    old "Editra"
-    new "Editra"
-
-    old "[name!q]"
-    new "[name!q]"
-
-    old " | "
-    new " | "
-
-translate german strings:
-
-    old "I'm compiling a short test program, to see if you have a working JDK on your\nsystem.\n"
-    new "Es wird ein kurzes Testprogramm erstellt, um zu testen, ob Sie ein funktionierendes JDK haben.\n"
-
-    old "I was unable to use javac to compile a test file. If you haven't installed\nthe Java Development Kit yet, please download it from:\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}http://www.oracle.com/technetwork/java/javase/downloads/index.html{/a}\n\nThe JDK is different from the JRE, so it's possible you have Java\nwithout having the JDK. Without a working JDK, I can't continue.\n"
-    new "Es konnte javac nicht verwendet werden, um eine Testdatei zu erstellen. Wenn Sie\ndas Java Development Kit noch nicht installiert haben, laden Sie es bitte herunter:\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}http://www.oracle.com/technetwork/java/javase/downloads/index.html{/a}\n\nDas JDK unterscheidet sich vom JRE, daher ist es möglich, dass Sie Java\nohne JDK haben. Ohne ein funktionierendes JDK, kann ich nicht weitermachen.\n"
-
-translate german strings:
-
-    old "[value!q]"
-    new "[value!q]"
-
-    old "[description!q]"
-    new "[description!q]"
-
-
-translate german strings:
-
-    old "Press shift+O (the letter) to access the console."
-    new "Drücken Sie Shift + O, um die Konsole aufzurufen."
-
-    old "Launching"
-    new "Startet"
-
-translate german strings:
-
-    old "Show templates"
-    new "Vorlagen anzeigen"
-
-translate german strings:
-
-    old "What is the full name of your application? This name will appear in the list of installed applications."
-    new "Wie lautet der volle Titel Ihrer Anwendung? Dieser Titel wird in der Liste von installierten Anwendungen angezeigt."
-
-    old "[ft.text!q]"
-    new "[ft.text!q]"
-
-    old "The JDK is present and working. Good!"
-    new "Das JDK ist verfügbar und funktioniert. Gut!"
-
-    old "Apache ANT has already been unpacked."
-    new "Apache-ANT wurde bereits entpackt."
-
-    old "The Android SDK has already been unpacked."
-    new "Das Android-SDK wurde bereits entpackt."
-
-    old "The required Android packages are already installed."
-    new "Die benötigten Android-Packages wurden bereits installiert."
-
-    old "You've already created an Android keystore, so I won't create a new one for you."
-    new "Sie haben bereits einen Android-Key erstellt, es wird kein neuer erstellt."
-
-    old "It looks like you're ready to start packaging games."
-    new "Es sieht aus, als wären Sie bereit, Spiele zu erstellen."
-
-
-translate german strings:
-
-    old "English"
-    new "English"
-
-    old "German"
-    new "German"
-
-    old "Japanese"
-    new "Japanese"
-
-
-translate german strings:
-
-    old "French"
-    new "French"
-
-    old "Spanish"
-    new "Spanish"
-
-    old "Russian"
-    new "Russian"
-
-    old "Arabic"
-    new "Arabic"
-
diff --git a/launcher/game/tl/german/translations.rpy b/launcher/game/tl/german/translations.rpy
deleted file mode 100644
index 9d306e3..0000000
--- a/launcher/game/tl/german/translations.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate german strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Erstellt oder aktualisiert Übersetzungen"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Bitte geben Sie den Namen der Sprache ein, deren Übersetzung Sie erstellen oder aktualisieren möchten."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "Der Name der Sprache darf nicht leer sein."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren’Py erstellt Übersetzungen …"
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren’Py hat die Übersetzungen für [language] erstellt."
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "In welchem Format möchten Sie die extrahierten Dialoge?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren’Py extrahiert Dialoge …"
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren’Py hat die Dialoge fertig extrahiert. Die extrahierten Dialoge können im Hauptverzeichnis unter dialogue.[format] gefunden werden."
diff --git a/launcher/game/tl/german/updater.rpy b/launcher/game/tl/german/updater.rpy
deleted file mode 100644
index a3f5ccc..0000000
--- a/launcher/game/tl/german/updater.rpy
+++ /dev/null
@@ -1,94 +0,0 @@
-translate german strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Aktualisierungskanal auswählen"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Der Aktualisierungskanal kontrolliert die Version, die Ren’py herunterlädt. Bitte wählen Sie einen Aktualisierungskanal:"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Veröffentlichungen"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Empfohlen.{/b} Die Version von Ren’Py, die für alle neuen Spielveröffentlichungen verwendet werden sollte."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Vorveröffentlichungen"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Eine Vorschau auf die nächste Version von Ren’Py, die zu Testzwecken und mit neuen Funktionen verwendet werden kann, jedoch nicht für Veröffentlichung von Spielen geeignet ist."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Experimentell"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Experimentelle Versionen von Ren’Py. Sie sollten diesen Kanal nur auswählen, wenn Sie von einem Ren’Py-Entwickler dazu aufgefordert werden."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Ein Fehler ist aufgetreten:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Überprüft auf Aktualisierungen."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren’Py ist aktuell"
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] ist nun verfügbar. Möchten Sie sie installieren?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Vorbereiten, um die Aktualisierungen herunterzuladen."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Aktualisierungen werden heruntergeladen."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Aktualisierungen werden entpackt."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Abschließen."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "Die Aktualisierungen wurden installiert. Ren’Py startet neu."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "Die Aktualisierungen wurden installiert."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "Die Aktualisierungen wurde abgebrochen."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Ren’Py aktualisieren"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Fortsetzen"
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Die allerneuste Ren’Py Version. Diese enthält die neusten Funktionen, könnte aber auch überhaupt nicht funktionieren."
-
diff --git a/launcher/game/tl/greek/about.rpy b/launcher/game/tl/greek/about.rpy
deleted file mode 100644
index 4f8c937..0000000
--- a/launcher/game/tl/greek/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate greek strings:
-
-    # game/about.rpy:39
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:43
-    old "View license"
-    new "Δείτε την άδεια χρήσης"
-
-    # game/about.rpy:45
-    old "Back"
-    new "Πίσω"
-
diff --git a/launcher/game/tl/greek/add_file.rpy b/launcher/game/tl/greek/add_file.rpy
deleted file mode 100644
index a32fad4..0000000
--- a/launcher/game/tl/greek/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate greek strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "ΟΝΟΜΑ_ΑΡΧΕΙΟΥ"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "Δώστε το όνομα του προς δημιουργία αρχείου σεναρίου-κώδικα"
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "Το όνομα του αρχείου πρέπει να έχει την επέκταση .rpy "
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "Υπάρχει ήδη αυτό το αρχείο."
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Η Ren'Py αυτόματα φορτώνει όλα τα αρχεία σεναρίων-κώδικα με την κατάληξη .pry . Για να χρησιμοποιήσετε ένα \n # αρχείο, δημιουργήστε μέσα στο αρχείο προς χρήση μία ετικέτα (label) και κάντε μια μεταπήδηση στην ετικέτα (jump), από ένα άλλο αρχείο.\n"
-
diff --git a/launcher/game/tl/greek/android.rpy b/launcher/game/tl/greek/android.rpy
deleted file mode 100644
index b60a047..0000000
--- a/launcher/game/tl/greek/android.rpy
+++ /dev/null
@@ -1,171 +0,0 @@
-
-translate greek strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Για να χτίσετε πακέτα για το Android, παρακαλούμε κατεβάστε το RAPT και τοποθετήστε το στον φάκελο της Ren'Py. Κατόπιν αυτού, επανεκκινήστε τον Εκκινητή."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Αν εργάζεστε σε Windows, για τη δημιουργία πακέτων Android, απαιτείται ένα 32-bit Java Development Kit. Το JDK είναι διαφορετικό του JRE, οπότε μπορεί να έχετε Java χωρίς όμως να έχετε το JDK. Παρακαλoύμε λοιπόν να  {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html} κατεβάσετε κι εγκαταστήσετε από εδώ το JDK{/a} και κατόπιν να επανεκκινήσετε τον Εκκινητή της Ren'Py. "
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "Το RAPT έχει εγκατασταθεί, αλλά θα πρέπει να εγαταστήσετε το Android SDK για να μπορέσετε να χτίσετε πακέτα Android. Επιλέξτε να εγκαταστήσετε το SDK για να γίνει αυτό."
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "Το RAPT έχει εγκατασταθεί, αλλά δεν έχετε ορίσει ένα κλειδί. Παρακαλώ δημιουργήστε ένα νέο κλειδί ή επαναφέρετε το android.keystore."
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Το συγκεκριμένο έργο δεν έχει ρυθμιστεί. Χρησιμοποιήστε το \"Ρύθμιση\" για να το ρυθμίσετε προτού το χτίσετε."
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Επιλέξτε \"Χτίσε\" για να χτίσετε το συγκεκριμένο έργο σας ή συνδέστε μια συσκευή Android κι επιλέξτε \"Χτίσε κι εγκατέστησε\" για να το χτίσετε και να το εγκαταστήσετε στη συσκευή."
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Επιχειρεί να προσομοιώσει ένα τηλέφωνο με Android. \n\nΗ οθόνη αφής προσομοιώνεται με το ποντίκι, αλλά μόνο όταν κρατάτε πατημένο το κουμπί. Το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Επιχειρεί να προσομοιώσει ένα tablet με Android. \n\n Η οθόνη αφής προσομοιώνεται με το ποντίκι, αλλά μόνο όταν κρατάτε πατημένο το κουμπί. Το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Επιχειρεί να προσομοιώσει μια κονσόλα για τηλεόραση, που τρέχει Android, σαν το OUYA ή το Fire TV. \n\n Τα πλήκτρα με τα βέλη αντιστοιχούν στα πλήκτρα σταυρό με βέλη του χειριστηρίου, το Enter είναι το Select, το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Κατεβάζει κι εγκαθιστά το Android SDK και τα υποστηρικτικά πακέτα. Προαιρετικά δημιουργεί τα απαιτούμενα κλειδιά, για να δοθεί υπογραφή στο πακέτο."
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "Ρυθμίζει το όνομα του πακέτου, την έκδοση κι άλλες πληροφορίες για το έργο."
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Ανοίγει το αρχείο που περιέχει τα κλειδιά του Google Play στον επεξεργαστή κειμένου.\n\nΑυτό θα το χρειαστέτε μόνο αν η εφαρμογή θα χρησιμοποιεί επέκταση APK. Διαβάστε τα εγχειρίδια για περισσότερς λεπτομέρεις."
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "Χτίζει το πακέτο Android."
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Χτίζει το πακέτο Android και το εγκαθιστά σε μια συσκευή Android συνδεδεμένη στον Η/Υ."
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Χτίζει το πακέτο Android, το εγκαθιστά σε μια συσκευή Android συνδεδεμένη στον Η/Υ και το εκτελεί."
-
-    # game/android.rpy:48
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Σύνδεση σε συσκευή Android που τρέχει ADB, με TCP/IP"
-
-    # game/android.rpy:49
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Αποσύνδεση από συσκευή Android που τρέχει ADB, με TCP/IP"
-
-    # game/android.rpy:50
-    old "Retrieves the log from the Android device and writes it to a file."
-    new "Λήψη καταγεγραμμένων συμβάντων από τη συσκευή Android  και καταγραφή τους σε αρχείο."
-
-    # game/android.rpy:240
-    old "Copying Android files to distributions directory."
-    new "Αντιγράφονται τα αρχεία για Android στο φάκελο της διανομής"
-
-    # game/android.rpy:304
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:324
-    old "Emulation:"
-    new "Προσομοίωση"
-
-    # game/android.rpy:333
-    old "Phone"
-    new "Κινητό Τηλέφωνο"
-
-    # game/android.rpy:337
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:341
-    old "Television"
-    new "Τηλεόραση"
-
-    # game/android.rpy:353
-    old "Build:"
-    new "Χτίσε:"
-
-    # game/android.rpy:361
-    old "Install SDK & Create Keys"
-    new "Εγκατάσταση του SDK και δημιουργία κλειδιών"
-
-    # game/android.rpy:365
-    old "Configure"
-    new "Ρύθμιση"
-
-    # game/android.rpy:369
-    old "Build Package"
-    new "Χτίσε το πακέτο"
-
-    # game/android.rpy:373
-    old "Build & Install"
-    new "Χτίσε κι εγκατέστησε"
-
-    # game/android.rpy:377
-    old "Build, Install & Launch"
-    new "Χτίσε, εγκατέστησε κι εκτέλεσε"
-
-    # game/android.rpy:388
-    old "Other:"
-    new "Άλλο:"
-
-    # game/android.rpy:396
-    old "Remote ADB Connect"
-    new "Απομακρυσμένη σύνδεση με το ADB"
-
-    # game/android.rpy:400
-    old "Remote ADB Disconnect"
-    new "Απομακρυσμένη αποσύνδεση από το ADB"
-
-    # game/android.rpy:404
-    old "Logcat"
-    new "Logcat"
-
-    # game/android.rpy:437
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Προτού πακετάρετε εφαρμογές για Android, θα χρειαστείτε να κατεβάσετε το RAPT, Ren'Py Android Packaging Tool. Θέλετε να κατεβάσετε το RAPT τώρα;"
-
-    # game/android.rpy:490
-    old "Remote ADB Address"
-    new "Διεύθυνση εξ αποστάσεως ADB."
-
-    # game/android.rpy:490
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Παρακαλώ εισάγετε τη διεύθυνση IP και τον αριθμό port που θέλετε να συνδεθείτε, υπό τη μορφή \"192.168.1.143:5555\". Συμβουλευτείτε το εγχειρίδιο χρήσης της συσκευής σας, για να κρίνετε αν υποστηρίζει απομακρυσμένο ADB κι αν ναι, τη διεύθυνση και το port που χρησιμοποιεί."
-
-    # game/android.rpy:502
-    old "Invalid remote ADB address"
-    new "Λάθος διεύθυνση εξ αποστάσεως ADB."
-
-    # game/android.rpy:502
-    old "The address must contain one exactly one ':'."
-    new "Η διεύθυνση πρέπει να περιέχει ακριβώς μόνο μία άνω κάτω τελεία ':'."
-
-    # game/android.rpy:506
-    old "The host may not contain whitespace."
-    new "Ο host δε πρέπει να έχει κενά στο όνομά του."
-
-    # game/android.rpy:512
-    old "The port must be a number."
-    new "Το port πρέπει να είναι αριθμός."
-
-    # game/android.rpy:538
-    old "Retrieving logcat information from device."
-    new "Λαμβάνονται οι πληροφορίες του logcat για τη συσκευή."
-
diff --git a/launcher/game/tl/greek/choose_directory.rpy b/launcher/game/tl/greek/choose_directory.rpy
deleted file mode 100644
index ae385a2..0000000
--- a/launcher/game/tl/greek/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate greek strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Η Ren'Py δε μπόρεσε να τρέξει την python με το tkinter ώστε να δαλέξει το φάκελο. Παρακαλώ εγκαταστήστε το python-tk ή το πακέτο tkinter."
-
diff --git a/launcher/game/tl/greek/choose_theme.rpy b/launcher/game/tl/greek/choose_theme.rpy
deleted file mode 100644
index 14fad64..0000000
--- a/launcher/game/tl/greek/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate greek strings:
-
-    # game/choose_theme.rpy:303
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Δε μπόρεσε να αλλάξει το θέμα. Πιθανώς το αρχείο options.rpy υπέστει υπερβολικά μεγάλη τροποποίηση."
-
-    # game/choose_theme.rpy:368
-    old "Display"
-    new "Εμφάνιση"
-
-    # game/choose_theme.rpy:369
-    old "Window"
-    new "Παράθυρο"
-
-    # game/choose_theme.rpy:370
-    old "Fullscreen"
-    new "Πλήρης οθόνη"
-
-    # game/choose_theme.rpy:371
-    old "Planetarium"
-    new "Πλανητάριο"
-
-    # game/choose_theme.rpy:378
-    old "Sound Volume"
-    new "Ένταση ήχου"
-
-    # game/choose_theme.rpy:426
-    old "Choose Theme"
-    new "Επιλέξτε θέμα"
-
-    # game/choose_theme.rpy:439
-    old "Theme"
-    new "Θέμα"
-
-    # game/choose_theme.rpy:464
-    old "Color Scheme"
-    new "Συνδυασμός χρωμάτων"
-
-    # game/choose_theme.rpy:496
-    old "Continue"
-    new "Συνέχεια"
-
diff --git a/launcher/game/tl/greek/common.rpy b/launcher/game/tl/greek/common.rpy
index d342a74..465e48d 100644
--- a/launcher/game/tl/greek/common.rpy
+++ b/launcher/game/tl/greek/common.rpy
@@ -1,772 +1,335 @@
 
 translate greek strings:
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Monday"
     new "{#weekday}Δευτέρα"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Tuesday"
     new "{#weekday}Τρίτη"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Wednesday"
     new "{#weekday}Τετάρτη"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Thursday"
     new "{#weekday}Πέμπτη"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Friday"
     new "{#weekday}Παρασκευή"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Saturday"
     new "{#weekday}Σάββατο"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Sunday"
     new "{#weekday}Κυριακή"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Mon"
     new "{#weekday_short}Δευ"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Tue"
     new "{#weekday_short}Τρι"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Wed"
     new "{#weekday_short}Τετ"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Thu"
     new "{#weekday_short}Πεμ"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Fri"
     new "{#weekday_short}Παρ"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sat"
     new "{#weekday_short}Σαβ"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sun"
     new "{#weekday_short}Κυρ"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}January"
     new "{#month}Ιανουάριος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}February"
     new "{#month}Φεβρουάριος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}March"
     new "{#month}Μάρτιος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}April"
     new "{#month}Απρίλιος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}May"
     new "{#month}Μάιος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}June"
     new "{#month}Ιούνιος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}July"
     new "{#month}Ιούλιος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}August"
     new "{#month}Αύγουστος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}September"
     new "{#month}Σεπτέμβριος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}October"
     new "{#month}Οκτώμβριος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}November"
     new "{#month}Νοέμβριος"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}December"
     new "{#month}Δεκέμβριος"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jan"
     new "{#month_short}Ιαν"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Feb"
     new "{#month_short}Φεβ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Mar"
     new "{#month_short}Μάρ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Apr"
     new "{#month_short}Απρ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}May"
     new "{#month_short}Μάι"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jun"
     new "{#month_short}Ιούν"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jul"
     new "{#month_short}Ιούλ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Aug"
     new "{#month_short}Αύγ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Sep"
     new "{#month_short}Σεπ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Oct"
     new "{#month_short}Οκτ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Nov"
     new "{#month_short}Νοέ"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Dec"
     new "{#month_short}Δεκ"
 
-    # renpy/common/00action_file.rpy:230
+    # 00action_file.rpy:235
     old "%b %d, %H:%M"
     new "%b %d, %H:%M"
 
-    # renpy/common/00action_file.rpy:718
+    # 00action_file.rpy:820
     old "Quick save complete."
     new "Η ταχεία αποθήκευση παιχνιδιού ολοκληρώθηκε."
 
-
-translate greek strings:
-
-    # renpy/common/00console.rpy:180
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)s κονσόλα, αυθεντικά δημιουργήθηκε από τους: Shiz, C, και delta.\n"
-
-    # renpy/common/00console.rpy:181
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Πατήστε <esc> για να βγείτε από την κονσόλα. Δώστε την εντολή help για βοήθεια. \n"
-
-    # renpy/common/00console.rpy:185
-    old "Ren'Py script enabled."
-    new "Σενάρια κώδικα Ren'Py ενεργοποιήθηκαν."
-
-    # renpy/common/00console.rpy:187
-    old "Ren'Py script disabled."
-    new "Σενάρια κώδικα Ren'Py απενεργοποιήθηκαν."
-
-    # renpy/common/00console.rpy:393
-    old "help: show this help"
-    new "help: εμφάνισε αυτή τη βοήθεια"
-
-    # renpy/common/00console.rpy:398
-    old "commands:\n"
-    new "εντολές:\n"
-
-    # renpy/common/00console.rpy:408
-    old " <renpy script statement>: run the statement\n"
-    new " <renpy script statement>: εκτέλεση αυτής της δήλωσης\n"
-
-    # renpy/common/00console.rpy:410
-    old " <python expression or statement>: run the expression or statement"
-    new "<python expression or statement>: εκτέλεση αυτής της δήλωσης ή έκφρασης\n"
-
-    # renpy/common/00console.rpy:418
-    old "clear: clear the console history"
-    new "clear: καθαρισμός ιστορικού κονσόλας"
-
-    # renpy/common/00console.rpy:422
-    old "exit: exit the console"
-    new "exit: έξοδος από την κονσόλα"
-
-    # renpy/common/00console.rpy:430
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: ανάκτηση αποθηκευμένου παιχνιδιού από την αντίστοιχη θυρίδα"
-
-    # renpy/common/00console.rpy:443
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: αποθήκευση του παιχνιδιού σε αντίστοιχη θυρίδα"
-
-    # renpy/common/00console.rpy:454
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: επανεκκινεί το παιχνίδι, ανανεώνει τα σενάρια κώδικα"
-
-    # renpy/common/00console.rpy:462
-    old "watch <expression>: watch a python expression"
-    new "watch <expression>: παρακολουθεί την έκφραση της python"
-
-    # renpy/common/00console.rpy:488
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expression>: σταματάει να παρακολουθεί την έκφραση της python"
-
-    # renpy/common/00console.rpy:514
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: σταματάει να παρακολουθεί όλες τις εκφράσεις"
-
-    # renpy/common/00console.rpy:531
-    old "jump <label>: jumps to label"
-    new "jump <label>: μεταπηδάει την εκτέλεση κώδικα στην ετικέτα label"
-
-
-translate greek strings:
-
-    # renpy/common/00gallery.rpy:561
-    old "Image [index] of [count] locked."
-    new "Η εικόνα [index] του [count] είναι κλειδωμένη."
-
-    # renpy/common/00gallery.rpy:581
-    old "prev"
-    new "προηγούμενο"
-
-    # renpy/common/00gallery.rpy:582
-    old "next"
-    new "επόμενο"
-
-    # renpy/common/00gallery.rpy:583
-    old "slideshow"
-    new "επίδειξη διαφανειών"
-
-    # renpy/common/00gallery.rpy:584
-    old "return"
-    new "επιστροφή"
-
-
-translate greek strings:
-
-    # renpy/common/00gamepad.rpy:32
-    old "Select Gamepad to Calibrate"
-    new "Επιλέξτε gamepad για να το ρυθμίσετε"
-
-    # renpy/common/00gamepad.rpy:35
-    old "No Gamepads Available"
-    new "Δεν υπάρχουν διαθέσιμα gamepads"
-
-    # renpy/common/00gamepad.rpy:54
-    old "Calibrating [name] ([i]/[total])"
-    new "Ρυθμίζεται το [name] ([i]/[total])"
-
-    # renpy/common/00gamepad.rpy:58
-    old "Press or move the [control!r] [kind]."
-    new "Πατήστε ή κουνήστε το [control!r] [kind]."
-
-    # renpy/common/00gamepad.rpy:66
-    old "Skip (A)"
-    new "Παράλειψη(A)"
-
-    # renpy/common/00gamepad.rpy:69
-    old "Back (B)"
-    new "Πίσω(B)"
-
-
-translate greek strings:
-
-    # renpy/common/00gltest.rpy:68
-    old "Graphics Acceleration"
-    new "Επιτάχυνση γραφικών"
-
-    # renpy/common/00gltest.rpy:72
-    old "Automatically Choose"
-    new "Επέλεξε αυτόματα"
-
-    # renpy/common/00gltest.rpy:77
-    old "Force Angle/DirectX Renderer"
-    new "Εξανάγκασε τον Angle/DirectX Renderer"
-
-    # renpy/common/00gltest.rpy:81
-    old "Force OpenGL Renderer"
-    new "Εξανάγκασε τον OpenGL Renderer"
-
-    # renpy/common/00gltest.rpy:85
-    old "Force Software Renderer"
-    new "Εξανάγκασε Renderer λογισμικό"
-
-    # renpy/common/00gltest.rpy:91
-    old "Gamepad"
-    new "Gamepad"
-
-    # renpy/common/00gltest.rpy:95
-    old "Enable"
-    new "Ενεργοποιημένο"
-
-    # renpy/common/00gltest.rpy:99
-    old "Disable"
-    new "Απενεργοποιημένο"
-
-    # renpy/common/00gltest.rpy:105
-    old "Calibrate"
-    new "Ρύθμισε"
-
-    # renpy/common/00gltest.rpy:111
-    old "Changes will take effect the next time this program is run."
-    new "Οι αλλαγές θα λάβουν χώρα, την επόμενη φορά που θα εκτελεστεί το πρόγραμμα."
-
-    # renpy/common/00gltest.rpy:115
-    old "Quit"
-    new "Έξοδος"
-
-    # renpy/common/00gltest.rpy:120
-    old "Return"
-    new "Επιστροφή"
-
-    # renpy/common/00gltest.rpy:150
-    old "Performance Warning"
-    new "Προειδοποίηση επιδόσεων"
-
-    # renpy/common/00gltest.rpy:155
-    old "This computer is using software rendering."
-    new "Αυτός ο ηλεκτρονικός υπολογιστής χρησιμοποιεί λογισμικό rendering."
-
-    # renpy/common/00gltest.rpy:157
-    old "This computer is not using shaders."
-    new "Αυτός ο ηλεκτρονικός υπολογιστής δε χρησιμοποιεί shaders."
-
-    # renpy/common/00gltest.rpy:159
-    old "This computer is displaying graphics slowly."
-    new "Αυτός ο ηλεκτρονικός υπολογιστής εμφανίζει γραφικά με αργό ρυθμό."
-
-    # renpy/common/00gltest.rpy:161
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Αυτός ο ηλεκτρονικός υπολογιστής έχει ένα πρόβλημα με το να δείξει γραφικά: [problem]."
-
-    # renpy/common/00gltest.rpy:166
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Οι οδηγοί γραφικών του, ίσως δεν είναι ενημερωμένοι ή δε λειτουργούν σωστά. Αυτό μπορεί να προκαλέσει αργή ή λάθος εμφάνιση γραφικών. Ενημέρωση του Direct X μπορεί να λύσει το πρόβλημα."
-
-    # renpy/common/00gltest.rpy:168
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Οι οδηγοί γραφικών του, ίσως δεν είναι ενημερωμένοι ή δε λειτουργούν σωστά. Αυτό μπορεί να προκαλέσει αργή ή λάθος εμφάνιση γραφικών."
-
-    # renpy/common/00gltest.rpy:173
-    old "Update DirectX"
-    new "Ενημέρωση του DirectX"
-
-    # renpy/common/00gltest.rpy:179
-    old "Continue, Show this warning again"
-    new "Συνέχισε, Εμφάνισε αυτή τη προειδοποίηση ξανά"
-
-    # renpy/common/00gltest.rpy:183
-    old "Continue, Don't show warning again"
-    new "Συνέχισε, Μην εμφανίσεις αυτή τη προειδοποίηση ξανά"
-
-    # renpy/common/00gltest.rpy:209
-    old "Updating DirectX."
-    new "Ενημερώνεται το DirectX"
-
-    # renpy/common/00gltest.rpy:213
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "Η εγκατάσταση του DirectX μέσω ιστού ξεκίνησε. Ίσως αρχίζει ελαχιστοποιημένο στη μπάρα εργασιών. Παρακαλούμε ακολουθήστε τις οδηγίες-βήματα εγκατάστασης του DirectX."
-
-    # renpy/common/00gltest.rpy:217
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Σημέίωση: Το Microsoft's DirectX πρόγραμμα εγκατάστασης μέσω ιστού, εξ ορισμού θα εγκαταστήσει τη Bing toolbar. Αν δε θέλετε κάτι τέτοιο, προσέξτε να μην είναι τσεκαρισμένη η αντίστοιχη επιλογή.{/b} "
-
-    # renpy/common/00gltest.rpy:221
-    old "When setup finishes, please click below to restart this program."
-    new "Όταν τελειώσει η εγκατάσταση, πατήστε από κάτω για να γίνει επανεκκίνηση του προγράμματος."
-
-    # renpy/common/00gltest.rpy:223
-    old "Restart"
-    new "Επανέναρξη"
-
-
-translate greek strings:
-
-    # renpy/common/00keymap.rpy:242
-    old "Saved screenshot as %s."
-    new "Αποθηκευμένα στιγμιότυπα οθόνης ως  %s."
-
-
-translate greek strings:
-
-    # renpy/common/00layout.rpy:444
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Είστε σίγουροι;"
 
-    # renpy/common/00layout.rpy:445
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Είσαστε σίγουροι πως θέλετε να σβήσετε αυτό το αποθηκευμένο παιχνίδι;"
 
-    # renpy/common/00layout.rpy:446
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Είσαστε σίγουροι πως θέλετε να αντικαταστήσετε αυτό το αποθηκευμένο παιχνίδι με το τρέχον;"
 
-    # renpy/common/00layout.rpy:447
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Αν φορτώσετε το παιχνίδι αυτό, θα χάσετε πρόοδο που δεν αποθηκεύσατυε. \n Είσαστε σίγουροι πως θέλετε να το κάνετε αυτό;"
 
-    # renpy/common/00layout.rpy:448
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Είσαστε σίγουροι πως θέλετε να βγείτε;"
 
-    # renpy/common/00layout.rpy:449
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Είσαστε σίγουροι πως θέλετε να επιστρέψετε στο κεντρικό μενού; \n Θα χαθεί πρόοδος που δεν έχει αποθηκευτεί."
 
-    # renpy/common/00layout.rpy:450
+    # 00gui.rpy:233
     old "Are you sure you want to end the replay?"
     new "Σίγουρα θέλετε να λήξετε την επανάληψη;"
 
-    # renpy/common/00layout.rpy:451
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Εισαστε σίγουροι πως θέλετε να ξεκινήσετε την παράλειψη;"
 
-    # renpy/common/00layout.rpy:452
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Σίγουρα θέλετε να παραλείψετε την επόμενη επιλογή;"
 
-    # renpy/common/00layout.rpy:453
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Σίγουρα θέλετε να παραλείψετε τα πάντα έως το μέρος με διάλογο που δεν έχετε δει ή την επόμενη επιλογή;"
-
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-translate greek strings:
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Αποθηκευμένα στιγμιότυπα οθόνης ως  %s."
 
-    # renpy/common/00library.rpy:125
+    # 00library.rpy:142
     old "Self-voicing disabled."
     new "Aπενεργοποιήθηκε το η λειτουργία αυτοαπαγγελίας."
 
-    # renpy/common/00library.rpy:126
+    # 00library.rpy:143
     old "Clipboard voicing enabled. "
     new "Απενεργοποιήθηκε η λειουργία αυτοαπαγγελίας μέσω clipboard"
 
-    # renpy/common/00library.rpy:127
+    # 00library.rpy:144
     old "Self-voicing enabled. "
     new "Η λειτουργία αυτοαπαγγελίας ενεργοποιήθηκε."
 
-    # renpy/common/00library.rpy:162
+    # 00library.rpy:179
     old "Skip Mode"
     new "Κατάσταση παράλειψης"
 
-    # renpy/common/00library.rpy:165
-    old "Fast Skip Mode"
-    new "Κατάσταση γρήγορης παράλειψης"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-
-translate greek strings:
-
-    # renpy/common/00preferences.rpy:409
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "Η λειτουργία αυτοαπαγγελίας μέσω clipboard ενεργοποιήθηκε. Πατήστε 'shift+C' για να την απερνεργοποιήσετε."
 
-    # renpy/common/00preferences.rpy:411
+    # 00preferences.rpy:424
     old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
     new "Η λειτουργία αυτοαπαγγελίας θα έλεγε \"[renpy.display.tts.last]\". Πατήστε 'alt+shift+V' για απενεργοποίηση."
 
-    # renpy/common/00preferences.rpy:413
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "Η λειτουργία αυτοαπαγγελίας ενεργοποιήθηκε. Πατήστε το 'v' για απενεργοποίηση."
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate greek strings:
-
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "Το πρόγραμμα ενημέρωσης της Ren'Py δεν υποστηρίζει συσκευές κινητων τηλεφώνων."
 
-    # renpy/common/00updater.rpy:481
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "Προσομοιώνεται ένα σφάλμα."
 
-    # renpy/common/00updater.rpy:657
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "Ειτε το έργο δεν υποστηρίζει ενημερώσεις, είτε το αρχείο κατάστασης ενημερώσεων έχει διαγραφεί."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "Αυτός ο λογαριασμός, δεν έχει δικαιώματα που να του επιτρέπουν να κάνει ενημέρωση."
 
-    # renpy/common/00updater.rpy:674
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "Αυτός ο λογαριασμός, δεν έχει δικαιώματα που να του επιτρέπουν να ενημερώσει το ημερολόγιο συμβάντων (log)."
 
-    # renpy/common/00updater.rpy:699
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "Δεν ήταν δυνατόν να επαληθευτεί η υπογραφή της ενημέρωσης."
 
-    # renpy/common/00updater.rpy:970
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "Το αρχείο ενημέρωσης δεν κατέβηκε."
 
-    # renpy/common/00updater.rpy:988
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "Το αρχείο ενημέρωσης δε διαθέτει σωστό digest, ενδεχομένως να είναι παραμορφωμένο."
 
-    # renpy/common/00updater.rpy:1044
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "Κατά το ξεπακετάρισμα {}, άγνωστος τύπος {}."
 
-    # renpy/common/00updater.rpy:1395
+    # 00updater.rpy:1393
     old "Updater"
     new "Ενημερωτής"
 
-    # renpy/common/00updater.rpy:1404
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Το πρόγραμμα είναι ενημερωμένο."
 
-    # renpy/common/00updater.rpy:1406
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "Η έκδοση [u.version] είναι διαθέσιμη. θέλετε να την εγκαταστήσετε;"
 
-    # renpy/common/00updater.rpy:1408
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Προετοιμασία για κατέβασμα των ενημερώσεων."
 
-    # renpy/common/00updater.rpy:1410
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Κατεβάζω τις ενημερώσεις."
 
-    # renpy/common/00updater.rpy:1412
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Ξεπακετάρω τις ενημερώσεις."
 
-    # renpy/common/00updater.rpy:1416
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "Οι ενημερώσεις εγκαταστήθηκαν. Το πρόγραμμα θα επανεκκινηθεί."
 
-    # renpy/common/00updater.rpy:1418
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "Οι ενημερώσεις εγκαταστήθηκαν."
 
-    # renpy/common/00updater.rpy:1420
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "Οι ενημερώσεις ματαιώθηκαν."
 
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Η εικόνα [index] του [count] είναι κλειδωμένη."
 
-translate greek strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "Άδεια θυρίδα."
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
-    new "Προηγούμενο"
-
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
-    new "Επόμενο"
-
-
-translate greek strings:
-
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "Ρύθμισης χειριστηρίου joystick"
-
-
-translate greek strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "Μενού Δημιουργού"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "Ξαναφόρτωσε το παιχνίδι"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Κονσόλα"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "Προβολέας μεταβλητών"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "Θεματικός έλεγχος"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "Λήψη θέσης εικόνας"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "Λίστα ονομάτων αρχείων"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Εμφάνισε το ιστορικό φορτώματος εικόνων."
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Απέκρυψε το ιστορικό φορτώματος εικόνων."
-
-    # renpy/common/_developer/developer.rpym:150
-    old "No variables have changed since the game started."
-    new "Δεν έχει αλλάξει τιμή μεταβλητής από την αρχή του παιχνιδιού."
-
-    # renpy/common/_developer/developer.rpym:153
-    old "Return to the developer menu"
-    new "Επιστροφή στο μενού Δημιουργού."
-
-    # renpy/common/_developer/developer.rpym:386
-    old "Rectangle: %r"
-    new "Παραλληλόγραμμο: %r"
-
-    # renpy/common/_developer/developer.rpym:391
-    old "Mouse position: %r"
-    new "Θέση ποντικιού: %r"
-
-    # renpy/common/_developer/developer.rpym:396
-    old "Right-click or escape to quit."
-    new "Δεξί κλικ ή Esc για να βγείτε."
-
-    # renpy/common/_developer/developer.rpym:425
-    old "Rectangle copied to clipboard."
-    new "Το παραλληλόγραμμο αποθηκεύτηκε στο clipboard."
-
-    # renpy/common/_developer/developer.rpym:428
-    old "Position copied to clipboard."
-    new "Η θέση αποθηκεύτηκε στο clipboard."
-
-    # renpy/common/_developer/developer.rpym:459
-    old "Done"
-    new "Ολοκληρώθηκε."
-
-
-translate greek strings:
-
-    # renpy/common/_developer/inspector.rpym:46
-    old "Displayable Inspector"
-    new "Πρόγραμμα επιθεώρησης με προβολή πληροφοριών"
-
-    # renpy/common/_developer/inspector.rpym:52
-    old "Nothing to inspect."
-    new "Τίποτα προς επιθεώρηση"
-
-    # renpy/common/_developer/inspector.rpym:70
-    old "Size"
-    new "Μέγεθος"
-
-    # renpy/common/_developer/inspector.rpym:74
-    old "Style"
-    new "Στυλ"
-
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "Τοποθεσία"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Επιθεώρούνται τα στυλ του [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:155
-    old "displayable:"
-    new "προβαλλόμενο:"
-
-    # renpy/common/_developer/inspector.rpym:162
-    old "        (no properties affect the displayable)"
-    new "        (το προβαλλόμενο δεν επηρεάζεται από ιδιότητες)"
-
-    # renpy/common/_developer/inspector.rpym:164
-    old "        (default properties omitted)"
-    new "        (οι ιδιότητες εξσφαλμάτωσης παραλείφθηκαν)"
-
-    # renpy/common/_developer/inspector.rpym:206
-    old "<repr() failed>"
-    new "το <repr() απέτυχε>"
-
-
-translate greek strings:
-
-    # renpy/common/_errorhandling.rpym:500
-    old "An exception has occurred."
-    new "Συνέβη μια προγραμματιστική εξαίρεση."
-
-    # renpy/common/_errorhandling.rpym:526
-    old "Rollback"
-    new "Ανάκληση"
-
-    # renpy/common/_errorhandling.rpym:528
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Γίνεται απόπειρα επιστροφής σε προηγούμενη χρονικά κατάσταση, ώστε να σώσετε ή να επιλέξετε διαφορετική επιλογή."
-
-    # renpy/common/_errorhandling.rpym:531
-    old "Ignore"
-    new "Παράληψη"
-
-    # renpy/common/_errorhandling.rpym:533
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Παραλείπει την προγραμματιστική εξαίρεση, επιτρέποντάς σας να συνεχίσετε. Συνήθως αυτό οδηγεί σε επιπλέον προβλήματα."
-
-    # renpy/common/_errorhandling.rpym:536
-    old "Reload"
-    new "Επαναφόρτωση"
-
-    # renpy/common/_errorhandling.rpym:538
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Επαναφορτώνει το παιχνίδι από το δίσκο, σώζοντας κι ανακαλώντας τη θέση του παιχνιδιού, αν αυτό είναι δυνατόν."
-
-    # renpy/common/_errorhandling.rpym:540
-    old "Open Traceback"
-    new "Άνοιγμα του Traceback"
-
-    # renpy/common/_errorhandling.rpym:542
-    old "Opens the traceback.txt file in a text editor."
-    new "Ανοίγει το αρχείο traceback.txt σε επεξεργαστή κειμένου."
-
-    # renpy/common/_errorhandling.rpym:545
-    old "Copy to Clipboard"
-    new "Αποθήκευση στο clipboard"
-
-    # renpy/common/_errorhandling.rpym:547
-    old "Copies the traceback.txt file to the clipboard."
-    new "Αποθηκεύει το traceback.txt στο clipboard"
-
-    # renpy/common/_errorhandling.rpym:553
-    old "Quits the game."
-    new "Κλέινει το παιχνίδι."
-
-    # renpy/common/_errorhandling.rpym:580
-    old "Parsing the script failed."
-    new "Απέτυχε η ανάλυση του σεναρίου κώδικα."
-
-    # renpy/common/_errorhandling.rpym:607
-    old "Open Parse Errors"
-    new "Άνοιξε τα σφάλματα της ανάλυσης."
-
-    # renpy/common/_errorhandling.rpym:609
-    old "Opens the errors.txt file in a text editor."
-    new "Ανοίγει το αρχείο errors.txt σε επεξεργαστή κειμένου."
-
-    # renpy/common/_errorhandling.rpym:614
-    old "Copies the errors.txt file to the clipboard."
-    new "Αντιγράφει το errors.txt στο clipboard."
-
+    # 00gallery.rpy:583
+    old "prev"
+    new "προηγούμενο"
 
-translate greek strings:
+    # 00gallery.rpy:584
+    old "next"
+    new "επόμενο"
 
-    # renpy/common/_layout/classic_load_save.rpym:170
-    old "a"
-    new "a"
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "επίδειξη διαφανειών"
 
-    # renpy/common/_layout/classic_load_save.rpym:179
-    old "q"
-    new "q"
+    # 00gallery.rpy:586
+    old "return"
+    new "επιστροφή"
 
diff --git a/launcher/game/tl/greek/developer.rpy b/launcher/game/tl/greek/developer.rpy
new file mode 100644
index 0000000..755f738
--- /dev/null
+++ b/launcher/game/tl/greek/developer.rpy
@@ -0,0 +1,179 @@
+
+translate greek strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Μενού Δημιουργού"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Ξαναφόρτωσε το παιχνίδι"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Κονσόλα"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Προβολέας μεταβλητών"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Θεματικός έλεγχος"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Λήψη θέσης εικόνας"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Λίστα ονομάτων αρχείων"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Εμφάνισε το ιστορικό φορτώματος εικόνων."
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Απέκρυψε το ιστορικό φορτώματος εικόνων."
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Τίποτα προς επιθεώρηση"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Επιστροφή στο μενού Δημιουργού."
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Παραλληλόγραμμο: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Θέση ποντικιού: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Δεξί κλικ ή Esc για να βγείτε."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Το παραλληλόγραμμο αποθηκεύτηκε στο clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Η θέση αποθηκεύτηκε στο clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Πρόγραμμα επιθεώρησης με προβολή πληροφοριών"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Μέγεθος"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Στυλ"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Τοποθεσία"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Επιθεώρούνται τα στυλ του [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "προβαλλόμενο:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (το προβαλλόμενο δεν επηρεάζεται από ιδιότητες)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (οι ιδιότητες εξσφαλμάτωσης παραλείφθηκαν)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "το <repr() απέτυχε>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Πατήστε <esc> για να βγείτε από την κονσόλα. Δώστε την εντολή help για βοήθεια. \n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Σενάρια κώδικα Ren'Py ενεργοποιήθηκαν."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Σενάρια κώδικα Ren'Py απενεργοποιήθηκαν."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: εμφάνισε αυτή τη βοήθεια"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "εντολές:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: εκτέλεση αυτής της δήλωσης\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new "<python expression or statement>: εκτέλεση αυτής της δήλωσης ή έκφρασης\n"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: καθαρισμός ιστορικού κονσόλας"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: έξοδος από την κονσόλα"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: ανάκτηση αποθηκευμένου παιχνιδιού από την αντίστοιχη θυρίδα"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: αποθήκευση του παιχνιδιού σε αντίστοιχη θυρίδα"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: επανεκκινεί το παιχνίδι, ανανεώνει τα σενάρια κώδικα"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: παρακολουθεί την έκφραση της python"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: σταματάει να παρακολουθεί την έκφραση της python"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: σταματάει να παρακολουθεί όλες τις εκφράσεις"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: μεταπηδάει την εκτέλεση κώδικα στην ετικέτα label"
+
diff --git a/launcher/game/tl/greek/distribute.rpy b/launcher/game/tl/greek/distribute.rpy
deleted file mode 100644
index b106fb3..0000000
--- a/launcher/game/tl/greek/distribute.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate greek strings:
-
-    # game/distribute.rpy:384
-    old "Scanning project files..."
-    new "Γίνεται ανάγνωση των αρχείων του έργου..."
-
-    # game/distribute.rpy:400
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Το χτίσιμο της διανομής απέτυχε.\n\n Η build.directory_name μεταβλητή πρέπει να μην εμπεριέχει κενά, άνω-κάτω τελεία, ή ερωτηματικό."
-
-    # game/distribute.rpy:445
-    old "No packages are selected, so there's nothing to do."
-    new "Δεν έχει επιλεγεί πακέτο, οπότε δεν υπάρχει κάτι να γίνει."
-
-    # game/distribute.rpy:457
-    old "Scanning Ren'Py files..."
-    new "Σαρώνονται τα αρχεία της Ren'Py..."
-
-    # game/distribute.rpy:509
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Όλα τα πακέτα χτίσητκαν.\n\nΔεν υποστηρίζεται σε Windows το ξεπακετάρισμα κι επαναπακετάρισμα, διανομών για Linux και Macintosh, επειδή στα εν λόγω λειτουργικά συστήματα υπάρχουν πληροφορίες δικαιωμάτων χρήσης."
-
-    # game/distribute.rpy:638
-    old "Archiving files..."
-    new "Τα αρχεία τακτοποιούνται."
-
-    # game/distribute.rpy:956
-    old "Writing the [variant] [format] package."
-    new "Γράφεται το [variant] [format] πακέτο."
-
-    # game/distribute.rpy:969
-    old "Making the [variant] update zsync file."
-    new "Κάνω το [variant] να ενημερώσει το αρχείο zsync."
-
-    # game/distribute.rpy:1111
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Επεξεργασμένα {b}[complete]{/b} από {b}[total]{/b} αρχεία."
-
diff --git a/launcher/game/tl/greek/distribute_gui.rpy b/launcher/game/tl/greek/distribute_gui.rpy
deleted file mode 100644
index 97a9fb3..0000000
--- a/launcher/game/tl/greek/distribute_gui.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate greek strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "Χτίσε Διανομές: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:171
-    old "Directory Name:"
-    new "Όνομα Φακέλου:"
-
-    # game/distribute_gui.rpy:175
-    old "Executable Name:"
-    new "Όνομα εκτελέσιμου αρχείου:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "Πράξεις:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "Επεξεργαστείτε το αρχείο options.rpy"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "Προσθήκη 'from clauses to calls', μία φορά"
-
-    # game/distribute_gui.rpy:195
-    old "Refresh"
-    new "Ανανέωση"
-
-    # game/distribute_gui.rpy:212
-    old "Build Packages:"
-    new "Χτίστε τα Πακέτα:"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "Επιλογές:"
-
-    # game/distribute_gui.rpy:236
-    old "Build Updates"
-    new "Χτίστε ενημερώσεις"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "Προσθήκη from clauses to calls"
-
-    # game/distribute_gui.rpy:239
-    old "Force Recompile"
-    new "Εξαναγκασμός επαναμεταγλώττισης:"
-
-    # game/distribute_gui.rpy:243
-    old "Build"
-    new "Χτίσε"
-
-    # game/distribute_gui.rpy:247
-    old "Adding from clauses to call statements that do not have them."
-    new "Προσθέτονται from clauses to call σε δηλώσεις οι οποίες δεν έχουν."
-
-    # game/distribute_gui.rpy:268
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Βρέθηκαν σφάλματα κατά την εκτέλεση του έργου. Παρακαλούμε σιγουρευτείτε πως το έργο τρέχει χωρίς σφάλματα, πριν χτίσετε μια διανομή."
-
-    # game/distribute_gui.rpy:285
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Το έργο σας δεν περιέχει πληροφορίες για το χτίσιμό του. Θέλετε να προστεθούν στο τέλος του αρχείου options.rpy;"
-
diff --git a/launcher/game/tl/greek/editor.rpy b/launcher/game/tl/greek/editor.rpy
deleted file mode 100644
index 8d71b0e..0000000
--- a/launcher/game/tl/greek/editor.rpy
+++ /dev/null
@@ -1,55 +0,0 @@
-
-translate greek strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Συνιστάται.{/b} Ένας επεξεργαστής κειμένου σε έκδοση beta, με εύκολο περιβάλλον εργασίας και χαραχτηριστικά που σας βοηθούν, όπως π.χ. ορθογραφικό έλεγχο. Ο Editra προς το παρόν δεν υποστηρίζει IME για είσοδο κειμένου σε Κινέζικα, Ιαπωνέζικα και Κορεάτικα."
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Συνιστάται.{/b} Ένας επεξεργαστής κειμένου σε έκδοση beta, με εύκολο περιβάλλον εργασίας και χαραχτηριστικά που σας βοηθούν, όπως π.χ. ορθογραφικό έλεγχο. Ο Editra προς το παρόν δεν υποστηρίζει IME για είσοδο κειμένου σε Κινέζικα, Ιαπωνέζικα και Κορεάτικα. Σε Linux ο Editra απαιτεί το wxPython."
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "Αυτό πιθανώς να συνέβη, διότι το wxPython δεν έχει εγκατασταθεί σε αυτό το σύστημα."
-
-    # game/editor.rpy:169
-    old "Up to 22 MB download required."
-    new "Απαιτείται να κατέβουν έως και 22 MB."
-
-    # game/editor.rpy:182
-    old "A mature editor that requires Java."
-    new "Ένας ώριμος επεξεργαστής κειμένου που απαιτεί Java."
-
-    # game/editor.rpy:182
-    old "1.8 MB download required."
-    new "1.8 MB απαιτείται να κατέβει."
-
-    # game/editor.rpy:182
-    old "This may have occured because Java is not installed on this system."
-    new "Αυτό πιθανώς να συνέβη, διότι η Java δεν έχει εγκατασταθεί σε αυτό το σύστημα."
-
-    # game/editor.rpy:191
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Επικαλείται τον επεξεργαστή κειμένου που στο σύστημά σας σχετίζεται με αρχεία με επέκταση .rpy"
-
-    # game/editor.rpy:207
-    old "Prevents Ren'Py from opening a text editor."
-    new "Εμποδίζει τη Ren'Py να ανοίξει επεξεργαστή κειμένου."
-
-    # game/editor.rpy:359
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Μια προγραμματιστική εξαίρεση συνέβει κατά την εκκίνηση του επεξεργαστή κειμένου:\n[exception!q] "
-
-    # game/editor.rpy:457
-    old "Select Editor"
-    new "Επιλέξτε επεξεργαστή κειμένου"
-
-    # game/editor.rpy:472
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Ο επεξεργαστής κειμένου είναι το πρόγραμμα που θα χρησιμοποιείτε για να τροποποιείτε τα αρχεία σεναρίων κώδικα της Ren'Py. Από εδώ μπορείτε να επιλέξετε ποιον επεξεργαστή θα χρησιμοποιεί η Ren'Py. Αν δεν είναι ήδη εγκατεστημένος, θα κατέβει και θα εγκατασταθεί αυτόματα."
-
-    # game/editor.rpy:494
-    old "Cancel"
-    new "Ακύρωση"
-
diff --git a/launcher/game/tl/greek/error.rpy b/launcher/game/tl/greek/error.rpy
new file mode 100644
index 0000000..72dd3da
--- /dev/null
+++ b/launcher/game/tl/greek/error.rpy
@@ -0,0 +1,179 @@
+
+translate greek strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Επιτάχυνση γραφικών"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Επέλεξε αυτόματα"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Εξανάγκασε τον Angle/DirectX Renderer"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Εξανάγκασε τον OpenGL Renderer"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Εξανάγκασε Renderer λογισμικό"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Ενεργοποιημένο"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Οι αλλαγές θα λάβουν χώρα, την επόμενη φορά που θα εκτελεστεί το πρόγραμμα."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Προειδοποίηση επιδόσεων"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Αυτός ο ηλεκτρονικός υπολογιστής χρησιμοποιεί λογισμικό rendering."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Αυτός ο ηλεκτρονικός υπολογιστής δε χρησιμοποιεί shaders."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Αυτός ο ηλεκτρονικός υπολογιστής εμφανίζει γραφικά με αργό ρυθμό."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Αυτός ο ηλεκτρονικός υπολογιστής έχει ένα πρόβλημα με το να δείξει γραφικά: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Οι οδηγοί γραφικών του, ίσως δεν είναι ενημερωμένοι ή δε λειτουργούν σωστά. Αυτό μπορεί να προκαλέσει αργή ή λάθος εμφάνιση γραφικών. Ενημέρωση του Direct X μπορεί να λύσει το πρόβλημα."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Οι οδηγοί γραφικών του, ίσως δεν είναι ενημερωμένοι ή δε λειτουργούν σωστά. Αυτό μπορεί να προκαλέσει αργή ή λάθος εμφάνιση γραφικών."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Ενημέρωση του DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Συνέχισε, Εμφάνισε αυτή τη προειδοποίηση ξανά"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Συνέχισε, Μην εμφανίσεις αυτή τη προειδοποίηση ξανά"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Ενημερώνεται το DirectX"
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Η εγκατάσταση του DirectX μέσω ιστού ξεκίνησε. Ίσως αρχίζει ελαχιστοποιημένο στη μπάρα εργασιών. Παρακαλούμε ακολουθήστε τις οδηγίες-βήματα εγκατάστασης του DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Σημέίωση: Το Microsoft's DirectX πρόγραμμα εγκατάστασης μέσω ιστού, εξ ορισμού θα εγκαταστήσει τη Bing toolbar. Αν δε θέλετε κάτι τέτοιο, προσέξτε να μην είναι τσεκαρισμένη η αντίστοιχη επιλογή.{/b} "
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Όταν τελειώσει η εγκατάσταση, πατήστε από κάτω για να γίνει επανεκκίνηση του προγράμματος."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Επανέναρξη"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Επιλέξτε gamepad για να το ρυθμίσετε"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "Δεν υπάρχουν διαθέσιμα gamepads"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Ρυθμίζεται το [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Πατήστε ή κουνήστε το [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Παράλειψη(A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Πίσω(B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Άνοιγμα του Traceback"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Ανοίγει το αρχείο traceback.txt σε επεξεργαστή κειμένου."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Αποθήκευση στο clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Αποθηκεύει το traceback.txt στο clipboard"
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Συνέβη μια προγραμματιστική εξαίρεση."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Ανάκληση"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Γίνεται απόπειρα επιστροφής σε προηγούμενη χρονικά κατάσταση, ώστε να σώσετε ή να επιλέξετε διαφορετική επιλογή."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Παράληψη"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Παραλείπει την προγραμματιστική εξαίρεση, επιτρέποντάς σας να συνεχίσετε. Συνήθως αυτό οδηγεί σε επιπλέον προβλήματα."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Επαναφόρτωση"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Επαναφορτώνει το παιχνίδι από το δίσκο, σώζοντας κι ανακαλώντας τη θέση του παιχνιδιού, αν αυτό είναι δυνατόν."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Κλέινει το παιχνίδι."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Απέτυχε η ανάλυση του σεναρίου κώδικα."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Άνοιξε τα σφάλματα της ανάλυσης."
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Ανοίγει το αρχείο errors.txt σε επεξεργαστή κειμένου."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Αντιγράφει το errors.txt στο clipboard."
+
diff --git a/launcher/game/tl/greek/front_page.rpy b/launcher/game/tl/greek/front_page.rpy
deleted file mode 100644
index f3ecec3..0000000
--- a/launcher/game/tl/greek/front_page.rpy
+++ /dev/null
@@ -1,111 +0,0 @@
-
-translate greek strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Άνοικε το φάκελο [text] "
-
-    # game/front_page.rpy:93
-    old "refresh"
-    new "ανανέωση"
-
-    # game/front_page.rpy:120
-    old "+ Create New Project"
-    new "+ Δημιουργία νέου έργου"
-
-    # game/front_page.rpy:132
-    old "Launch Project"
-    new "Φόρτωση Έργου"
-
-    # game/front_page.rpy:149
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-    # game/front_page.rpy:151
-    old "Select project [text]."
-    new "Επιλέξτε έργο [text]."
-
-    # game/front_page.rpy:167
-    old "Tutorial"
-    new "Διδακτικό κι επεξηγηματικό παιχνίδι"
-
-    # game/front_page.rpy:168
-    old "The Question"
-    new "Η Ερώτηση"
-
-    # game/front_page.rpy:184
-    old "Active Project"
-    new "Ενεργό έργο"
-
-    # game/front_page.rpy:192
-    old "Open Directory"
-    new "Άνοιγμα φακέλου"
-
-    # game/front_page.rpy:197
-    old "game"
-    new "παιχνίδι"
-
-    # game/front_page.rpy:198
-    old "base"
-    new "βάση"
-
-    # game/front_page.rpy:199
-    old "images"
-    new "εικόνες"
-
-    # game/front_page.rpy:205
-    old "Edit File"
-    new "Επεξεργασία αρχείου"
-
-    # game/front_page.rpy:213
-    old "All script files"
-    new "Όλα τα αρχεία σεναρίων κώδικα"
-
-    # game/front_page.rpy:222
-    old "Navigate Script"
-    new "Καθοδηγήστε το σενάριο κώδικα"
-
-    # game/front_page.rpy:233
-    old "Check Script (Lint)"
-    new "Έλεγχος του σεναρίου κώδικα (Lint)"
-
-    # game/front_page.rpy:234
-    old "Change Theme"
-    new "Αλλαγή θέματος"
-
-    # game/front_page.rpy:235
-    old "Delete Persistent"
-    new "Διαγραφή επιμένων δεδομένων"
-
-    # game/front_page.rpy:244
-    old "Build Distributions"
-    new "Χτίστε Διανομές"
-
-    # game/front_page.rpy:246
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:247
-    old "iOS"
-    new "iOs"
-
-    # game/front_page.rpy:248
-    old "Generate Translations"
-    new "Δηιμιουργία Μεταγλωττίσεων"
-
-    # game/front_page.rpy:249
-    old "Extract Dialogue"
-    new "Εξάγετε διάλογο"
-
-    # game/front_page.rpy:265
-    old "Checking script for potential problems..."
-    new "Έλεγχος σεναρίου κώδικα για πιθανά προβλήματα..."
-
-    # game/front_page.rpy:280
-    old "Deleting persistent data..."
-    new "Διαγράφονται τα επιμένοντα δεδομένα..."
-
-    # game/front_page.rpy:288
-    old "Recompiling all rpy files into rpyc files..."
-    new "Ξαναγίνεται μεταγλώττιση όλων των αρχείων rpy σε αρχεία rpc..."
-
diff --git a/launcher/game/tl/greek/gui.rpy b/launcher/game/tl/greek/gui.rpy
new file mode 100644
index 0000000..d9148c8
--- /dev/null
+++ b/launcher/game/tl/greek/gui.rpy
@@ -0,0 +1,411 @@
+
+translate greek strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/greek/interface.rpy b/launcher/game/tl/greek/interface.rpy
deleted file mode 100644
index a95b32f..0000000
--- a/launcher/game/tl/greek/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate greek strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "Τεκμηρίωση"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "Ο ιστότοπος της Ren'Py"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "Λίστα παιχνιδιών Ren'Py"
-
-    # game/interface.rpy:110
-    old "About"
-    new "Περί"
-
-    # game/interface.rpy:117
-    old "update"
-    new "ενημέρωση"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "επιλογές"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "έξοδος"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "Ναι"
-
-    # game/interface.rpy:194
-    old "No"
-    new "Όχι"
-
-    # game/interface.rpy:230
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Λόγω περιορισμών στη μορφή πακεταρίσματος, δεν επιτρέπεται να δώσετε χαρακτήρες που να μην ανήκουν στον ASCII σε ονομασίες αρχείων ή φακέλων."
-
-    # game/interface.rpy:322
-    old "ERROR"
-    new "ΣΦΑΛΜΑ"
-
-    # game/interface.rpy:351
-    old "While [what!q], an error occured:"
-    new "Ενόσω [what!q], συνέβη ένα σφάλμα:"
-
-    # game/interface.rpy:351
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:370
-    old "Text input may not contain the {{ or [[ characters."
-    new "Το κείμενο που εισάγετε δε πρέπει να εμπεριέχει τους χαρακτήρες {{ ή [[ "
-
-    # game/interface.rpy:375
-    old "File and directory names may not contain / or \\."
-    new "Ονόματα αρχείων και φακέλων δε πρέπει να περιέχουν τους χαρακτήρες / ή \\"
-
-    # game/interface.rpy:381
-    old "File and directory names must consist of ASCII characters."
-    new "Όνόματα αρχείων και φακέλων πρέπει να αποτελούνται μόνο από χαρακτήρες ASCII."
-
-    # game/interface.rpy:402
-    old "INFORMATION"
-    new "ΠΛΗΡΟΦΟΡΙΕΣ"
-
-    # game/interface.rpy:449
-    old "PROCESSING"
-    new "ΓΙΝΕΤΑΙ ΕΠΕΞΕΡΓΑΣΙΑ"
-
-    # game/interface.rpy:466
-    old "QUESTION"
-    new "ΕΡΩΤΗΣΗ"
-
-    # game/interface.rpy:479
-    old "CHOICE"
-    new "ΕΠΙΛΟΓΗ"
-
diff --git a/launcher/game/tl/greek/ios.rpy b/launcher/game/tl/greek/ios.rpy
deleted file mode 100644
index d0dad00..0000000
--- a/launcher/game/tl/greek/ios.rpy
+++ /dev/null
@@ -1,99 +0,0 @@
-
-translate greek strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Για να χτίσετε πακέτα iOS, παρακαλώ κατεβάστε το renios, αποσυμπιέστε το και τοποθετήστε το στο φάκελο της Ren'Py. Κατόπιν επανεκκινήστε τον εκκινητή."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Ο φάκελος στον οποίο θα τοποθετηθούν τα τα Xcode έργα, δεν έχει επιλεχτεί ακόμα. Ζρησιμοποιήστε το 'Επιλογή φακέλου' για να το επιλέξετε. "
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "Δεν υπάρχει έργο Xcode που να ανταποκρίνεται στο συγκεκριμένο έργο Ren'Py. Επιλέξτε 'Δημιουργήστε έργο Xcode' για να δημιουργήσετε ένα. "
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Ένα αντίστοιχο έγο Xcode υπάρχει. Επιλέξτε 'Ενημέρωση του έργου Xcode' για να το ενημερώσετε με τα μεγαλύτερα αρχεία παιχνιδιού ή χρησιμοποιήστε το Xcode για να το χτίσετε κι εγκαταστήσετε."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Απόπειρα εξομοίωσης ενός iPhone.\n\nΗ είσοδος δεδομένων αφής προσομοιώνεται με το ποντίκη, αλλά μόνο όταν κρατείται πατημένο το αριστερό κουμπί."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Απόπειρα εξομοίωσης ενός iPad.\n\nΗ είσοδος δεδομένων αφής προσομοιώνεται με το ποντίκη, αλλά μόνο όταν κρατείται πατημένο το αριστερό κουμπί."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Επιλέγει το φάκελο που θα τοποθετηθούν τα έργα Xcode."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "Δημιουργεί ένα Xcode έργο που ανταποκρίνεται στο τρέχον έργο της Ren'Py."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Ενημερώνει το έργο Xcode με τα νεώτερα αρχεία του παιχνιδιού. Αυτό πρέπει να γίνεται κάθε φορά που ένα έργο Ren'Py αλλάζει."
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Ανοίγει ένα έργο Xcode στο Xcode."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Ανοίγει το φάκελο που περιέχει τα έργα Xcode."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "To έργο Xcode υπάρχει ήδη. Θέλετε να μετονομάσουμε το παλιό έργο και να το αντικαταστήσουμε με ένα νέο;"
-
-    # game/ios.rpy:211
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:240
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:244
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:264
-    old "Select Xcode Projects Directory"
-    new "Επιλέξτε τον φάκελο που περιέχει τα έργα Xcode"
-
-    # game/ios.rpy:268
-    old "Create Xcode Project"
-    new "Δημιουργήστε έργο Xcode"
-
-    # game/ios.rpy:272
-    old "Update Xcode Project"
-    new "Ενημέρωση του έργου Xcode"
-
-    # game/ios.rpy:277
-    old "Launch Xcode"
-    new "Εκτέλεση του Xcode"
-
-    # game/ios.rpy:312
-    old "Open Xcode Projects Directory"
-    new "Άνοιξε το φάκελο που περιέχει τα Xcode έργα"
-
-    # game/ios.rpy:345
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "Πριν πακετάρετε iOS εφαρμογές, θα πρέπει να κατεβάσετε το renios, ακρωνύμιο Ren'Py's iΟs Support. Θέλετε να κατεβάσετε το renios τώρα;"
-
-    # game/ios.rpy:354
-    old "XCODE PROJECTS DIRECTORY"
-    new "ΦΑΚΕΛΟΣ ΕΡΓΩΝ XCODE"
-
-    # game/ios.rpy:354
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Παρακαλώ επιλέξτε το φάκελο που θα περιέχει τα έργα Xcode, χρησιμοποιώντας τον επιλογέα φακέλου.\n{b}Ο επιλογέας ίσως είναι ήδη ανοικτός πίσω απ' αυτό το παράθυρο.{/b} "
-
-    # game/ios.rpy:359
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Η Ren'Py έθεσε ως φάκελο έργων Xcode τον:"
-
diff --git a/launcher/game/tl/greek/launcher.rpy b/launcher/game/tl/greek/launcher.rpy
new file mode 100644
index 0000000..b39a61e
--- /dev/null
+++ b/launcher/game/tl/greek/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate greek strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Δείτε την άδεια χρήσης"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "ΟΝΟΜΑ_ΑΡΧΕΙΟΥ"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Δώστε το όνομα του προς δημιουργία αρχείου σεναρίου-κώδικα"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Το όνομα του αρχείου πρέπει να έχει την επέκταση .rpy "
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Υπάρχει ήδη αυτό το αρχείο."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Η Ren'Py αυτόματα φορτώνει όλα τα αρχεία σεναρίων-κώδικα με την κατάληξη .pry . Για να χρησιμοποιήσετε ένα \n # αρχείο, δημιουργήστε μέσα στο αρχείο προς χρήση μία ετικέτα (label) και κάντε μια μεταπήδηση στην ετικέτα (jump), από ένα άλλο αρχείο.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Για να χτίσετε πακέτα για το Android, παρακαλούμε κατεβάστε το RAPT και τοποθετήστε το στον φάκελο της Ren'Py. Κατόπιν αυτού, επανεκκινήστε τον Εκκινητή."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Αν εργάζεστε σε Windows, για τη δημιουργία πακέτων Android, απαιτείται ένα 32-bit Java Development Kit. Το JDK είναι διαφορετικό του JRE, οπότε μπορεί να έχετε Java χωρίς όμως να έχετε το JDK. Παρακαλoύμε λοιπόν να  {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html} κατεβάσετε κι εγκαταστήσετε από εδώ το JDK{/a} και κατόπιν να επανεκκινήσετε τον Εκκινητή της Ren'Py. "
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "Το RAPT έχει εγκατασταθεί, αλλά θα πρέπει να εγαταστήσετε το Android SDK για να μπορέσετε να χτίσετε πακέτα Android. Επιλέξτε να εγκαταστήσετε το SDK για να γίνει αυτό."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "Το RAPT έχει εγκατασταθεί, αλλά δεν έχετε ορίσει ένα κλειδί. Παρακαλώ δημιουργήστε ένα νέο κλειδί ή επαναφέρετε το android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Το συγκεκριμένο έργο δεν έχει ρυθμιστεί. Χρησιμοποιήστε το \"Ρύθμιση\" για να το ρυθμίσετε προτού το χτίσετε."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Επιλέξτε \"Χτίσε\" για να χτίσετε το συγκεκριμένο έργο σας ή συνδέστε μια συσκευή Android κι επιλέξτε \"Χτίσε κι εγκατέστησε\" για να το χτίσετε και να το εγκαταστήσετε στη συσκευή."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Επιχειρεί να προσομοιώσει ένα τηλέφωνο με Android. \n\nΗ οθόνη αφής προσομοιώνεται με το ποντίκι, αλλά μόνο όταν κρατάτε πατημένο το κουμπί. Το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Επιχειρεί να προσομοιώσει ένα tablet με Android. \n\n Η οθόνη αφής προσομοιώνεται με το ποντίκι, αλλά μόνο όταν κρατάτε πατημένο το κουμπί. Το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Επιχειρεί να προσομοιώσει μια κονσόλα για τηλεόραση, που τρέχει Android, σαν το OUYA ή το Fire TV. \n\n Τα πλήκτρα με τα βέλη αντιστοιχούν στα πλήκτρα σταυρό με βέλη του χειριστηρίου, το Enter είναι το Select, το πλήκτρο Escape αντιστοιχεί στο κουμπί menu και το PageUP στο κουμπί \"Πίσω\""
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Κατεβάζει κι εγκαθιστά το Android SDK και τα υποστηρικτικά πακέτα. Προαιρετικά δημιουργεί τα απαιτούμενα κλειδιά, για να δοθεί υπογραφή στο πακέτο."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Ρυθμίζει το όνομα του πακέτου, την έκδοση κι άλλες πληροφορίες για το έργο."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Ανοίγει το αρχείο που περιέχει τα κλειδιά του Google Play στον επεξεργαστή κειμένου.\n\nΑυτό θα το χρειαστέτε μόνο αν η εφαρμογή θα χρησιμοποιεί επέκταση APK. Διαβάστε τα εγχειρίδια για περισσότερς λεπτομέρεις."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Χτίζει το πακέτο Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Χτίζει το πακέτο Android και το εγκαθιστά σε μια συσκευή Android συνδεδεμένη στον Η/Υ."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Χτίζει το πακέτο Android, το εγκαθιστά σε μια συσκευή Android συνδεδεμένη στον Η/Υ και το εκτελεί."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Σύνδεση σε συσκευή Android που τρέχει ADB, με TCP/IP"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Αποσύνδεση από συσκευή Android που τρέχει ADB, με TCP/IP"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Λήψη καταγεγραμμένων συμβάντων από τη συσκευή Android  και καταγραφή τους σε αρχείο."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Αντιγράφονται τα αρχεία για Android στο φάκελο της διανομής"
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Προσομοίωση"
+
+    # android.rpy:333
+    old "Phone"
+    new "Κινητό Τηλέφωνο"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Τηλεόραση"
+
+    # android.rpy:353
+    old "Build:"
+    new "Χτίσε:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Εγκατάσταση του SDK και δημιουργία κλειδιών"
+
+    # android.rpy:365
+    old "Configure"
+    new "Ρύθμιση"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Χτίσε το πακέτο"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Χτίσε κι εγκατέστησε"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Χτίσε, εγκατέστησε κι εκτέλεσε"
+
+    # android.rpy:388
+    old "Other:"
+    new "Άλλο:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Απομακρυσμένη σύνδεση με το ADB"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Απομακρυσμένη αποσύνδεση από το ADB"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Προτού πακετάρετε εφαρμογές για Android, θα χρειαστείτε να κατεβάσετε το RAPT, Ren'Py Android Packaging Tool. Θέλετε να κατεβάσετε το RAPT τώρα;"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Διεύθυνση εξ αποστάσεως ADB."
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Παρακαλώ εισάγετε τη διεύθυνση IP και τον αριθμό port που θέλετε να συνδεθείτε, υπό τη μορφή \"192.168.1.143:5555\". Συμβουλευτείτε το εγχειρίδιο χρήσης της συσκευής σας, για να κρίνετε αν υποστηρίζει απομακρυσμένο ADB κι αν ναι, τη διεύθυνση και το port που χρησιμοποιεί."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Λάθος διεύθυνση εξ αποστάσεως ADB."
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Η διεύθυνση πρέπει να περιέχει ακριβώς μόνο μία άνω κάτω τελεία ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "Ο host δε πρέπει να έχει κενά στο όνομά του."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Το port πρέπει να είναι αριθμός."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Λαμβάνονται οι πληροφορίες του logcat για τη συσκευή."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Η Ren'Py δε μπόρεσε να τρέξει την python με το tkinter ώστε να δαλέξει το φάκελο. Παρακαλώ εγκαταστήστε το python-tk ή το πακέτο tkinter."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Δε μπόρεσε να αλλάξει το θέμα. Πιθανώς το αρχείο options.rpy υπέστει υπερβολικά μεγάλη τροποποίηση."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Πλανητάριο"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Επιλέξτε θέμα"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Θέμα"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Συνδυασμός χρωμάτων"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Συνέχεια"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "ΠΛΗΡΟΦΟΡΙΕΣ"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Γίνεται ανάγνωση των αρχείων του έργου..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Το χτίσιμο της διανομής απέτυχε.\n\n Η build.directory_name μεταβλητή πρέπει να μην εμπεριέχει κενά, άνω-κάτω τελεία, ή ερωτηματικό."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Δεν έχει επιλεγεί πακέτο, οπότε δεν υπάρχει κάτι να γίνει."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Σαρώνονται τα αρχεία της Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Όλα τα πακέτα χτίσητκαν.\n\nΔεν υποστηρίζεται σε Windows το ξεπακετάρισμα κι επαναπακετάρισμα, διανομών για Linux και Macintosh, επειδή στα εν λόγω λειτουργικά συστήματα υπάρχουν πληροφορίες δικαιωμάτων χρήσης."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Τα αρχεία τακτοποιούνται."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Γράφεται το [variant] [format] πακέτο."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Κάνω το [variant] να ενημερώσει το αρχείο zsync."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Επεξεργασμένα {b}[complete]{/b} από {b}[total]{/b} αρχεία."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Χτίσε Διανομές: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Όνομα Φακέλου:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Όνομα εκτελέσιμου αρχείου:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Πράξεις:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Επεξεργαστείτε το αρχείο options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Προσθήκη 'from clauses to calls', μία φορά"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Ανανέωση"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Χτίστε τα Πακέτα:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Επιλογές:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Χτίστε ενημερώσεις"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Προσθήκη from clauses to calls"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Εξαναγκασμός επαναμεταγλώττισης:"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Χτίσε"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Προσθέτονται from clauses to call σε δηλώσεις οι οποίες δεν έχουν."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Βρέθηκαν σφάλματα κατά την εκτέλεση του έργου. Παρακαλούμε σιγουρευτείτε πως το έργο τρέχει χωρίς σφάλματα, πριν χτίσετε μια διανομή."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Το έργο σας δεν περιέχει πληροφορίες για το χτίσιμό του. Θέλετε να προστεθούν στο τέλος του αρχείου options.rpy;"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Συνιστάται.{/b} Ένας επεξεργαστής κειμένου σε έκδοση beta, με εύκολο περιβάλλον εργασίας και χαραχτηριστικά που σας βοηθούν, όπως π.χ. ορθογραφικό έλεγχο. Ο Editra προς το παρόν δεν υποστηρίζει IME για είσοδο κειμένου σε Κινέζικα, Ιαπωνέζικα και Κορεάτικα."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Συνιστάται.{/b} Ένας επεξεργαστής κειμένου σε έκδοση beta, με εύκολο περιβάλλον εργασίας και χαραχτηριστικά που σας βοηθούν, όπως π.χ. ορθογραφικό έλεγχο. Ο Editra προς το παρόν δεν υποστηρίζει IME για είσοδο κειμένου σε Κινέζικα, Ιαπωνέζικα και Κορεάτικα. Σε Linux ο Editra απαιτεί το wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Αυτό πιθανώς να συνέβη, διότι το wxPython δεν έχει εγκατασταθεί σε αυτό το σύστημα."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Απαιτείται να κατέβουν έως και 22 MB."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Ένας ώριμος επεξεργαστής κειμένου που απαιτεί Java."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB απαιτείται να κατέβει."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Αυτό πιθανώς να συνέβη, διότι η Java δεν έχει εγκατασταθεί σε αυτό το σύστημα."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Επικαλείται τον επεξεργαστή κειμένου που στο σύστημά σας σχετίζεται με αρχεία με επέκταση .rpy"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Εμποδίζει τη Ren'Py να ανοίξει επεξεργαστή κειμένου."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Μια προγραμματιστική εξαίρεση συνέβει κατά την εκκίνηση του επεξεργαστή κειμένου:\n[exception!q] "
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Επιλέξτε επεξεργαστή κειμένου"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Ο επεξεργαστής κειμένου είναι το πρόγραμμα που θα χρησιμοποιείτε για να τροποποιείτε τα αρχεία σεναρίων κώδικα της Ren'Py. Από εδώ μπορείτε να επιλέξετε ποιον επεξεργαστή θα χρησιμοποιεί η Ren'Py. Αν δεν είναι ήδη εγκατεστημένος, θα κατέβει και θα εγκατασταθεί αυτόματα."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Ακύρωση"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Άνοικε το φάκελο [text] "
+
+    # front_page.rpy:93
+    old "refresh"
+    new "ανανέωση"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Δημιουργία νέου έργου"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Φόρτωση Έργου"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Επιλέξτε έργο [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Διδακτικό κι επεξηγηματικό παιχνίδι"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "Η Ερώτηση"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Ενεργό έργο"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Άνοιγμα φακέλου"
+
+    # front_page.rpy:195
+    old "game"
+    new "παιχνίδι"
+
+    # front_page.rpy:196
+    old "base"
+    new "βάση"
+
+    # front_page.rpy:197
+    old "images"
+    new "εικόνες"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Επεξεργασία αρχείου"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Όλα τα αρχεία σεναρίων κώδικα"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Καθοδηγήστε το σενάριο κώδικα"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Έλεγχος του σεναρίου κώδικα (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Αλλαγή θέματος"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Διαγραφή επιμένων δεδομένων"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Χτίστε Διανομές"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOs"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Δηιμιουργία Μεταγλωττίσεων"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Εξάγετε διάλογο"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Έλεγχος σεναρίου κώδικα για πιθανά προβλήματα..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Διαγράφονται τα επιμένοντα δεδομένα..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Ξαναγίνεται μεταγλώττιση όλων των αρχείων rpy σε αρχεία rpc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "ΟΝΟΜΑ ΕΡΓΟΥ"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Παρακαλώ εισάγετε το όνομα του έργου σας:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Το όνομα του έργου δε πρέπει να είναι κενό."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "Το έργο [project_name!q] υπάρχει ήδη. Παρακαλούμε επιλέξτε άλλο όνομα για το έργο σας."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "Ο φάκελος [project_name!q] υπάρχει ήδη. Παρακαλούμε επιλέξτε άλλο όνομα για το έργο σας."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Τεκμηρίωση"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ο ιστότοπος της Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Λίστα παιχνιδιών Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "ενημέρωση"
+
+    # interface.rpy:119
+    old "preferences"
+    new "επιλογές"
+
+    # interface.rpy:120
+    old "quit"
+    new "έξοδος"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Λόγω περιορισμών στη μορφή πακεταρίσματος, δεν επιτρέπεται να δώσετε χαρακτήρες που να μην ανήκουν στον ASCII σε ονομασίες αρχείων ή φακέλων."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ΣΦΑΛΜΑ"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Ενόσω [what!q], συνέβη ένα σφάλμα:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Το κείμενο που εισάγετε δε πρέπει να εμπεριέχει τους χαρακτήρες {{ ή [[ "
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Ονόματα αρχείων και φακέλων δε πρέπει να περιέχουν τους χαρακτήρες / ή \\"
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Όνόματα αρχείων και φακέλων πρέπει να αποτελούνται μόνο από χαρακτήρες ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "ΓΙΝΕΤΑΙ ΕΠΕΞΕΡΓΑΣΙΑ"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "ΕΡΩΤΗΣΗ"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "ΕΠΙΛΟΓΗ"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Για να χτίσετε πακέτα iOS, παρακαλώ κατεβάστε το renios, αποσυμπιέστε το και τοποθετήστε το στο φάκελο της Ren'Py. Κατόπιν επανεκκινήστε τον εκκινητή."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Ο φάκελος στον οποίο θα τοποθετηθούν τα τα Xcode έργα, δεν έχει επιλεχτεί ακόμα. Ζρησιμοποιήστε το 'Επιλογή φακέλου' για να το επιλέξετε. "
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "Δεν υπάρχει έργο Xcode που να ανταποκρίνεται στο συγκεκριμένο έργο Ren'Py. Επιλέξτε 'Δημιουργήστε έργο Xcode' για να δημιουργήσετε ένα. "
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Ένα αντίστοιχο έγο Xcode υπάρχει. Επιλέξτε 'Ενημέρωση του έργου Xcode' για να το ενημερώσετε με τα μεγαλύτερα αρχεία παιχνιδιού ή χρησιμοποιήστε το Xcode για να το χτίσετε κι εγκαταστήσετε."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Απόπειρα εξομοίωσης ενός iPhone.\n\nΗ είσοδος δεδομένων αφής προσομοιώνεται με το ποντίκη, αλλά μόνο όταν κρατείται πατημένο το αριστερό κουμπί."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Απόπειρα εξομοίωσης ενός iPad.\n\nΗ είσοδος δεδομένων αφής προσομοιώνεται με το ποντίκη, αλλά μόνο όταν κρατείται πατημένο το αριστερό κουμπί."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Επιλέγει το φάκελο που θα τοποθετηθούν τα έργα Xcode."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Δημιουργεί ένα Xcode έργο που ανταποκρίνεται στο τρέχον έργο της Ren'Py."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Ενημερώνει το έργο Xcode με τα νεώτερα αρχεία του παιχνιδιού. Αυτό πρέπει να γίνεται κάθε φορά που ένα έργο Ren'Py αλλάζει."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Ανοίγει ένα έργο Xcode στο Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Ανοίγει το φάκελο που περιέχει τα έργα Xcode."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "To έργο Xcode υπάρχει ήδη. Θέλετε να μετονομάσουμε το παλιό έργο και να το αντικαταστήσουμε με ένα νέο;"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Επιλέξτε τον φάκελο που περιέχει τα έργα Xcode"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Δημιουργήστε έργο Xcode"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Ενημέρωση του έργου Xcode"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Εκτέλεση του Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Άνοιξε το φάκελο που περιέχει τα Xcode έργα"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Πριν πακετάρετε iOS εφαρμογές, θα πρέπει να κατεβάσετε το renios, ακρωνύμιο Ren'Py's iΟs Support. Θέλετε να κατεβάσετε το renios τώρα;"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "ΦΑΚΕΛΟΣ ΕΡΓΩΝ XCODE"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Παρακαλώ επιλέξτε το φάκελο που θα περιέχει τα έργα Xcode, χρησιμοποιώντας τον επιλογέα φακέλου.\n{b}Ο επιλογέας ίσως είναι ήδη ανοικτός πίσω απ' αυτό το παράθυρο.{/b} "
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Η Ren'Py έθεσε ως φάκελο έργων Xcode τον:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Περιήγηση: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Σειρά: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "αλφαβητική"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "βάσει-αρχείου"
+
+    # navigation.rpy:182
+    old "natural"
+    new "φυσιολογική"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Κατηγορία:"
+
+    # navigation.rpy:196
+    old "files"
+    new "αρχεία"
+
+    # navigation.rpy:197
+    old "labels"
+    new "ετικέτες "
+
+    # navigation.rpy:198
+    old "defines"
+    new "ορισμοί"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "μετασχηματισμοί"
+
+    # navigation.rpy:200
+    old "screens"
+    new "οθόνες"
+
+    # navigation.rpy:201
+    old "callables"
+    new "καλούμενα"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODOs"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Προσθήκη αρχείου σεναρίου κώδικα"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Δε βρέθηκε σχόλιο TODO.\n\nΓια να δημιουργήσετε ένα προσθέστε \"# TODO\" στον κώδικά σας."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Η λίστα ονομάτων είναι άδεια."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Ήταν αδύνατον να οριστεί ο φάκελος του έργου. Ματαιώνεται η πράξη."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Επιλέξτε Μορτίβο Έργου"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Παρακαλώ επιλέξτε ένα μοτίβο, για να το εφαρμόσετε στο έργο σας. Το μοτίβο θέτει βασική γραμματοσειρά και τη γλώσσα του περιβάλλοντος χρήστη. Αν δεν υποστηρίζεται η γλώσσα σας, επιλέξτε 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Επιλογές Εκκινητή"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Φάκελος έργων:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Φάκελος έργων: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Δεν έχει ορισθέι"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Επεξεργαστής κειμένου:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Επεξεργαστής κειμένου: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Ενημέρωση καναλιού:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Επιλογές πλοήγησης:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Συμπερίληψη ιδιωτικών ονομάτων"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Συμπερίληψη ονομάτων βιβλιοθηκών"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Επιλογές Εκκινητή:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Κατασκευή γραφικών από το hardware."
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Εμφάνιση μοτίβων"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Εμφάνιση μέρους επεξεργασίας αρχείου"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Μεγάλο μέγεθος γραμματοσειράς"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Έξοδος κονσόλας"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Άνοιξε το έργο Εκκινητής"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Γλώσσα:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Μετά τις αλλαγές στον κώδικα του σεναρίου, πατήστε shift+R για να φορτώσετε εκ νέου το παιχνίδι."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Πατήστε shift+O (το γράμμα) για να ανοίξετε την κονσόλα."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Πατήστε shift+D για να ανοίξετε το Μενού Δημιουργού."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Κάνατε αντίγραφο ασφαλείας των έργων σας πρόσφατα;"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Αποτυχία εκκίνησης του έργου."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Παρακαλούμε σιγουρευτείτε πως το έργο εκκινείται φυσιολογικά, προτού εκτελέσετε αυτή την εντολή."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Η Ren'Py αναζητάει έργα..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Εκκίνηση"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "ΦΑΚΕΛΟΣ ΕΡΓΩΝ"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Παρακαλώ επιλέξτε το φάκελο έργων, χρησιμοποιώντας τον επιλογέα φακέλου.\n{b}Ο επιλογέας φακέλου ίσως έχει ανοίξει πίσω από αυτό το παράθυρο.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Αυτός ο εκκινητής θα ψάξει για έργα σε αυτό το φάκελο, θα δημιουργεί νέα έργα σε αυτό τον φάκελο και θα τοποθετεί χτισμένα έργα σε αυτό το φάκελο."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Η Ren'Py όρισε τον φάκελο έργων το φάκελο:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Δημιουργία κενής συμβολοσειράς για μεταφράσεις"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Η Ren'Py δημιουργεί αρχεία μεταγλωττίσεων..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Η Ren'Py ολοκλήρωσε τη δημιουργία αρχείων μεταγλώττισης για τη γλώσσα [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Εξαγωγή διαλόγου: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Μορφή:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Χωρισμένο με Tab φύλλο εργασίας (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Διάλογος σε απλή μορφή κειμένου (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Αφαίρεση tags από το κείμενο διαλόγου."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Ειδικοί χαρακτήρες."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Εξαγωγή όλων των μεταφράσιμων συμβολοσειρών, όχι μόνο το διάλογο."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Η Ren'Py εξάγει το διάλογο...."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Η Ren'Py ολοκλήρωσε την εξαγωγή του διλόγου. Ο διάλογος μπορεί να βρεθεί στο: dialogue.[persistent.dialogue_format] εντός του κεντρικού φακέλου του παιχνιδιού."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Επιλέξτε κανάλι ενημέρωσης:"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Το κανάλι ενημέρωσης ελέγχει την έκδοση της Ren'Py που ο ενημερωτής θα κατεβάσει. Παρακαλώ επιλέξτε ένα κανάλι ενημέρωσης:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Κύρια Έκδοση"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Αυτή που συνιστάται.{/b} Η έκδοση της Ren'Py που θα έπρεπε να χρησιμοποιούν όλα τα νέα παιχνίδια που δημιουργούνται."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Ακυκλοφόρητη"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Μια εικόνα της επόμενης έκδοσης της Ren'Py η οποία μπορεί να χρησιμοποιηθεί για ελέγχους και για το πλεονέκτημα χρήσης των νέων λειτουργιών. Δε συνιστάται για τελικές εκδόσεις παιχνιδιών."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Πειραματική"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Η Πειραματική έκδοση της Ren'Py. Μην επιλέξετε το κανάλι αυτό, εκτός κι αν κάποιος εκ των δημιουργών της σας το ζητήσει."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Καθεβραδυνή"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Η απόλυτη νεώτερη έκδοση της Ren'Py. Μπορεί να έχει τα πιο νέα χαρακτηριστικά, αλλά να μη μπορέι καν να φορτώσει."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Ένα σφάλμα συνέβη:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Έλεγχος για διαθέσιμες ενημερώσεις"
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Η Ren'Py είναι ενημερωμένη."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new " Η έκδοση [u.version] είναι διαθέσιμη. Θέλετε να την εγκαταστήσετε;"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Ετοιμάζεται το κατέβασμα της ενημέρωσης."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Η ενημέρωση κατεβαίνει."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Ξεπακετάρεται η ενημέρωση."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Ολοκληρώνεται η ενημέρωση."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Η ενημέρωση εγκαταστήθηκε επιτυχώς. Η Ren'Py θα επανεκκινηθεί."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Η ενημέρωση εγκαταστήθηκε."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Η ενημέρωση ματαιώθηκε."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ενημέρωση Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Συνέχισε"
+
diff --git a/launcher/game/tl/greek/mobilebuild.rpy b/launcher/game/tl/greek/mobilebuild.rpy
deleted file mode 100644
index 3c8448c..0000000
--- a/launcher/game/tl/greek/mobilebuild.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate none strings:
-
-    # game/mobilebuild.rpy:109
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
diff --git a/launcher/game/tl/greek/navigation.rpy b/launcher/game/tl/greek/navigation.rpy
deleted file mode 100644
index 6ddf729..0000000
--- a/launcher/game/tl/greek/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate greek strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "Περιήγηση: [project.current.name]"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "Σειρά: "
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "αλφαβητική"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "βάσει-αρχείου"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "φυσιολογική"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "Κατηγορία:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "αρχεία"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "ετικέτες "
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "ορισμοί"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "μετασχηματισμοί"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "οθόνες"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "καλούμενα"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "TODOs"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ Προσθήκη αρχείου σεναρίου κώδικα"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Δε βρέθηκε σχόλιο TODO.\n\nΓια να δημιουργήσετε ένα προσθέστε \"# TODO\" στον κώδικά σας."
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "Η λίστα ονομάτων είναι άδεια."
-
diff --git a/launcher/game/tl/greek/new_project.rpy b/launcher/game/tl/greek/new_project.rpy
deleted file mode 100644
index 8483dd9..0000000
--- a/launcher/game/tl/greek/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate greek strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "Επιλέξτε Μορτίβο Έργου"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Παρακαλώ επιλέξτε ένα μοτίβο, για να το εφαρμόσετε στο έργο σας. Το μοτίβο θέτει βασική γραμματοσειρά και τη γλώσσα του περιβάλλοντος χρήστη. Αν δεν υποστηρίζεται η γλώσσα σας, επιλέξτε 'english'."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Ήταν αδύνατον να οριστεί ο φάκελος του έργου. Ματαιώνεται η πράξη."
-
-    # game/new_project.rpy:75
-    old "PROJECT NAME"
-    new "ΟΝΟΜΑ ΕΡΓΟΥ"
-
-    # game/new_project.rpy:75
-    old "Please enter the name of your project:"
-    new "Παρακαλώ εισάγετε το όνομα του έργου σας:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "Το όνομα του έργου δε πρέπει να είναι κενό."
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "Το έργο [project_name!q] υπάρχει ήδη. Παρακαλούμε επιλέξτε άλλο όνομα για το έργο σας."
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "Ο φάκελος [project_name!q] υπάρχει ήδη. Παρακαλούμε επιλέξτε άλλο όνομα για το έργο σας."
-
diff --git a/launcher/game/tl/greek/obsolete.rpy b/launcher/game/tl/greek/obsolete.rpy
new file mode 100644
index 0000000..965bec9
--- /dev/null
+++ b/launcher/game/tl/greek/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate greek strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Ρύθμισης χειριστηρίου joystick"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Άδεια θυρίδα."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Προηγούμενο"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Επόμενο"
+
diff --git a/launcher/game/tl/greek/options.rpy b/launcher/game/tl/greek/options.rpy
new file mode 100644
index 0000000..6fa273c
--- /dev/null
+++ b/launcher/game/tl/greek/options.rpy
@@ -0,0 +1,195 @@
+
+translate greek strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/greek/preferences.rpy b/launcher/game/tl/greek/preferences.rpy
deleted file mode 100644
index 4102c2d..0000000
--- a/launcher/game/tl/greek/preferences.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate greek strings:
-
-    # game/preferences.rpy:64
-    old "Launcher Preferences"
-    new "Επιλογές Εκκινητή"
-
-    # game/preferences.rpy:85
-    old "Projects Directory:"
-    new "Φάκελος έργων:"
-
-    # game/preferences.rpy:92
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:94
-    old "Projects directory: [text]"
-    new "Φάκελος έργων: [text]"
-
-    # game/preferences.rpy:96
-    old "Not Set"
-    new "Δεν έχει ορισθέι"
-
-    # game/preferences.rpy:111
-    old "Text Editor:"
-    new "Επεξεργαστής κειμένου:"
-
-    # game/preferences.rpy:117
-    old "Text editor: [text]"
-    new "Επεξεργαστής κειμένου: [text]"
-
-    # game/preferences.rpy:133
-    old "Update Channel:"
-    new "Ενημέρωση καναλιού:"
-
-    # game/preferences.rpy:153
-    old "Navigation Options:"
-    new "Επιλογές πλοήγησης:"
-
-    # game/preferences.rpy:157
-    old "Include private names"
-    new "Συμπερίληψη ιδιωτικών ονομάτων"
-
-    # game/preferences.rpy:158
-    old "Include library names"
-    new "Συμπερίληψη ονομάτων βιβλιοθηκών"
-
-    # game/preferences.rpy:168
-    old "Launcher Options:"
-    new "Επιλογές Εκκινητή:"
-
-    # game/preferences.rpy:172
-    old "Hardware rendering"
-    new "Κατασκευή γραφικών από το hardware."
-
-    # game/preferences.rpy:173
-    old "Show templates"
-    new "Εμφάνιση μοτίβων"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "Εμφάνιση μέρους επεξεργασίας αρχείου"
-
-    # game/preferences.rpy:175
-    old "Large fonts"
-    new "Μεγάλο μέγεθος γραμματοσειράς"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "Δημιουργία κενής συμβολοσειράς για μεταφράσεις"
-
-    # game/preferences.rpy:179
-    old "Console output"
-    new "Έξοδος κονσόλας"
-
-    # game/preferences.rpy:200
-    old "Open launcher project"
-    new "Άνοιξε το έργο Εκκινητής"
-
-    # game/preferences.rpy:214
-    old "Language:"
-    new "Γλώσσα:"
-
diff --git a/launcher/game/tl/greek/project.rpy b/launcher/game/tl/greek/project.rpy
deleted file mode 100644
index f223e65..0000000
--- a/launcher/game/tl/greek/project.rpy
+++ /dev/null
@@ -1,51 +0,0 @@
-
-translate greek strings:
-
-    # game/project.rpy:47
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Μετά τις αλλαγές στον κώδικα του σεναρίου, πατήστε shift+R για να φορτώσετε εκ νέου το παιχνίδι."
-
-    # game/project.rpy:47
-    old "Press shift+O (the letter) to access the console."
-    new "Πατήστε shift+O (το γράμμα) για να ανοίξετε την κονσόλα."
-
-    # game/project.rpy:47
-    old "Press shift+D to access the developer menu."
-    new "Πατήστε shift+D για να ανοίξετε το Μενού Δημιουργού."
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "Κάνατε αντίγραφο ασφαλείας των έργων σας πρόσφατα;"
-
-    # game/project.rpy:225
-    old "Launching the project failed."
-    new "Αποτυχία εκκίνησης του έργου."
-
-    # game/project.rpy:225
-    old "Please ensure that your project launches normally before running this command."
-    new "Παρακαλούμε σιγουρευτείτε πως το έργο εκκινείται φυσιολογικά, προτού εκτελέσετε αυτή την εντολή."
-
-    # game/project.rpy:238
-    old "Ren'Py is scanning the project..."
-    new "Η Ren'Py αναζητάει έργα..."
-
-    # game/project.rpy:530
-    old "Launching"
-    new "Εκκίνηση"
-
-    # game/project.rpy:559
-    old "PROJECTS DIRECTORY"
-    new "ΦΑΚΕΛΟΣ ΕΡΓΩΝ"
-
-    # game/project.rpy:559
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Παρακαλώ επιλέξτε το φάκελο έργων, χρησιμοποιώντας τον επιλογέα φακέλου.\n{b}Ο επιλογέας φακέλου ίσως έχει ανοίξει πίσω από αυτό το παράθυρο.{/b}"
-
-    # game/project.rpy:559
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Αυτός ο εκκινητής θα ψάξει για έργα σε αυτό το φάκελο, θα δημιουργεί νέα έργα σε αυτό τον φάκελο και θα τοποθετεί χτισμένα έργα σε αυτό το φάκελο."
-
-    # game/project.rpy:564
-    old "Ren'Py has set the projects directory to:"
-    new "Η Ren'Py όρισε τον φάκελο έργων το φάκελο:"
-
diff --git a/launcher/game/tl/greek/screens.rpy b/launcher/game/tl/greek/screens.rpy
new file mode 100644
index 0000000..b4a24ce
--- /dev/null
+++ b/launcher/game/tl/greek/screens.rpy
@@ -0,0 +1,643 @@
+
+translate greek strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Πίσω"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Skip"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Save"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.Save"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.Load"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Preferences"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Main Menu"
+
+    # screens.rpy:328
+    old "About"
+    new "Περί"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Help"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Έξοδος"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Επιστροφή"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Εμφάνιση"
+
+    # screens.rpy:739
+    old "Window"
+    new "Παράθυρο"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Πλήρης οθόνη"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Απενεργοποιημένο"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "After Choices"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transitions"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Text Speed"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Auto-Forward Time"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Music Volume"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Ένταση ήχου"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Voice Volume"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Ρύθμισε"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Ναι"
+
+    # screens.rpy:1162
+    old "No"
+    new "Όχι"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/greek/style.rpy b/launcher/game/tl/greek/style.rpy
index 1570e12..e02abfc 100644
--- a/launcher/game/tl/greek/style.rpy
+++ b/launcher/game/tl/greek/style.rpy
@@ -1,2 +1 @@
-translate greek python:
-    make_style_backup()
+
diff --git a/launcher/game/tl/greek/translations.rpy b/launcher/game/tl/greek/translations.rpy
deleted file mode 100644
index c283b5d..0000000
--- a/launcher/game/tl/greek/translations.rpy
+++ /dev/null
@@ -1,58 +0,0 @@
-
-translate greek strings:
-
-    # game/translations.rpy:34
-    old "Create or Update Translations"
-    new "Δημιουργία ή ενημέρωση μεταγλωττίσεων"
-
-    # game/translations.rpy:34
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Παρακαλώ δώστε την ονομασία της γλώσσας που θέλετε να δημιουργήσετε ή να ενημερώσετε μεταγλωττίσεις."
-
-    # game/translations.rpy:39
-    old "The language name can not be the empty string."
-    new "Το όνομα γλώσσας δε μπορεί να είναι κενή συμβολοσειρά."
-
-    # game/translations.rpy:50
-    old "Ren'Py is generating translations...."
-    new "Η Ren'Py δημιουργεί αρχεία μεταγλωττίσεων..."
-
-    # game/translations.rpy:54
-    old "Ren'Py has finished generating [language] translations."
-    new "Η Ren'Py ολοκλήρωσε τη δημιουργία αρχείων μεταγλώττισης για τη γλώσσα [language]."
-
-    # game/translations.rpy:68
-    old "Extract Dialogue: [project.current.name!q]"
-    new "Εξαγωγή διαλόγου: [project.current.name!q]"
-
-    # game/translations.rpy:84
-    old "Format:"
-    new "Μορφή:"
-
-    # game/translations.rpy:92
-    old "Tab-delimited Spreadsheet (dialogue.tab)"
-    new "Χωρισμένο με Tab φύλλο εργασίας (dialogue.tab)"
-
-    # game/translations.rpy:93
-    old "Dialogue Text Only (dialogue.txt)"
-    new "Διάλογος σε απλή μορφή κειμένου (dialogue.txt)"
-
-    # game/translations.rpy:106
-    old "Strip text tags from the dialogue."
-    new "Αφαίρεση tags από το κείμενο διαλόγου."
-
-    # game/translations.rpy:107
-    old "Escape quotes and other special characters."
-    new "Ειδικοί χαρακτήρες."
-
-    # game/translations.rpy:108
-    old "Extract all translatable strings, not just dialogue."
-    new "Εξαγωγή όλων των μεταφράσιμων συμβολοσειρών, όχι μόνο το διάλογο."
-
-    # game/translations.rpy:136
-    old "Ren'Py is extracting dialogue...."
-    new "Η Ren'Py εξάγει το διάλογο...."
-
-    # game/translations.rpy:140
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
-    new "Η Ren'Py ολοκλήρωσε την εξαγωγή του διλόγου. Ο διάλογος μπορεί να βρεθεί στο: dialogue.[persistent.dialogue_format] εντός του κεντρικού φακέλου του παιχνιδιού."
diff --git a/launcher/game/tl/greek/updater.rpy b/launcher/game/tl/greek/updater.rpy
deleted file mode 100644
index 38b42db..0000000
--- a/launcher/game/tl/greek/updater.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-
-translate greek strings:
-
-    # game/updater.rpy:75
-    old "Select Update Channel"
-    new "Επιλέξτε κανάλι ενημέρωσης:"
-
-    # game/updater.rpy:86
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Το κανάλι ενημέρωσης ελέγχει την έκδοση της Ren'Py που ο ενημερωτής θα κατεβάσει. Παρακαλώ επιλέξτε ένα κανάλι ενημέρωσης:"
-
-    # game/updater.rpy:91
-    old "Release"
-    new "Κύρια Έκδοση"
-
-    # game/updater.rpy:97
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Αυτή που συνιστάται.{/b} Η έκδοση της Ren'Py που θα έπρεπε να χρησιμοποιούν όλα τα νέα παιχνίδια που δημιουργούνται."
-
-    # game/updater.rpy:102
-    old "Prerelease"
-    new "Ακυκλοφόρητη"
-
-    # game/updater.rpy:108
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Μια εικόνα της επόμενης έκδοσης της Ren'Py η οποία μπορεί να χρησιμοποιηθεί για ελέγχους και για το πλεονέκτημα χρήσης των νέων λειτουργιών. Δε συνιστάται για τελικές εκδόσεις παιχνιδιών."
-
-    # game/updater.rpy:114
-    old "Experimental"
-    new "Πειραματική"
-
-    # game/updater.rpy:120
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Η Πειραματική έκδοση της Ren'Py. Μην επιλέξετε το κανάλι αυτό, εκτός κι αν κάποιος εκ των δημιουργών της σας το ζητήσει."
-
-    # game/updater.rpy:126
-    old "Nightly"
-    new "Καθεβραδυνή"
-
-    # game/updater.rpy:132
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Η απόλυτη νεώτερη έκδοση της Ren'Py. Μπορεί να έχει τα πιο νέα χαρακτηριστικά, αλλά να μη μπορέι καν να φορτώσει."
-
-    # game/updater.rpy:152
-    old "An error has occured:"
-    new "Ένα σφάλμα συνέβη:"
-
-    # game/updater.rpy:154
-    old "Checking for updates."
-    new "Έλεγχος για διαθέσιμες ενημερώσεις"
-
-    # game/updater.rpy:156
-    old "Ren'Py is up to date."
-    new "Η Ren'Py είναι ενημερωμένη."
-
-    # game/updater.rpy:158
-    old "[u.version] is now available. Do you want to install it?"
-    new " Η έκδοση [u.version] είναι διαθέσιμη. Θέλετε να την εγκαταστήσετε;"
-
-    # game/updater.rpy:160
-    old "Preparing to download the update."
-    new "Ετοιμάζεται το κατέβασμα της ενημέρωσης."
-
-    # game/updater.rpy:162
-    old "Downloading the update."
-    new "Η ενημέρωση κατεβαίνει."
-
-    # game/updater.rpy:164
-    old "Unpacking the update."
-    new "Ξεπακετάρεται η ενημέρωση."
-
-    # game/updater.rpy:166
-    old "Finishing up."
-    new "Ολοκληρώνεται η ενημέρωση."
-
-    # game/updater.rpy:168
-    old "The update has been installed. Ren'Py will restart."
-    new "Η ενημέρωση εγκαταστήθηκε επιτυχώς. Η Ren'Py θα επανεκκινηθεί."
-
-    # game/updater.rpy:170
-    old "The update has been installed."
-    new "Η ενημέρωση εγκαταστήθηκε."
-
-    # game/updater.rpy:172
-    old "The update was cancelled."
-    new "Η ενημέρωση ματαιώθηκε."
-
-    # game/updater.rpy:189
-    old "Ren'Py Update"
-    new "Ενημέρωση Ren'Py"
-
-    # game/updater.rpy:195
-    old "Proceed"
-    new "Συνέχισε"
-
diff --git a/launcher/game/tl/indonesian/about.rpy b/launcher/game/tl/indonesian/about.rpy
deleted file mode 100644
index 208d7e2..0000000
--- a/launcher/game/tl/indonesian/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate indonesian strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "Lihat Lisensi"
-
-    # game/about.rpy:27
-    old "Back"
-    new "Kembali"
-
diff --git a/launcher/game/tl/indonesian/add_file.rpy b/launcher/game/tl/indonesian/add_file.rpy
deleted file mode 100644
index 8c5e4ec..0000000
--- a/launcher/game/tl/indonesian/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate indonesian strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "NAMAFILE"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Masukkan nama script file yang akan di buat"
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "Nama file harus memlikili extensi .rpy"
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "File sudah ada"
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'py secara otomatis meload semua script dengan akhiran .rpy. Untuk menggunakan\n# file ini, silahkan define label dan jump ke file itu dari file lain.\n"
-
diff --git a/launcher/game/tl/indonesian/android.rpy b/launcher/game/tl/indonesian/android.rpy
deleted file mode 100644
index fc3978d..0000000
--- a/launcher/game/tl/indonesian/android.rpy
+++ /dev/null
@@ -1,204 +0,0 @@
-
-translate indonesian strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Untuk membuat package android, silahkan download RAPT (dari {a=http://www.renpy.org/dl/android}here{/a}), silahkan unzip/extrak, lalu taruh di direktori Ren'Py, Dan restart launcher Ren'Py."
-
-    # game/android.rpy:13
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT sudah terinstall, tapi kamu harus menginstall Android SDK sebelum kamu dapat membuat package Android. Untuk Melakukan Ini Pilih Install SDK"
-
-    # game/android.rpy:14
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT sudah terinstall, tapi kunci/key belum di configurasi. Silahkan buat kunci/key baru, atau restore android.keystore"
-
-    # game/android.rpy:15
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Projek ini belum di configurasi. Gunakan \"Konfigurasi\" untuk mengkonfigurasi sebelum membuat build."
-
-    # game/android.rpy:16
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Pilih \"Build\" untuk membuild projek ini, atau koneksikan perangkat Android dan pilih \"Buat & Install\" untuk membuild dan install pada perangkat."
-
-    # game/android.rpy:18
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Mencoba untuk mengemulasi perangkat Android.\n\nInput sentuhan di emulasikan melalui mouse, tapi hanya ketika tombol di tahan. Escape di mapped ke tombol menu, dan PageUp di mapped ke tombol back."
-
-    # game/android.rpy:19
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Mencoba untuk mengemulasi tablet Android.\n\nInput sentuhan di emulasikan melalui mouse, tapi hanya ketika tombol di tahan. Escape di mapped ke tombol menu, dan PageUp di mapped ke tombol back."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Mencoba untuk mengemulasi konsol OUYA.\n\nInput Kontroller di map ke tombol panah, Enter di map ke tombol select, Escape di map ke tombol menu, dan PageUp di map ke tombol back."
-
-    # game/android.rpy:22
-    old "Downloads and installs the Android SDK and supporting packages. Opsional, menghasilkan kunci yang diperlukan untuk menandatangani paket."
-    new "Download dan install Android SDK dan package pendukung. Menggenerate "
-
-    # game/android.rpy:23
-    old "Configures the package name, version, and other information about this project."
-    new "Konfigurasi nama package, versi, dan informasi lainnya mengenai project ini."
-
-    # game/android.rpy:24
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Buka file yang berisi Google Play keys di editor. \n\n Ini hanya di butuhkan juka aplikasi menggunakan expansi APK. Baca dokumentasi untuk detail lebih lanjut"
-
-    # game/android.rpy:25
-    old "Builds the Android package."
-    new "Bangun package Android."
-
-    # game/android.rpy:26
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Build package Android, dan install di perangkat Android yang terkoneksi ke komputer mu."
-
-    # game/android.rpy:142
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:361
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:381
-    old "Emulation:"
-    new "Emulasi:"
-
-    # game/android.rpy:389
-    old "Phone"
-    new "Telepon"
-
-    # game/android.rpy:393
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:397
-    old "Television / OUYA"
-    new "Televisi/ OUYA"
-
-    # game/android.rpy:409
-    old "Build:"
-    new "Build:"
-
-    # game/android.rpy:417
-    old "Install SDK & Create Keys"
-    new "Install SDK & Buat Keys"
-
-    # game/android.rpy:421
-    old "Configure"
-    new "Konfigurasi"
-
-    # game/android.rpy:425
-    old "Build Package"
-    new "Buat package"
-
-    # game/android.rpy:429
-    old "Build & Install"
-    new "Buat & Install"
-
-
-translate indonesian strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Untuk membuat package Android, silahkan download RAPT, unzip/extrak, dan taruh di direktori Ren,Py. Dan restart launcher Ren'Py."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Java Development Kit 32-bit di perlukan untuk membuat package Android di Windows, JDK itu berbeda dari JRE, jadi sangat mungkin kamu memiliki java tanpa JDK\n\nTolong {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Download dan install JDK{/a}, lalu restart launcher Ren'Py "
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Mencoba mengemulasi konsol televisi Android, Seperti OUYA atau Fire TV.\n\nInput kontroller di map ke tombol panah, Enter di map ke tombol select, Escape di map ke tombol menu, dan PageUp di map ke tombol back"
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Sambungkan ke perangkat Android yang memiliki ADB berjalan di mode TCP/IP"
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Putuskan hubungan dari perangkat Android yang menjalankan ADB di mode TCP/IP"
-
-    # game/android.rpy:516
-    old "Other:"
-    new "Lainnya:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "Koneksi remote ADB"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "Putus remote ADB"
-
-    # game/android.rpy:561
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Sebelum mempackage aplikasi Android, kamu harus mendownload RAPT, Ren'Py Android Packaging Tool. Maukah kamu mendownload RAPT sekarang?"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "Alamat remote ADB"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Tolong masukkan alamat IP dan nomor port untuk menyambung, dalam bentuk \"192.168.1.143:5555\". Silahkan lihat dokumentasi perangkat anda untuk memastikan apakah mendukung remote ADB, dan jika mendukung, alamat dan port untuk menggunakan."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "Alamat remote ADB invalid"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "Alamat hanya boleh mengandung 1 ':'."
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "Host seharus nya tidak mengandung spasi."
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "Port harus berisi angka."
-
-
-translate indonesian strings:
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Buat package Android, Install di perangkat Android yang terkoneksi ke komputer, dan menjalankan aplikasi pada perangkat mu."
-
-    # game/android.rpy:290
-    old "Television"
-    new "Televisi"
-
-    # game/android.rpy:326
-    old "Build, Install & Launch"
-    new "Buat, Install & Jalankan"
-
-
-translate indonesian strings:
-
-    # game/android.rpy:50
-    old "Retrieves the log from the Android device and writes it to a file."
-    new "Ambil log dari perangkat Android dan menulist nya ke file."
-
-    # game/android.rpy:240
-    old "Copying Android files to distributions directory."
-    new "Mengcopy file Android ke direktori distribusi."
-
-    # game/android.rpy:404
-    old "Logcat"
-    new "Logcat"
-
-    # game/android.rpy:538
-    old "Retrieving logcat information from device."
-    new "Mendapatkan informasi logcat dari perangkat."
-
-
-
-translate indonesian strings:
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Download dan pasang Android SDK dan paket pendukung. Opsional, mengenerate key/kunci yang di butuhkan untuk menandatangani paket."
-
diff --git a/launcher/game/tl/indonesian/choose_directory.rpy b/launcher/game/tl/indonesian/choose_directory.rpy
deleted file mode 100644
index 2455b16..0000000
--- a/launcher/game/tl/indonesian/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate indonesian strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py tidak bisa menjalankan python dengan tkinter untuk memilih direktori. Tolong install python-tk atau tkinter package."
-
diff --git a/launcher/game/tl/indonesian/choose_theme.rpy b/launcher/game/tl/indonesian/choose_theme.rpy
deleted file mode 100644
index 53296c6..0000000
--- a/launcher/game/tl/indonesian/choose_theme.rpy
+++ /dev/null
@@ -1,44 +0,0 @@
-
-translate indonesian strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Tidak bisa mengganti tema. Mungkin options.rpy di ubah terlalu banyak."
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Tampilam"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Window"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Layar Penuh"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Volume Suara"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Pilih Tema"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "Tema"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "Pilih Skema"
-
-    # game/choose_theme.rpy:444
-    old "Continue"
-    new "Lanjutkan"
-
-
diff --git a/launcher/game/tl/indonesian/common.rpy b/launcher/game/tl/indonesian/common.rpy
index ad00b73..0d32456 100644
--- a/launcher/game/tl/indonesian/common.rpy
+++ b/launcher/game/tl/indonesian/common.rpy
@@ -1,845 +1,335 @@
 
 translate indonesian strings:
 
-    # renpy/common/00action_file.rpy:118
-    old "%b %d, %H:%M"
-    new "%b %d, %H:%M"
-
-
-translate indonesian strings:
-
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Akselerasi Grafis"
-
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Pilih Otomatis"
-
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Paksakan Renderer Angle/DirectX"
-
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "Paksakan Renderer OpenGL"
-
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Paksakan Renderer software"
-
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Perubahan akan memberikan efek, saat program di jalankan lagi nanti."
-
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "Keluar"
-
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Kembali"
-
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Peringatan Performa"
-
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Komputer ini menggunakan rendering software."
-
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Komputer ini tidak menggunakan shaders."
-
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Komputer ini menampilkan grafis dengan lambat."
-
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Komputer ini mengalami masalah saat menampilkan grafis: [problem]"
-
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Driver grafis mungkin sudah ketinggalan jaman atau tidak berkerja dengan benar.\nIni dapat menyebabkan komputer lambat bahkan tidak akurat dalam menampilkan grafis,\nMengupdate DirectX dapat memperbaiki masalah ini."
-
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Driver grafis mungkin sudah ketinggalan jaman atau tidak berkerja dengan benar.\nIni dapat menyebabkan komputer lambat bahkan tidak akurat dalam menampilkan grafis."
-
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "Update DirectX"
-
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Lanjutkan, Tampilkan peringatan ini lagi"
-
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Lanjutkan, Jangan tampilkan peringatan ini lagi"
-
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "Mengupdate DirectX."
-
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "DirectX web setup telah di jalankan. Mungkin akan berjalan dengan mode minimized di taskbar.\nSilahkan ikuti instruksi untuk memasang DirectX."
-
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Catatan:{/b} Program Microsoft's DirectX web setup, secara default akan memasang toolbar Bing.\nJika kamu tidak mengigini toolbar ini, silahkan uncheck box yang bersangkutan."
-
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "Ketik setup selesai, silahkan klik tombol di bawah untuk me restart program ini."
-
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Restart"
-
-
-translate indonesian strings:
-
-    # renpy/common/00keymap.rpy:167
-    old "Saved screenshot as %s."
-    new "Menyimpan screenshot sebagai %s."
-
-
-translate indonesian strings:
-
-    # renpy/common/00layout.rpy:421
-    old "Are you sure?"
-    new "Apakah kamu yakin?"
-
-    # renpy/common/00layout.rpy:422
-    old "Are you sure you want to delete this save?"
-    new "Apakah kamu yakin ingin menghapus save ini?"
-
-    # renpy/common/00layout.rpy:423
-    old "Are you sure you want to overwrite your save?"
-    new "Apakah kamu yakin ingin menimpa save ini?"
-
-    # renpy/common/00layout.rpy:424
-    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
-    new "Loading akan menghapus proses yang belum tersimpan.\nApakah kamu yakin?"
-
-    # renpy/common/00layout.rpy:425
-    old "Are you sure you want to quit?"
-    new "Apakah kamu yakin ingin keluar?"
-
-    # renpy/common/00layout.rpy:426
-    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
-    new "Apakah kamu yakin ingin kembali ke main menu?\nProgress belum tersimpan akan hilang."
-
-
-translate indonesian strings:
-
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "Mode Skip"
-
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Mode Skip Cepat"
-
-
-translate indonesian strings:
-
-    # renpy/common/00updater.rpy:1258
-    old "Updater"
-    new "Updater"
-
-    # renpy/common/00updater.rpy:1267
-    old "This program is up to date."
-    new "Program ini sudah up to date."
-
-    # renpy/common/00updater.rpy:1269
-    old "[u.version] is available. Do you want to install it?"
-    new "Versi: [u.version] sudah tersedia. Apakah kamu ingin memasang nya?"
-
-    # renpy/common/00updater.rpy:1271
-    old "Preparing to download the updates."
-    new "Bersiap untuk mendownload update."
-
-    # renpy/common/00updater.rpy:1273
-    old "Downloading the updates."
-    new "Mendownload update."
-
-    # renpy/common/00updater.rpy:1275
-    old "Unpacking the updates."
-    new "Meng unpack update."
-
-    # renpy/common/00updater.rpy:1279
-    old "The updates have been installed. The program will restart."
-    new "Update sudah terpasang. Program akan me restart."
-
-    # renpy/common/00updater.rpy:1281
-    old "The updates have been installed."
-    new "Update sudah terpasang."
-
-    # renpy/common/00updater.rpy:1283
-    old "The updates were cancelled."
-    new "Proses update di batalkan."
-
-
-translate indonesian strings:
-
-    # renpy/common/_compat/gamemenu.rpym:180
-    old "Empty Slot."
-    new "Slot Kosong"
-
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Sebelumnya"
-
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Selanjutnya"
-
-
-translate indonesian strings:
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "Mapping Joystick"
-
-
-translate indonesian strings:
-
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "Kesalahan telah terjadi."
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Rollback"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Coba untuk roll back, memungkinkan kamu untuk bisa menyimpan atau memilih pilihan yang berbeda"
-
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "Abaikan"
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Abaikan kesalahan, Memungkinkan kamu untuk melanjutkan. Biasanya ini berujung pada error yang baru."
-
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "Muat ulang"
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Muat ulang game dari harddisk, Menyimpan dan memulihkan state game jika mungkin."
-
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "Buka Traceback"
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Buka traceback.txt di text editor."
-
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "Keluar dari game."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "Gagal mengcompile script."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Buka kesalahan compile"
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Membuka errors.txt di text editor."
-
-
-translate indonesian strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
-
-
-translate indonesian strings:
-
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "Save Cepat Selesai."
-
-
-translate indonesian strings:
-
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "Gambar [index] dari [count] dikunci."
-
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "Sebelum"
-
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "Berikutnya"
-
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "Slideshow"
-
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "Kembali"
-
-
-translate indonesian strings:
-
-    # renpy/common/00layout.rpy:427
-    old "Are you sure you want to begin skipping?"
-    new "Apakah kamu yakin akan memulai skipping?"
-
-    # renpy/common/00layout.rpy:428
-    old "Are you sure you want to skip to the next choice?"
-    new "Apakah kamu yakin ingin meloncat ke pilihan berikutnya?"
-
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Apakah kamu yakin ingin melompati dialong yang\nbelum dilihat atau pilihan berikut nya?"
-
-
-translate indonesian strings:
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "consol %(version)s, dibut secara original oleh Shiz, C, dan delta.\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Tekan <esc> untuk keluar konsol. Ketik help untuk bantuan.\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "Script Ren'Py di aktifkan."
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "Script Ren'Py di matikan."
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: menampilkan bantuan"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "perintah:\n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new " <renpy script statement>: Menjalankan pernyataan\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <python expression or statement>: Menjalankan expresi atau pernyataan"
-
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: membersikan histori konsol"
-
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: keluar konsol"
-
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: load game dari slot"
-
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: simpan game di slot"
-
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: reload game, me refresh script"
-
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <expression>: lihat expresi python"
-
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expression>: berhenti melihat expresi"
-
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: berhenti melihat semua expresi"
-
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: lompat ke label"
-
-
-translate indonesian strings:
-
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "Otomatis reload"
-
-
-translate indonesian strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "Menu Pengembang"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "Reload Game (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Konsol (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "Viewer variabel"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "Test Tema"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "Pemilih LokasI Gambar"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "List Namafile"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Perlihatkan Log Load Gambar"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Sembunyikan Load Log Gambar"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "Tidak ada variabel yang di ubah sejak game di mulai."
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "Kembali ke menu pengembang"
-
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}Gambar Hilang{/b}"
-
-    # renpy/common/_developer/developer.rpym:424
-    old "Rectangle: %r"
-    new "Persegi Panjang: %r"
-
-    # renpy/common/_developer/developer.rpym:429
-    old "Mouse position: %r"
-    new "Posisi Mouse: %r"
-
-    # renpy/common/_developer/developer.rpym:431
-    old "Right-click or escape to quit."
-    new "Klik-Kanan atau escape untuk keluar."
-
-    # renpy/common/_developer/developer.rpym:482
-    old "Done"
-    new "Selesai"
-
-
-translate indonesian strings:
-
-    # renpy/common/_developer/inspector.rpym:43
-    old "Displayable Inspector"
-    new "Inspektur yang dapat di tampilkan"
-
-    # renpy/common/_developer/inspector.rpym:49
-    old "Nothing to inspect."
-    new "Tidak ada yang dapat di inspeksi"
-
-    # renpy/common/_developer/inspector.rpym:58
-    old "Size"
-    new "Ukuran"
-
-    # renpy/common/_developer/inspector.rpym:63
-    old "Style"
-    new "Gaya"
-
-    # renpy/common/_developer/inspector.rpym:123
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Menginspeksi Gaya dari [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:135
-    old "displayable:"
-    new "displayable:"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "        (no properties affect the displayable)"
-    new "        (tidak ada properti yang mempengaruhi displayable)"
-
-    # renpy/common/_developer/inspector.rpym:144
-    old "        (default properties omitted)"
-    new "        (properti default di ubah)"
-
-    # renpy/common/_developer/inspector.rpym:174
-    old "<repr() failed>"
-    new "<repr() failed>"
-
-
-translate indonesian strings:
-
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "Lokasi"
-
-
-translate indonesian strings:
-
-    # renpy/common/00preferences.rpy:387
-    old "Clipboard voicing enabled. Press 'shift+C' to disable."
-    new "Catatan pengisi suara diaktifkan, tekan 'shift+C' untuk matikan."
-
-    # renpy/common/00preferences.rpy:389
-    old "Self-voicing enabled. Press 'v' to disable."
-    new "Pengisi suara sendiri di aktifkan. Tekan 'v' untuk matikan. V"
-
-
-translate indonesian strings:
-
-    # renpy/common/00updater.rpy:362
-    old "The Ren'Py Updater is not supported on mobile devices."
-    new "Ren'Py Updater tidak di support di perangkat handphone."
-
-    # renpy/common/00updater.rpy:478
-    old "An error is being simulated."
-    new "Error sedang di simulasikan."
-
-    # renpy/common/00updater.rpy:654
-    old "Either this project does not support updating, or the update status file was deleted."
-    new "Antara proyek tidak mendukung update, atau file status update di hapus."
-
-    # renpy/common/00updater.rpy:668
-    old "This account does not have permission to perform an update."
-    new "Akun ini tidak memiliki izin untuk melakukan update."
-
-    # renpy/common/00updater.rpy:671
-    old "This account does not have permission to write the update log."
-    new "Akun ini tidak memiliki izin untuk menulis log update."
-
-    # renpy/common/00updater.rpy:696
-    old "Could not verify update signature."
-    new "Tidak dapat memverifikasi signature update."
-
-    # renpy/common/00updater.rpy:956
-    old "The update file was not downloaded."
-    new "File update tidak di download."
-
-    # renpy/common/00updater.rpy:974
-    old "The update file does not have the correct digest - it may have been corrupted."
-    new "File update tiidak memiliki digest yang benar  - mungkin file corrupt."
-
-    # renpy/common/00updater.rpy:1030
-    old "While unpacking {}, unknown type {}."
-    new "Ketika unppack {}, tipe tidak diketahui {}."
-
-
-translate indonesian strings:
-
-    # renpy/common/_developer/developer.rpym:437
-    old "Rectangle copied to clipboard."
-    new "Persegi di salin ke catatan."
-
-    # renpy/common/_developer/developer.rpym:440
-    old "Position copied to clipboard."
-    new "Posisi di salin ke catatan."
-
-
-translate indonesian strings:
-
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Monday"
     new "{#weekday}Senin"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Tuesday"
     new "{#weekday}Selasa"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Wednesday"
     new "{#weekday}Rabu"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Thursday"
     new "{#weekday}Kamis"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Friday"
     new "{#weekday}Jumat"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Saturday"
     new "{#weekday}Sabtu"
 
-    # renpy/common/00action_file.rpy:26
+    # 00action_file.rpy:26
     old "{#weekday}Sunday"
     new "{#weekday}Minggu"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Mon"
     new "{#weekday_short}Sen"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Tue"
     new "{#weekday_short}Sel"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Wed"
     new "{#weekday_short}Rab"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Thu"
     new "{#weekday_short}Kam"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Fri"
     new "{#weekday_short}Jum"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sat"
     new "{#weekday_short}Sab"
 
-    # renpy/common/00action_file.rpy:37
+    # 00action_file.rpy:37
     old "{#weekday_short}Sun"
     new "{#weekday_short}Ming"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}January"
     new "{#month}Januari"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}February"
     new "{#month}Febuari"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}March"
     new "{#month}Maret"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}April"
     new "{#month}April"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}May"
     new "{#month}Mei"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}June"
     new "{#month}Juni"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}July"
     new "{#month}Juli"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}August"
     new "{#month}Agustus"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}September"
     new "{#month}September"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}October"
     new "{#month}Oktober"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}November"
     new "{#month}November"
 
-    # renpy/common/00action_file.rpy:47
+    # 00action_file.rpy:47
     old "{#month}December"
     new "{#month}Desember"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jan"
     new "{#month_short}Jan"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Feb"
     new "{#month_short}Feb"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Mar"
     new "{#month_short}Mar"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Apr"
     new "{#month_short}Aprl"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}May"
     new "{#month_short}Mei"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jun"
     new "{#month_short}Jun"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Jul"
     new "{#month_short}Jul"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Aug"
     new "{#month_short}Agust"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Sep"
     new "{#month_short}Sep"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Oct"
     new "{#month_short}Okt"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Nov"
     new "{#month_short}Nov"
 
-    # renpy/common/00action_file.rpy:63
+    # 00action_file.rpy:63
     old "{#month_short}Dec"
     new "{#month_short}Des"
 
-    # renpy/common/00action_file.rpy:550
-    old "Page {}"
-    new "Halaman {}"
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d, %H:%M"
 
-    # renpy/common/00action_file.rpy:550
-    old "Automatic saves"
-    new "Otomatis save"
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Save Cepat Selesai."
 
-    # renpy/common/00action_file.rpy:550
-    old "Quick saves"
-    new "Save cepat"
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "Apakah kamu yakin?"
 
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "Apakah kamu yakin ingin menghapus save ini?"
 
-translate indonesian strings:
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "Apakah kamu yakin ingin menimpa save ini?"
 
-    # renpy/common/00gamepad.rpy:32
-    old "Select Gamepad to Calibrate"
-    new "Pilih Gamepad untuk di Kalibrasi"
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "Loading akan menghapus proses yang belum tersimpan.\nApakah kamu yakin?"
 
-    # renpy/common/00gamepad.rpy:35
-    old "No Gamepads Available"
-    new "Tidak ada Gamepad yang Tersedia"
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "Apakah kamu yakin ingin keluar?"
 
-    # renpy/common/00gamepad.rpy:54
-    old "Calibrating [name] ([i]/[total])"
-    new "Mengkalibrasi [nama] ([i]/[total])"
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "Apakah kamu yakin ingin kembali ke main menu?\nProgress belum tersimpan akan hilang."
 
-    # renpy/common/00gamepad.rpy:58
-    old "Press or move the [control!r] [kind]."
-    new "Tekan atau gerakan [control!r] [kind]."
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Apakah kamu yakin untuk mengakhiri replay?"
 
-    # renpy/common/00gamepad.rpy:66
-    old "Skip (A)"
-    new "Lompati (A)"
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "Apakah kamu yakin akan memulai skipping?"
 
-    # renpy/common/00gamepad.rpy:69
-    old "Back (B)"
-    new "Kembali (B)"
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "Apakah kamu yakin ingin meloncat ke pilihan berikutnya?"
 
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Apakah kamu yakin ingin meloncati dialog yang belum terlihat sampai ke pilihan berikutnya?"
 
-translate indonesian strings:
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Menyimpan screenshot sebagai %s."
 
-    # renpy/common/00gltest.rpy:89
-    old "Gamepad"
-    new "Gamepad"
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing di matikan."
 
-    # renpy/common/00gltest.rpy:93
-    old "Enable"
-    new "Aktifkan"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Papan Klip voicing di nyalakan. "
 
-    # renpy/common/00gltest.rpy:97
-    old "Disable"
-    new "Matikan"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing di nyalakan. "
 
-    # renpy/common/00gltest.rpy:103
-    old "Calibrate"
-    new "Kalibrasi"
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Mode Skip"
 
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "Program ini berisi software gratis di bawah banyak lisensi, termasuk lisensi 'MIT' dan 'GNU Lesser General Public License'.Daftar komplit software, termasuk link penuh untuk source code, dapat di temukan {a=https://www.renpy.org/l/license}disini{/a}."
 
-translate indonesian strings:
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Catatan pengisi suara diaktifkan, tekan 'shift+C' untuk matikan."
 
-    # renpy/common/00layout.rpy:456
-    old "Are you sure you want to end the replay?"
-    new "Apakah kamu yakin untuk mengakhiri replay?"
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing akan mengatakan \"[renpy.display.tts.last]\". Tekan 'alt+shift+V' untuk matikan."
 
-    # renpy/common/00layout.rpy:459
-    old "Are you sure you want to skip to unseen dialogue to the next choice?"
-    new "Apakah kamu yakin mau melompati dialog yang belum terlihat ke pilihan berikut nya?"
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Pengisi suara sendiri di aktifkan. Tekan 'v' untuk matikan. V"
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate indonesian strings:
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "Ren'Py Updater tidak di support di perangkat handphone."
 
-    # renpy/common/00library.rpy:139
-    old "Self-voicing disabled."
-    new "Self-voicing di matikan."
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "Error sedang di simulasikan."
 
-    # renpy/common/00library.rpy:140
-    old "Clipboard voicing enabled. "
-    new "Papan Klip voicing di nyalakan. "
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Antara proyek tidak mendukung update, atau file status update di hapus."
 
-    # renpy/common/00library.rpy:141
-    old "Self-voicing enabled. "
-    new "Self-voicing di nyalakan. "
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "Akun ini tidak memiliki izin untuk melakukan update."
 
-    # renpy/common/00library.rpy:262
-    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
-    new "Program ini berisi software gratis di bawah banyak lisensi, termasuk lisensi 'MIT' dan 'GNU Lesser General Public License'.Daftar komplit software, termasuk link penuh untuk source code, dapat di temukan {a=https://www.renpy.org/l/license}disini{/a}."
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "Akun ini tidak memiliki izin untuk menulis log update."
 
-    # renpy/common/00library.rpy:292
-    old "A Ren'Py Game"
-    new "Permainan Ren'Py"
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "Tidak dapat memverifikasi signature update."
 
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "File update tidak di download."
 
-translate indonesian strings:
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "File update tiidak memiliki digest yang benar  - mungkin file corrupt."
 
-    # renpy/common/00preferences.rpy:411
-    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
-    new "Self-voicing akan mengatakan \"[renpy.display.tts.last]\". Tekan 'alt+shift+V' untuk matikan."
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "Ketika unppack {}, tipe tidak diketahui {}."
 
+    # 00updater.rpy:1393
+    old "Updater"
+    new "Updater"
 
-translate indonesian strings:
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "Program ini sudah up to date."
 
-    # renpy/common/_errorhandling.rpym:497
-    old "Copy to Clipboard"
-    new "Salin Ke Papan Klip"
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "Versi: [u.version] sudah tersedia. Apakah kamu ingin memasang nya?"
 
-    # renpy/common/_errorhandling.rpym:499
-    old "Copies the traceback.txt file to the clipboard."
-    new "Salin file traceback.txt ke Papan Klip."
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "Bersiap untuk mendownload update."
 
-    # renpy/common/_errorhandling.rpym:608
-    old "Copies the errors.txt file to the clipboard."
-    new "Salin file errors.txt ke Papan Klip."
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "Mendownload update."
 
-translate indonesian strings:
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "Meng unpack update."
+
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "Update sudah terpasang. Program akan me restart."
+
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "Update sudah terpasang."
+
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "Proses update di batalkan."
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Gambar [index] dari [count] dikunci."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "Sebelum"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "Berikutnya"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "Slideshow"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "Kembali"
 
-    # renpy/common/00layout.rpy:459
-    old "Are you sure you want to skip unseen dialogue to the next choice?"
-    new "Apakah kamu yakin ingin meloncati dialog yang belum terlihat sampai ke pilihan berikutnya?"
diff --git a/launcher/game/tl/indonesian/consolecommand.rpy b/launcher/game/tl/indonesian/consolecommand.rpy
deleted file mode 100644
index 0ce4310..0000000
--- a/launcher/game/tl/indonesian/consolecommand.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate indonesian strings:
-
-    # game/consolecommand.rpy:84
-    old "The command is being run in a new operating system console window."
-    new "Perintah sedang di jalankan di konsol windows sistem operasi baru."
-
diff --git a/launcher/game/tl/indonesian/developer.rpy b/launcher/game/tl/indonesian/developer.rpy
new file mode 100644
index 0000000..1ee0048
--- /dev/null
+++ b/launcher/game/tl/indonesian/developer.rpy
@@ -0,0 +1,179 @@
+
+translate indonesian strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Menu Pengembang"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Reload Game (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Konsol (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Viewer variabel"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Test Tema"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Pemilih LokasI Gambar"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "List Namafile"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Perlihatkan Log Load Gambar"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Sembunyikan Load Log Gambar"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Tidak ada yang dapat di inspeksi"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Kembali ke menu pengembang"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Persegi Panjang: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Posisi Mouse: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Klik-Kanan atau escape untuk keluar."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Persegi di salin ke catatan."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Posisi di salin ke catatan."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Inspektur yang dapat di tampilkan"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Ukuran"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Gaya"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Lokasi"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Menginspeksi Gaya dari [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (tidak ada properti yang mempengaruhi displayable)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (properti default di ubah)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Tekan <esc> untuk keluar konsol. Ketik help untuk bantuan.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Script Ren'Py di aktifkan."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Script Ren'Py di matikan."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: menampilkan bantuan"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "perintah:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: Menjalankan pernyataan\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: Menjalankan expresi atau pernyataan"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: membersikan histori konsol"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: keluar konsol"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: load game dari slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: simpan game di slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: reload game, me refresh script"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: lihat expresi python"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: berhenti melihat expresi"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: berhenti melihat semua expresi"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: lompat ke label"
+
diff --git a/launcher/game/tl/indonesian/distribute.rpy b/launcher/game/tl/indonesian/distribute.rpy
deleted file mode 100644
index f1e5f7b..0000000
--- a/launcher/game/tl/indonesian/distribute.rpy
+++ /dev/null
@@ -1,49 +0,0 @@
-
-translate indonesian strings:
-
-    # game/distribute.rpy:333
-    old "Nothing to do."
-    new "Nganggur"
-
-    # game/distribute.rpy:337
-    old "Scanning project files..."
-    new "Scanning file projek..."
-
-    # game/distribute.rpy:344
-    old "Scanning Ren'Py files..."
-    new "Scanning file Ren'Py..."
-
-    # game/distribute.rpy:494
-    old "Archiving files..."
-    new "Mengarsipkan file..."
-
-    # game/distribute.rpy:745
-    old "Writing the [variant] [format] package."
-    new "Menulis [variant] [format]"
-
-    # game/distribute.rpy:758
-    old "Making the [variant] update zsync file."
-    new "Membuat [variant] zsync update file."
-
-    # game/distribute.rpy:854
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Memproses {b}[complete]{/b} Dari {b}[total]{/b} file."
-
-    # game/distribute.rpy:915
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Semua package telah di buat.\n\nKarena masalah ijin, unpack dan repack file distribusi linux dan mac di windows tidak di dukung."
-
-
-translate indonesian strings:
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Tidak ada package yang di pilih, jadi sistem Nganggur."
-
-
-translate indonesian strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Membangun distribusi gagal:\n\nVariabel build.directory_name mungkin tidak menginclude spasi ,tanda kutip ,atau titik koma."
-
diff --git a/launcher/game/tl/indonesian/distribute_gui.rpy b/launcher/game/tl/indonesian/distribute_gui.rpy
deleted file mode 100644
index e450114..0000000
--- a/launcher/game/tl/indonesian/distribute_gui.rpy
+++ /dev/null
@@ -1,73 +0,0 @@
-
-translate indonesian strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Bangun Distribusi: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Nama Direktori:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Nama Executable:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "Aksi:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "Edit options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Segarkan"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Bangun Package:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "Bangun Update:"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "Bangun"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Error di deteksi saat menjalankan proyek. Tolong pastikan proyek berjalan tanpa error sebelum membangun distribusi"
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Proyek mu tidak mengandung informasi build. Maukah kamu menambahkan informasi build di akhir pada options.rpy?"
-
-
-translate indonesian strings:
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "Tambah dari klausa panggilan, sekali"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "Opsi:"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "Tambah dari klausa panggilan"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "Menambahkan dari klausul untuk memanggil pernyataan yang tidak memiliki mereka."
-
-
-translate indonesian strings:
-
-    # game/distribute_gui.rpy:199
-    old "Upload to itch.io"
-    new "Upload ke itch.io"
-
diff --git a/launcher/game/tl/indonesian/editor.rpy b/launcher/game/tl/indonesian/editor.rpy
deleted file mode 100644
index 3449e5d..0000000
--- a/launcher/game/tl/indonesian/editor.rpy
+++ /dev/null
@@ -1,62 +0,0 @@
-
-translate indonesian strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Di Rekomendasikan.{/b} Editor dengan interface yang mudah untuk di gunakan dan fitur yang sesuai dengan development . Saat ini Editra belum mendukung text input IME yang di butuhkan untuk bahasa Cina,Jepang Dan Korea."
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Di Rekomendasikan.{/b} Editor dengan interface yang mudah untuk di gunakan dan fitur yang sesuai dengan development . Saat ini Editra belum mendukung text input IME yang di butuhkan untuk bahasa Cina,Jepang Dan Korea. Pada Linux, Editra memerlikan wxPython."
-
-    # game/editor.rpy:137
-    old "The may have occured because wxPython is not installed on this system."
-    new "Ini mungkin terjadi karena wxPython tidak terpasang di sistem ini."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Download sampai dengan 22 mb di butuhkan."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "1.8 MB download di butuhkan."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Ini mungkin terjadi karena Java tidak terpasang di sistem ini."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Kesalahan terjadi ketika menjalankan editor text: \n[exception!q]"
-
-    # game/editor.rpy:378
-    old "Select Editor"
-    new "Pilih Editor"
-
-    # game/editor.rpy:393
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Text editor adalah program yang akan kamu gunakan untuk mengedit file script Ren'Pu, Kamu dapat memilih editor Ren'Py yang akan kamu pakai. Jika belum ada, editor akan otomatis di download dan di pasang."
-
-    # game/editor.rpy:415
-    old "Cancel"
-    new "Batal"
-
-
-translate indonesian strings:
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Ini mungkin terjadi karena wxPython tidak terpasang di sistem ini."
-
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Editor bagus yang memerlukan Java"
-
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Editor telah di asosiasikan dengan file .rpy"
-
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Larang Ren''Py untuk membuka editor text."
-
diff --git a/launcher/game/tl/indonesian/error.rpy b/launcher/game/tl/indonesian/error.rpy
new file mode 100644
index 0000000..bbb8286
--- /dev/null
+++ b/launcher/game/tl/indonesian/error.rpy
@@ -0,0 +1,179 @@
+
+translate indonesian strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Akselerasi Grafis"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Pilih Otomatis"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Paksakan Renderer Angle/DirectX"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Paksakan Renderer OpenGL"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Paksakan Renderer software"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Aktifkan"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Perubahan akan memberikan efek, saat program di jalankan lagi nanti."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Peringatan Performa"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Komputer ini menggunakan rendering software."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Komputer ini tidak menggunakan shaders."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Komputer ini menampilkan grafis dengan lambat."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Komputer ini mengalami masalah saat menampilkan grafis: [problem]"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Driver grafis mungkin sudah ketinggalan jaman atau tidak berkerja dengan benar.\nIni dapat menyebabkan komputer lambat bahkan tidak akurat dalam menampilkan grafis,\nMengupdate DirectX dapat memperbaiki masalah ini."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Driver grafis mungkin sudah ketinggalan jaman atau tidak berkerja dengan benar.\nIni dapat menyebabkan komputer lambat bahkan tidak akurat dalam menampilkan grafis."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Update DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Lanjutkan, Tampilkan peringatan ini lagi"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Lanjutkan, Jangan tampilkan peringatan ini lagi"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Mengupdate DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX web setup telah di jalankan. Mungkin akan berjalan dengan mode minimized di taskbar.\nSilahkan ikuti instruksi untuk memasang DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Catatan:{/b} Program Microsoft's DirectX web setup, secara default akan memasang toolbar Bing.\nJika kamu tidak mengigini toolbar ini, silahkan uncheck box yang bersangkutan."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Ketik setup selesai, silahkan klik tombol di bawah untuk me restart program ini."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Restart"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Pilih Gamepad untuk di Kalibrasi"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "Tidak ada Gamepad yang Tersedia"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Mengkalibrasi [nama] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Tekan atau gerakan [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Lompati (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Kembali (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Buka Traceback"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Buka traceback.txt di text editor."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Salin Ke Papan Klip"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Salin file traceback.txt ke Papan Klip."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Kesalahan telah terjadi."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Rollback"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Coba untuk roll back, memungkinkan kamu untuk bisa menyimpan atau memilih pilihan yang berbeda"
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Abaikan"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Abaikan kesalahan, Memungkinkan kamu untuk melanjutkan. Biasanya ini berujung pada error yang baru."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Muat ulang"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Muat ulang game dari harddisk, Menyimpan dan memulihkan state game jika mungkin."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Keluar dari game."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Gagal mengcompile script."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Buka kesalahan compile"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Membuka errors.txt di text editor."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Salin file errors.txt ke Papan Klip."
+
diff --git a/launcher/game/tl/indonesian/front_page.rpy b/launcher/game/tl/indonesian/front_page.rpy
deleted file mode 100644
index aaeb502..0000000
--- a/launcher/game/tl/indonesian/front_page.rpy
+++ /dev/null
@@ -1,137 +0,0 @@
-
-translate indonesian strings:
-
-    # game/front_page.rpy:79
-    old "+ Create New Project"
-    new "+ Buat Proyek Baru"
-
-    # game/front_page.rpy:90
-    old "Launch Project"
-    new "Jalankan Proyek"
-
-    # game/front_page.rpy:111
-    old "Tutorial"
-    new "Tutorial"
-
-    # game/front_page.rpy:112
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:128
-    old "Active Project"
-    new "Proyek Aktif"
-
-    # game/front_page.rpy:136
-    old "Open Directory"
-    new "Buka Direktori"
-
-    # game/front_page.rpy:141
-    old "game"
-    new "Game"
-
-    # game/front_page.rpy:142
-    old "base"
-    new "Base"
-
-    # game/front_page.rpy:148
-    old "Edit File"
-    new "Edit File"
-
-    # game/front_page.rpy:156
-    old "All script files"
-    new "Seluruh file script"
-
-    # game/front_page.rpy:165
-    old "Navigate Script"
-    new "Navigasi Script"
-
-    # game/front_page.rpy:176
-    old "Check Script (Lint)"
-    new "Cek Script (Lint)"
-
-    # game/front_page.rpy:177
-    old "Change Theme"
-    new "Gant Tema"
-
-    # game/front_page.rpy:178
-    old "Delete Persistent"
-    new "Hapus Presistent"
-
-    # game/front_page.rpy:186
-    old "Build Distributions"
-    new "Bangun Distribusi"
-
-    # game/front_page.rpy:188
-    old "Generate Translations"
-    new "Hasilkan Terjemahan"
-
-    # game/front_page.rpy:204
-    old "Checking script for potential problems..."
-    new "Mencek script untuk masalah yang berpotensial..."
-
-    # game/front_page.rpy:219
-    old "Deleting persistent data..."
-    new "Menghapus data presistent"
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "Extrak Dialog"
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:144
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Buka direktori [text]"
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "Pilih proyek [text]"
-
-    # game/front_page.rpy:234
-    old "Force Recompile"
-    new "Paksa Recompile"
-
-    # game/front_page.rpy:285
-    old "Recompiling all rpy files into rpyc files..."
-    new "Mengcompile ulang semua file rpy ke rpyc..."
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:246
-    old "iOS"
-    new "iOS"
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:198
-    old "images"
-    new "Gambar"
-
-
-translate indonesian strings:
-
-    # game/front_page.rpy:198
-    old "gui"
-    new "Gui"
-
-    # game/front_page.rpy:240
-    old "Change/Update GUI"
-    new "Ubah/Perbaharui GUI"
-
diff --git a/launcher/game/tl/indonesian/gui.rpy b/launcher/game/tl/indonesian/gui.rpy
index ee422c8..fb7304f 100644
--- a/launcher/game/tl/indonesian/gui.rpy
+++ b/launcher/game/tl/indonesian/gui.rpy
@@ -1,692 +1,411 @@
 
 translate indonesian strings:
 
-    # gui/game/gui.rpy:644
-    old "History"
-    new "Riwayat"
-
-    # gui/game/gui.rpy:645
-    old "Skip"
-    new "Lompati"
-
-    # gui/game/gui.rpy:646
-    old "Auto"
-    new "Otomatis"
-
-    # gui/game/gui.rpy:647
-    old "Save"
-    new "Simpan"
-
-    # gui/game/gui.rpy:648
-    old "Q.Save"
-    new "Simpan.C"
-
-    # gui/game/gui.rpy:649
-    old "Q.Load"
-    new "Muat.C"
-
-    # gui/game/gui.rpy:650
-    old "Prefs"
-    new "Setting"
-
-    # gui/game/gui.rpy:690
-    old "Start"
-    new "Mulai"
-
-    # gui/game/gui.rpy:698
-    old "Load"
-    new "Muat"
-
-    # gui/game/gui.rpy:700
-    old "Preferences"
-    new "Setting"
-
-    # gui/game/gui.rpy:704
-    old "End Replay"
-    new "Akhiri Replay"
-
-    # gui/game/gui.rpy:708
-    old "Main Menu"
-    new "Menu Utama"
-
-    # gui/game/gui.rpy:715
-    old "Help"
-    new "Bantuan"
-
-    # gui/game/gui.rpy:941
-    old "Version [config.version!t]\n"
-    new "Versi [config.version!t]\n"
-
-    # gui/game/gui.rpy:947
-    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
-    new "Dibuat Dengan {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
-
-    # gui/game/gui.rpy:1029
-    old "{#file_time}%A, %B %d %Y, %H:%M"
-    new "{#file_time}%A, %B %d %Y, %H:%M"
-
-    # gui/game/gui.rpy:1029
-    old "empty slot"
-    new "Slot Kosong"
-
-    # gui/game/gui.rpy:1046
-    old "<"
-    new "<"
-
-    # gui/game/gui.rpy:1048
-    old "{#auto_page}A"
-    new "{#auto_page}O"
-
-    # gui/game/gui.rpy:1050
-    old "{#quick_page}Q"
-    new "{#quick_page}C"
-
-    # gui/game/gui.rpy:1056
-    old ">"
-    new ">"
-
-    # gui/game/gui.rpy:1124
-    old "Rollback Side"
-    new "Arah Rollback"
-
-    # gui/game/gui.rpy:1126
-    old "Left"
-    new "Kiri"
-
-    # gui/game/gui.rpy:1127
-    old "Right"
-    new "Kanan"
-
-    # gui/game/gui.rpy:1132
-    old "Unseen Text"
-    new "Belum Terlihat"
-
-    # gui/game/gui.rpy:1133
-    old "After Choices"
-    new "Setelah Pilihan"
-
-    # gui/game/gui.rpy:1134
-    old "Transitions"
-    new "Transisi"
-
-    # gui/game/gui.rpy:1151
-    old "Auto-Forward Time"
-    new "Waktu Otomatis-Maju"
-
-    # gui/game/gui.rpy:1158
-    old "Music Volume"
-    new "Volume Musik"
-
-    # gui/game/gui.rpy:1171
-    old "Test"
-    new "Tes"
-
-    # gui/game/gui.rpy:1175
-    old "Voice Volume"
-    new "Volume Suara"
-
-    # gui/game/gui.rpy:1186
-    old "Mute All"
-    new "Senyapkan Semua"
-
-    # gui/game/gui.rpy:1299
-    old "The dialogue history is empty."
-    new "Riwayat dialog kosong."
-
-    # gui/game/gui.rpy:1365
-    old "Keyboard"
-    new "Papanketik"
-
-    # gui/game/gui.rpy:1366
-    old "Mouse"
-    new "Mouse"
-
-    # gui/game/gui.rpy:1382
-    old "Enter"
-    new "Enter"
-
-    # gui/game/gui.rpy:1383
-    old "Advances dialogue and activates the interface."
-    new "Dialog tingkat lanjut dan mengaktifkan antarmuka."
-
-    # gui/game/gui.rpy:1386
-    old "Space"
-    new "Spasi"
-
-    # gui/game/gui.rpy:1387
-    old "Advances dialogue without selecting choices."
-    new "Dialog tingkat lanjut tanpa memilih pilihan."
-
-    # gui/game/gui.rpy:1390
-    old "Arrow Keys"
-    new "Tombol Panah"
-
-    # gui/game/gui.rpy:1391
-    old "Navigate the interface."
-    new "Navigasi di antarmuka"
-
-    # gui/game/gui.rpy:1394
-    old "Escape"
-    new "Escape"
-
-    # gui/game/gui.rpy:1395
-    old "Accesses the game menu."
-    new "Akses menu permainan."
-
-    # gui/game/gui.rpy:1398
-    old "Ctrl"
-    new "Ctrl"
-
-    # gui/game/gui.rpy:1399
-    old "Skips dialogue while held down."
-    new "Lompati dialog ketika di tahan."
-
-    # gui/game/gui.rpy:1402
-    old "Tab"
-    new "Tab"
-
-    # gui/game/gui.rpy:1403
-    old "Toggles dialogue skipping."
-    new "Nyala/Matikan lompati dialog."
-
-    # gui/game/gui.rpy:1406
-    old "Page Up"
-    new "Page Up"
-
-    # gui/game/gui.rpy:1407
-    old "Rolls back to earlier dialogue."
-    new "Putar mundur ke dialog sebelumnya."
-
-    # gui/game/gui.rpy:1410
-    old "Page Down"
-    new "Page Down"
-
-    # gui/game/gui.rpy:1411
-    old "Rolls forward to later dialogue."
-    new "Putar maju ke dialog berikut."
-
-    # gui/game/gui.rpy:1415
-    old "Hides the user interface."
-    new "Sembunyikan antarmuka."
-
-    # gui/game/gui.rpy:1419
-    old "Takes a screenshot."
-    new "Ambiil tangkapan layar."
-
-    # gui/game/gui.rpy:1423
-    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
-    new "Nyalakan assisten {a=https://www.renpy.org/l/voicing}suara-sendiri{/a}"
-
-    # gui/game/gui.rpy:1429
-    old "Left Click"
-    new "Klik Kiri"
-
-    # gui/game/gui.rpy:1433
-    old "Middle Click"
-    new "Klik Tengah"
-
-    # gui/game/gui.rpy:1437
-    old "Right Click"
-    new "Klik Kanan"
-
-    # gui/game/gui.rpy:1441
-    old "Mouse Wheel Up\nClick Rollback Side"
-    new "Roda Mouse Atas\nKlik Arah Rollback"
-
-    # gui/game/gui.rpy:1445
-    old "Mouse Wheel Down"
-    new "Roda Mouse Bawah"
-
-    # gui/game/gui.rpy:1452
-    old "Right Trigger\nA/Bottom Button"
-    new "Trigger Kanan\nA/Tombol Bawah"
-
-    # gui/game/gui.rpy:1453
-    old "Advance dialogue and activates the interface."
-    new "Dialog tingkat lanjut dan mengaktifkan antarmuka."
-
-    # gui/game/gui.rpy:1457
-    old "Roll back to earlier dialogue."
-    new "Putar mundur ke dialog sebelumnya"
-
-    # gui/game/gui.rpy:1460
-    old "Right Shoulder"
-    new "Pundak Kanan"
-
-    # gui/game/gui.rpy:1461
-    old "Roll forward to later dialogue."
-    new "Putar maju ke dialog berikut"
-
-    # gui/game/gui.rpy:1464
-    old "D-Pad, Sticks"
-    new "D-Pad, Stick"
-
-    # gui/game/gui.rpy:1468
-    old "Start, Guide"
-    new "Mulai, Panduan"
-
-    # gui/game/gui.rpy:1469
-    old "Access the game menu."
-    new "Akses menu permainan."
-
-    # gui/game/gui.rpy:1472
-    old "Y/Top Button"
-    new "Y/Tombol Atas"
-
-    # gui/game/gui.rpy:1587
-    old "Skipping"
-    new "Melompati"
-
-    # gui/game/gui.rpy:1813
-    old "Menu"
-    new "Menu"
-
-    # gui/game/gui.rpy:2
+    # gui.rpy:2
     old "## Initialization"
     new "## Inisialisasi"
 
-    # gui/game/gui.rpy:5
+    # gui.rpy:5
     old "## The init offset statement causes the init code in this file to run before init code in any other file."
     new "## Pernyataan offset init menyebabkan kode init di file ini berjalan sebelum kode init di dalam file lainnya."
 
-    # gui/game/gui.rpy:9
+    # gui.rpy:9
     old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
     new "## Memanggil gui.init. mereset gaya ke value bawaan, dan menset lebar dan tinggi dari permainan."
 
-    # gui/game/gui.rpy:21
+    # gui.rpy:21
     old "## Colors"
     new "## Warna"
 
-    # gui/game/gui.rpy:23
+    # gui.rpy:23
     old "## The colors of text in the interface."
     new "## Warna text pada antarmuka."
 
-    # gui/game/gui.rpy:25
+    # gui.rpy:25
     old "## An accent color used throughout the interface to label and highlight text."
     new "## Warna aksen yang digunakan sepanjang interface sampai pewarnaan text."
 
-    # gui/game/gui.rpy:29
+    # gui.rpy:29
     old "## The color used for a text button when it is neither selected nor hovered."
     new "## Warna yang di gunakan untuk warna tombol text jika di pilih atau di tekan."
 
-    # gui/game/gui.rpy:32
+    # gui.rpy:32
     old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
     new "## Warna kecil yang di gunakan untuk text kecil, yang membutuhkan lebih terang/lebih gelap untuk mencapai efek yang sama"
 
-    # gui/game/gui.rpy:36
+    # gui.rpy:36
     old "## The color that is used for buttons and bars that are hovered."
     new "## Warna yang di gunakan untuk tombol dan bar yang di pilih."
 
-    # gui/game/gui.rpy:39
+    # gui.rpy:39
     old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
     new "## Warna yang digunakan untuk text tombol ketika di pijit tapi tidak di fokus. Tombol di pilih jika terdapat di layar saat ini atau value preferensi."
 
-    # gui/game/gui.rpy:43
+    # gui.rpy:43
     old "## The color used for a text button when it cannot be selected."
     new "## Warna yang di gunakan untuk tombol text ketika tidak bisa di pilih."
 
-    # gui/game/gui.rpy:46
+    # gui.rpy:46
     old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
     new "## Warna yang di gunakan untuk beberapa bagian dari bar yang tidak terisi. Ini tidak di gunakan secara langsung, Tapi di gunakan ketika me regenerasi file gambar bar."
 
-    # gui/game/gui.rpy:51
+    # gui.rpy:51
     old "## The colors used for dialogue and menu choice text."
     new "## Warna yang di gunakan untuk dialog dan text pilihan menu."
 
-    # gui/game/gui.rpy:56
+    # gui.rpy:56
     old "## Fonts and Font Sizes"
     new "## Font dan ukuran Font"
 
-    # gui/game/gui.rpy:58
+    # gui.rpy:58
     old "## The font used for in-game text."
     new "## Font yang digunakan untuk text in-game."
 
-    # gui/game/gui.rpy:61
+    # gui.rpy:61
     old "## The font used for character names."
     new "## Font yang di gunakan untuk nama karakter."
 
-    # gui/game/gui.rpy:64
+    # gui.rpy:64
     old "## The font used for out-of-game text."
     new "## Font yang digunakan untuk text di luar permainan."
 
-    # gui/game/gui.rpy:67
+    # gui.rpy:67
     old "## The size of normal dialogue text."
     new "## Ukuran normal dialog text."
 
-    # gui/game/gui.rpy:70
+    # gui.rpy:70
     old "## The size of character names."
     new "## Ukuran dari nama karakter."
 
-    # gui/game/gui.rpy:73
+    # gui.rpy:73
     old "## The size of text in the game's user interface."
     new "## Ukuran text antarmuka permainan."
 
-    # gui/game/gui.rpy:76
+    # gui.rpy:76
     old "## The size of labels in the game's user interface."
     new "## Ukuran label di antarmuka permainan."
 
-    # gui/game/gui.rpy:79
+    # gui.rpy:79
     old "## The size of text on the notify screen."
     new "## Ukuran dari text di layar notifikasi."
 
-    # gui/game/gui.rpy:82
+    # gui.rpy:82
     old "## The size of the game's title."
     new "## Ukuran judul permainan."
 
-    # gui/game/gui.rpy:86
+    # gui.rpy:86
     old "## Main and Game Menus"
     new "## Menu utama dan Menu permainan."
 
-    # gui/game/gui.rpy:88
+    # gui.rpy:88
     old "## The images used for the main and game menus."
     new "## Gambar yang di gunakan untuk Menu utama dan Menu permainan."
 
-    # gui/game/gui.rpy:92
+    # gui.rpy:92
     old "## Should we show the name and version of the game?"
     new "## Haruskah kita menunjukkan nama dan versi permainan game?"
 
-    # gui/game/gui.rpy:96
+    # gui.rpy:96
     old "## Dialogue"
     new "## Dialog"
 
-    # gui/game/gui.rpy:98
+    # gui.rpy:98
     old "## These variables control how dialogue is displayed on the screen one line at a time."
     new "## Variabel ini mengendalikan bagaimana dialog di tampilkan pada layar pada satu waktu."
 
-    # gui/game/gui.rpy:101
+    # gui.rpy:101
     old "## The height of the textbox containing dialogue."
     new "## Tinggi textbox yang berisi dialog."
 
-    # gui/game/gui.rpy:104
+    # gui.rpy:104
     old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
     new "## Penempatan texbox secara vertikal pada layar. 0.0 adalah atas, 0.5 adalah tengah, dan 1.0 adalah bawah."
 
-    # gui/game/gui.rpy:109
+    # gui.rpy:109
     old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
     new "## Penempatan nama karakter yang berbicara, hampir sama dengan kotak text. "
 
-    # gui/game/gui.rpy:114
+    # gui.rpy:114
     old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
     new "## Penempatan  horizontal nama karakter. Ini dapat berupa 0.0 untuk rata kiri, 0.5 untuk rata tengah, dan 1.0 untuk rata kanan. "
 
-    # gui/game/gui.rpy:118
+    # gui.rpy:118
     old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
     new "## Lebar, panjang, dan tepi dari kotak berisi nama karakter, Atau None untuk secara otomatis mengukur nya."
 
-    # gui/game/gui.rpy:123
+    # gui.rpy:123
     old "## The borders of the box containing the character's name, in left, top, right, bottom order."
     new "## Tepi kotak bersisi urutan nama karakter, di kiri, atas, kanan, bawah."
 
-    # gui/game/gui.rpy:127
+    # gui.rpy:127
     old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
     new "## Jika Benar, latar dari kotaknama akan di beri judul, jika Salah, latar dari kotaknama akan di ukur ulang."
 
-    # gui/game/gui.rpy:132
+    # gui.rpy:132
     old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
     new "## Penempatan dialog itu relatif pada kotaktext. Ini dapat berisi angka dari pixel yang relativ mulai dari sisi kiri sampai atas dari kotaknama, atau 0.5 untuk tengah."
 
-    # gui/game/gui.rpy:138
+    # gui.rpy:138
     old "## The maximum width of dialogue text, in pixels."
     new "## Lebar maximum dari dialog text, dalam pixel."
 
-    # gui/game/gui.rpy:141
+    # gui.rpy:141
     old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
     new "## rata tengah dari text dialog. Ini dapat berisi 0.0 untuk rata kiri, atau 0.5 untuk tengah, dan 1.0 untuk kanan."
 
-    # gui/game/gui.rpy:146
+    # gui.rpy:146
     old "## Buttons"
     new "## Tombol"
 
-    ##Translation updated at 2016-08-23 21:27
-    # gui/game/gui.rpy:148
+    # gui.rpy:148
     old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
-    new ""
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
 
-    # gui/game/gui.rpy:151
+    # gui.rpy:151
     old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
-    new ""
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
 
-    # gui/game/gui.rpy:155
+    # gui.rpy:155
     old "## The borders on each side of the button, in left, top, right, bottom order."
-    new ""
+    new "## The borders on each side of the button, in left, top, right, bottom order."
 
-    # gui/game/gui.rpy:158
+    # gui.rpy:158
     old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
-    new ""
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
 
-    # gui/game/gui.rpy:162
+    # gui.rpy:162
     old "## The font used by the button."
-    new ""
+    new "## The font used by the button."
 
-    # gui/game/gui.rpy:165
+    # gui.rpy:165
     old "## The size of the text used by the button."
-    new ""
+    new "## The size of the text used by the button."
 
-    # gui/game/gui.rpy:179
+    # gui.rpy:179
     old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
-    new ""
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
 
-    # gui/game/gui.rpy:183
+    # gui.rpy:183
     old "## These customizations are used by the default interface:"
-    new ""
+    new "## These customizations are used by the default interface:"
 
-    # gui/game/gui.rpy:198
+    # gui.rpy:198
     old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
-    new ""
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
 
-    # gui/game/gui.rpy:205
+    # gui.rpy:205
     old "## Choice Buttons"
-    new ""
+    new "## Choice Buttons"
 
-    # gui/game/gui.rpy:207
+    # gui.rpy:207
     old "## Choice buttons are used in the in-game menus."
-    new ""
+    new "## Choice buttons are used in the in-game menus."
 
-    # gui/game/gui.rpy:220
+    # gui.rpy:220
     old "## File Slot Buttons"
-    new ""
+    new "## File Slot Buttons"
 
-    # gui/game/gui.rpy:222
+    # gui.rpy:222
     old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
-    new ""
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
 
-    # gui/game/gui.rpy:226
+    # gui.rpy:226
     old "## The save slot button."
-    new ""
+    new "## The save slot button."
 
-    # gui/game/gui.rpy:234
+    # gui.rpy:234
     old "## The width and height of thumbnails used by the save slots."
-    new ""
+    new "## The width and height of thumbnails used by the save slots."
 
-    # gui/game/gui.rpy:238
+    # gui.rpy:238
     old "## The number of columns and rows in the grid of save slots."
-    new ""
+    new "## The number of columns and rows in the grid of save slots."
 
-    # gui/game/gui.rpy:243
+    # gui.rpy:243
     old "## Positioning and Spacing"
-    new ""
+    new "## Positioning and Spacing"
 
-    # gui/game/gui.rpy:245
+    # gui.rpy:245
     old "## These variables control the positioning and spacing of various user interface elements."
-    new ""
+    new "## These variables control the positioning and spacing of various user interface elements."
 
-    # gui/game/gui.rpy:248
+    # gui.rpy:248
     old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
-    new ""
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
 
-    # gui/game/gui.rpy:252
+    # gui.rpy:252
     old "## The vertical position of the skip indicator."
-    new ""
+    new "## The vertical position of the skip indicator."
 
-    # gui/game/gui.rpy:255
+    # gui.rpy:255
     old "## The vertical position of the notify screen."
-    new ""
+    new "## The vertical position of the notify screen."
 
-    # gui/game/gui.rpy:258
+    # gui.rpy:258
     old "## The spacing between menu choices."
-    new ""
+    new "## The spacing between menu choices."
 
-    # gui/game/gui.rpy:261
+    # gui.rpy:261
     old "## Buttons in the navigation section of the main and game menus."
-    new ""
+    new "## Buttons in the navigation section of the main and game menus."
 
-    # gui/game/gui.rpy:264
+    # gui.rpy:264
     old "## Controls the amount of spacing between preferences."
-    new ""
+    new "## Controls the amount of spacing between preferences."
 
-    # gui/game/gui.rpy:267
+    # gui.rpy:267
     old "## Controls the amount of spacing between preference buttons."
-    new ""
+    new "## Controls the amount of spacing between preference buttons."
 
-    # gui/game/gui.rpy:270
+    # gui.rpy:270
     old "## The spacing between file page buttons."
-    new ""
+    new "## The spacing between file page buttons."
 
-    # gui/game/gui.rpy:273
+    # gui.rpy:273
     old "## The spacing between file slots."
-    new ""
+    new "## The spacing between file slots."
 
-    # gui/game/gui.rpy:277
+    # gui.rpy:277
     old "## Frames"
-    new ""
+    new "## Frames"
 
-    # gui/game/gui.rpy:279
+    # gui.rpy:279
     old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
-    new ""
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
 
-    # gui/game/gui.rpy:282
+    # gui.rpy:282
     old "## Generic frames that are introduced by player code."
-    new ""
+    new "## Generic frames that are introduced by player code."
 
-    # gui/game/gui.rpy:285
+    # gui.rpy:285
     old "## The frame that is used as part of the confirm screen."
-    new ""
+    new "## The frame that is used as part of the confirm screen."
 
-    # gui/game/gui.rpy:288
+    # gui.rpy:288
     old "## The frame that is used as part of the skip screen."
-    new ""
+    new "## The frame that is used as part of the skip screen."
 
-    # gui/game/gui.rpy:291
+    # gui.rpy:291
     old "## The frame that is used as part of the notify screen."
-    new ""
+    new "## The frame that is used as part of the notify screen."
 
-    # gui/game/gui.rpy:294
+    # gui.rpy:294
     old "## Should frame backgrounds be tiled?"
-    new ""
+    new "## Should frame backgrounds be tiled?"
 
-    # gui/game/gui.rpy:298
+    # gui.rpy:298
     old "## Bars, Scrollbars, and Sliders"
-    new ""
+    new "## Bars, Scrollbars, and Sliders"
 
-    # gui/game/gui.rpy:300
+    # gui.rpy:300
     old "## These control the look and size of bars, scrollbars, and sliders."
-    new ""
+    new "## These control the look and size of bars, scrollbars, and sliders."
 
-    # gui/game/gui.rpy:302
+    # gui.rpy:302
     old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
-    new ""
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
 
-    # gui/game/gui.rpy:305
+    # gui.rpy:305
     old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
-    new ""
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
 
-    # gui/game/gui.rpy:311
+    # gui.rpy:311
     old "## True if bar images should be tiled. False if they should be linearly scaled."
-    new ""
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
 
-    # gui/game/gui.rpy:316
+    # gui.rpy:316
     old "## Horizontal borders."
-    new ""
+    new "## Horizontal borders."
 
-    # gui/game/gui.rpy:321
+    # gui.rpy:321
     old "## Vertical borders."
-    new ""
+    new "## Vertical borders."
 
-    # gui/game/gui.rpy:326
+    # gui.rpy:326
     old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
-    new ""
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
 
-    # gui/game/gui.rpy:331
+    # gui.rpy:331
     old "## History"
-    new ""
+    new "## History"
 
-    # gui/game/gui.rpy:333
+    # gui.rpy:333
     old "## The history screen displays dialogue that the player has already dismissed."
-    new ""
+    new "## The history screen displays dialogue that the player has already dismissed."
 
-    # gui/game/gui.rpy:335
+    # gui.rpy:335
     old "## The number of blocks of dialogue history Ren'Py will keep."
-    new ""
+    new "## The number of blocks of dialogue history Ren'Py will keep."
 
-    # gui/game/gui.rpy:338
+    # gui.rpy:338
     old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
-    new ""
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
 
-    # gui/game/gui.rpy:342
+    # gui.rpy:342
     old "## The position, width, and alignment of the label giving the name of the speaking character."
-    new ""
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
 
-    # gui/game/gui.rpy:349
+    # gui.rpy:349
     old "## The position, width, and alignment of the dialogue text."
-    new ""
+    new "## The position, width, and alignment of the dialogue text."
 
-    # gui/game/gui.rpy:356
+    # gui.rpy:356
     old "## NVL-Mode"
-    new ""
+    new "## NVL-Mode"
 
-    # gui/game/gui.rpy:358
+    # gui.rpy:358
     old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
-    new ""
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
 
-    # gui/game/gui.rpy:360
+    # gui.rpy:360
     old "## The borders of the background of the NVL-mode background window."
-    new ""
+    new "## The borders of the background of the NVL-mode background window."
 
-    # gui/game/gui.rpy:363
+    # gui.rpy:363
     old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
-    new ""
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
 
-    # gui/game/gui.rpy:367
+    # gui.rpy:367
     old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
-    new ""
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
 
-    # gui/game/gui.rpy:384
+    # gui.rpy:384
     old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
-    new ""
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
 
-    # gui/game/gui.rpy:391
+    # gui.rpy:391
     old "## The position of nvl menu_buttons."
-    new ""
+    new "## The position of nvl menu_buttons."
 
-    # gui/game/gui.rpy:403
+    # gui.rpy:403
     old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
-    new ""
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
 
-    # gui/game/gui.rpy:409
+    # gui.rpy:409
     old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
-    new ""
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
 
-    # gui/game/gui.rpy:413
+    # gui.rpy:413
     old "## Font sizes."
-    new ""
+    new "## Font sizes."
 
-    # gui/game/gui.rpy:421
+    # gui.rpy:421
     old "## Adjust the location of the textbox."
-    new ""
+    new "## Adjust the location of the textbox."
 
-    # gui/game/gui.rpy:427
+    # gui.rpy:427
     old "## Change the size and spacing of items in the game menu."
-    new ""
+    new "## Change the size and spacing of items in the game menu."
 
-    # gui/game/gui.rpy:436
+    # gui.rpy:436
     old "## File button layout."
-    new ""
+    new "## File button layout."
 
-    # gui/game/gui.rpy:440
+    # gui.rpy:440
     old "## NVL-mode."
-    new ""
+    new "## NVL-mode."
 
-    # gui/game/gui.rpy:456
+    # gui.rpy:456
     old "## Quick buttons."
-    new ""
+    new "## Quick buttons."
 
diff --git a/launcher/game/tl/indonesian/gui7.rpy b/launcher/game/tl/indonesian/gui7.rpy
deleted file mode 100644
index 5c08740..0000000
--- a/launcher/game/tl/indonesian/gui7.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate indonesian strings:
-
-    # game/gui7.rpy:161
-    old "Text Speed"
-    new "Kecepatan Text"
-
-    # game/gui7.rpy:190
-    old "Select Accent and Background Colors"
-    new "Pilih Accent Dan Warna Background"
-
-    # game/gui7.rpy:204
-    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
-    new "Tolong klik skema warna yang ingin kamu pakai, lalu klik continue. Warna ini dapat di ubah dan di kostumisasi lagi nanti."
-
-    # game/gui7.rpy:246
-    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
-    new "{b}Peringatan{/b}\nMelanjutkan akan menimpa bar ,tombol ,slot save ,barscroll ,dan foto slider.\n\nApa yang ingin kamu lakukan?"
-
-    # game/gui7.rpy:246
-    old "Choose new colors, then regenerate image files."
-    new "Pilih warna baru, dan regenerasi file gambar."
-
-    # game/gui7.rpy:246
-    old "Regenerate the image files using the colors in gui.rpy."
-    new "Regenerasi file gambar menggunakan warna di gui.rpy."
-
-    # game/gui7.rpy:293
-    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
-    new "Resolusi apa yang harus di gunakan proyek? Ren'Py dapat mengubah ukuran jendela naik dan turun, ini adalah ukuran inisial dari jendela, ukuran yang menentukan aset manya yang harus di gambar, dan ukuran dimana aset akan menjadi lebih tajamm.\n\nSetelan default 1280x720 adalah ukuran yang paling bisa di kompromi."
-
-    # game/gui7.rpy:341
-    old "Creating the new project..."
-    new "Membuat proyek baru..."
-
-    # game/gui7.rpy:343
-    old "Updating the project..."
-    new "Mengupdate proyek..."
-
diff --git a/launcher/game/tl/indonesian/interface.rpy b/launcher/game/tl/indonesian/interface.rpy
deleted file mode 100644
index b78d409..0000000
--- a/launcher/game/tl/indonesian/interface.rpy
+++ /dev/null
@@ -1,90 +0,0 @@
-
-translate indonesian strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Dokumentasi"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Website Ren'Py"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Daftar Game Ren'Py"
-
-    # game/interface.rpy:92
-    old "About"
-    new "Tentang"
-
-    # game/interface.rpy:99
-    old "update"
-    new "Pembaharuan"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "Setting"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "Keluar"
-
-    # game/interface.rpy:149
-    old "Yes"
-    new "Ya"
-
-    # game/interface.rpy:151
-    old "No"
-    new "Tidak"
-
-    # game/interface.rpy:181
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Karena limitasi format package ,format nama file dan direktori non-ASCII tidak di perbolehkan."
-
-    # game/interface.rpy:183
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:248
-    old "ERROR"
-    new "ERROR"
-
-    # game/interface.rpy:280
-    old "While [what!q], an error occured:"
-    new "Ketika [what!q], Kesalahakn Terjadi:"
-
-    # game/interface.rpy:281
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:298
-    old "Text input may not contain the {{ or [[ characters."
-    new "Input text tidak boleh mengandung karakter {{ atau [[."
-
-    # game/interface.rpy:303
-    old "File and directory names may not contain / or \\."
-    new "Nama file dan direktori tidak boleh mengandung / atau \\."
-
-    # game/interface.rpy:309
-    old "File and directory names must consist of ASCII characters."
-    new "Nama file dan direktori harus terdiri dari karakter ASCII."
-
-    # game/interface.rpy:330
-    old "INFORMATION"
-    new "INFORMASI"
-
-    # game/interface.rpy:373
-    old "PROCESSING"
-    new "MEMPROSES"
-
-    # game/interface.rpy:390
-    old "QUESTION"
-    new "PERTANYAAN"
-
-
-translate indonesian strings:
-
-    # game/interface.rpy:451
-    old "CHOICE"
-    new "PILIHAN"
-
diff --git a/launcher/game/tl/indonesian/ios.rpy b/launcher/game/tl/indonesian/ios.rpy
deleted file mode 100644
index 4b75a2b..0000000
--- a/launcher/game/tl/indonesian/ios.rpy
+++ /dev/null
@@ -1,99 +0,0 @@
-
-translate indonesian strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Untuk membangun package iOS, tolong download renios, unzip, dan taruh di direktori Ren'Pu, Lalu restart launcher Ren'Py."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Direktori dimana proyek Xcode akan di taruh belum di pilih, Silahkan 'Select Directory' untuk memilih."
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "Tidak ada proyek Xcode yang terkoresponding dengan proyek Ren'Py. Pilih 'Create Xcode Project' Untuk membuat satu."
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Xcode projek tersedia. Pilih 'Update Xcode Project'. untuk mengupdate nya dengan game file terbaru, atau gunakan Xcode untuk mebangaun dan pasang."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Mencoba untuk mengemulasi iPhone.\n\nInput Sentuh di emulasikan melalui mouse, tapi hanya jika tombol di tahan."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Mencoba untuk mengemulasi iPad.\n\nInput Sentuh di emulasikan melalui mouse, tapi hanya jika tombol di tahan."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Pilih direktori dimana Xcode akan di simpan."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "Buat proyek Xcode yang berhubungan dengan proyek Ren'Py yang sekarang."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Update proyek Xcode dengan file game terbaru. Ini harus di lakukan setiap proyek Ren'Py berubah"
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Buka proyek Xcode di Xcode."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Buka direktori yang berisi proyek Xcode."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Proyek Xcode sudah tersedia. Maukah kamu untuk menamai ulang proyek lama ,dan mengganti nya dengan yang baru?"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:229
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:233
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "Pilih direktori proyek Xcode"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "Buat proyek Xcode"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "Update kode proyek Xcode"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "Jalankan Xcode"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "Buka direktori proyek Xcode"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "Sebelum mem package aplikasi iOS, Kamu harus mendownload renios, Ren'Py iOS support. Maukah kamu mendownload renios sekarang?"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "DIREKTORI PROYEK XCODE"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Tolong pilih direktori proyek Xcode menggunakan pemilih direktori.\n{b}Pemilih direktori mungkin terbuka di belakang window ini.{/b}"
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py sudah menset direktori proyek Xcode ke:"
-
diff --git a/launcher/game/tl/indonesian/itch.rpy b/launcher/game/tl/indonesian/itch.rpy
deleted file mode 100644
index cdd3107..0000000
--- a/launcher/game/tl/indonesian/itch.rpy
+++ /dev/null
@@ -1,27 +0,0 @@
-
-translate indonesian strings:
-
-    # game/itch.rpy:56
-    old "The built distributions could not be found. Please choose 'Build' and try again."
-    new "Distribusi built tidak dapat di temukan. Tolong pilih 'Build' dan coba lagi."
-
-    # game/itch.rpy:87
-    old "No uploadable files were found. Please choose 'Build' and try again."
-    new "Tidak di temukan file yang bisa di upload. Tolong pilih 'Build' dan coba lagi."
-
-    # game/itch.rpy:95
-    old "The butler program was not found."
-    new "Program butler tidak di temukan."
-
-    # game/itch.rpy:95
-    old "Please install the itch.io app, which includes butler, and try again."
-    new "Tolong pasang aplikasi itch.io, yang menginclude butler, dan coba lagi."
-
-    # game/itch.rpy:104
-    old "The name of the itch project has not been set."
-    new "Nama proyek itch belum di set."
-
-    # game/itch.rpy:104
-    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
-    new "Tolong {a=https://itch.io/game/new}buat proyek mu{/a}, dan masukan line seperti \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} ke options.rpy. "
-
diff --git a/launcher/game/tl/indonesian/launcher.rpy b/launcher/game/tl/indonesian/launcher.rpy
new file mode 100644
index 0000000..56ae787
--- /dev/null
+++ b/launcher/game/tl/indonesian/launcher.rpy
@@ -0,0 +1,1200 @@
+
+translate indonesian strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Lihat Lisensi"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "NAMAFILE"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Masukkan nama script file yang akan di buat"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Nama file harus memlikili extensi .rpy"
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "File sudah ada"
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'py secara otomatis meload semua script dengan akhiran .rpy. Untuk menggunakan\n# file ini, silahkan define label dan jump ke file itu dari file lain.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Untuk membuat package Android, silahkan download RAPT, unzip/extrak, dan taruh di direktori Ren,Py. Dan restart launcher Ren'Py."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Java Development Kit 32-bit di perlukan untuk membuat package Android di Windows, JDK itu berbeda dari JRE, jadi sangat mungkin kamu memiliki java tanpa JDK\n\nTolong {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Download dan install JDK{/a}, lalu restart launcher Ren'Py "
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT sudah terinstall, tapi kamu harus menginstall Android SDK sebelum kamu dapat membuat package Android. Untuk Melakukan Ini Pilih Install SDK"
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT sudah terinstall, tapi kunci/key belum di configurasi. Silahkan buat kunci/key baru, atau restore android.keystore"
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Projek ini belum di configurasi. Gunakan \"Konfigurasi\" untuk mengkonfigurasi sebelum membuat build."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Pilih \"Build\" untuk membuild projek ini, atau koneksikan perangkat Android dan pilih \"Buat & Install\" untuk membuild dan install pada perangkat."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Mencoba untuk mengemulasi perangkat Android.\n\nInput sentuhan di emulasikan melalui mouse, tapi hanya ketika tombol di tahan. Escape di mapped ke tombol menu, dan PageUp di mapped ke tombol back."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Mencoba untuk mengemulasi tablet Android.\n\nInput sentuhan di emulasikan melalui mouse, tapi hanya ketika tombol di tahan. Escape di mapped ke tombol menu, dan PageUp di mapped ke tombol back."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Mencoba mengemulasi konsol televisi Android, Seperti OUYA atau Fire TV.\n\nInput kontroller di map ke tombol panah, Enter di map ke tombol select, Escape di map ke tombol menu, dan PageUp di map ke tombol back"
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Download dan pasang Android SDK dan paket pendukung. Opsional, mengenerate key/kunci yang di butuhkan untuk menandatangani paket."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Konfigurasi nama package, versi, dan informasi lainnya mengenai project ini."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Buka file yang berisi Google Play keys di editor. \n\n Ini hanya di butuhkan juka aplikasi menggunakan expansi APK. Baca dokumentasi untuk detail lebih lanjut"
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Bangun package Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Build package Android, dan install di perangkat Android yang terkoneksi ke komputer mu."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Buat package Android, Install di perangkat Android yang terkoneksi ke komputer, dan menjalankan aplikasi pada perangkat mu."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Sambungkan ke perangkat Android yang memiliki ADB berjalan di mode TCP/IP"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Putuskan hubungan dari perangkat Android yang menjalankan ADB di mode TCP/IP"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Ambil log dari perangkat Android dan menulist nya ke file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Mengcopy file Android ke direktori distribusi."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Emulasi:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Telepon"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Televisi"
+
+    # android.rpy:353
+    old "Build:"
+    new "Build:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Install SDK & Buat Keys"
+
+    # android.rpy:365
+    old "Configure"
+    new "Konfigurasi"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Buat package"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Buat & Install"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Buat, Install & Jalankan"
+
+    # android.rpy:388
+    old "Other:"
+    new "Lainnya:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Koneksi remote ADB"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Putus remote ADB"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Sebelum mempackage aplikasi Android, kamu harus mendownload RAPT, Ren'Py Android Packaging Tool. Maukah kamu mendownload RAPT sekarang?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Alamat remote ADB"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Tolong masukkan alamat IP dan nomor port untuk menyambung, dalam bentuk \"192.168.1.143:5555\". Silahkan lihat dokumentasi perangkat anda untuk memastikan apakah mendukung remote ADB, dan jika mendukung, alamat dan port untuk menggunakan."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Alamat remote ADB invalid"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Alamat hanya boleh mengandung 1 ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "Host seharus nya tidak mengandung spasi."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Port harus berisi angka."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Mendapatkan informasi logcat dari perangkat."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py tidak bisa menjalankan python dengan tkinter untuk memilih direktori. Tolong install python-tk atau tkinter package."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Tidak bisa mengganti tema. Mungkin options.rpy di ubah terlalu banyak."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Pilih Tema"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Tema"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Pilih Skema"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Lanjutkan"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMASI"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "Perintah sedang di jalankan di konsol windows sistem operasi baru."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Scanning file projek..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Membangun distribusi gagal:\n\nVariabel build.directory_name mungkin tidak menginclude spasi ,tanda kutip ,atau titik koma."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Tidak ada package yang di pilih, jadi sistem Nganggur."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Scanning file Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Semua package telah di buat.\n\nKarena masalah ijin, unpack dan repack file distribusi linux dan mac di windows tidak di dukung."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Mengarsipkan file..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Menulis [variant] [format]"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Membuat [variant] zsync update file."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Memproses {b}[complete]{/b} Dari {b}[total]{/b} file."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Bangun Distribusi: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Nama Direktori:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Nama Executable:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Aksi:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Edit options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Tambah dari klausa panggilan, sekali"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Segarkan"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload ke itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Bangun Package:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Opsi:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Bangun Update:"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Tambah dari klausa panggilan"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Paksa Recompile"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Bangun"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Menambahkan dari klausul untuk memanggil pernyataan yang tidak memiliki mereka."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Error di deteksi saat menjalankan proyek. Tolong pastikan proyek berjalan tanpa error sebelum membangun distribusi"
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Proyek mu tidak mengandung informasi build. Maukah kamu menambahkan informasi build di akhir pada options.rpy?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Di Rekomendasikan.{/b} Editor dengan interface yang mudah untuk di gunakan dan fitur yang sesuai dengan development . Saat ini Editra belum mendukung text input IME yang di butuhkan untuk bahasa Cina,Jepang Dan Korea."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Di Rekomendasikan.{/b} Editor dengan interface yang mudah untuk di gunakan dan fitur yang sesuai dengan development . Saat ini Editra belum mendukung text input IME yang di butuhkan untuk bahasa Cina,Jepang Dan Korea. Pada Linux, Editra memerlikan wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Ini mungkin terjadi karena wxPython tidak terpasang di sistem ini."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Download sampai dengan 22 mb di butuhkan."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Editor bagus yang memerlukan Java"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB download di butuhkan."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Ini mungkin terjadi karena Java tidak terpasang di sistem ini."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Editor telah di asosiasikan dengan file .rpy"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Larang Ren''Py untuk membuka editor text."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Kesalahan terjadi ketika menjalankan editor text: \n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Pilih Editor"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Text editor adalah program yang akan kamu gunakan untuk mengedit file script Ren'Pu, Kamu dapat memilih editor Ren'Py yang akan kamu pakai. Jika belum ada, editor akan otomatis di download dan di pasang."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Batal"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Buka direktori [text]"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "Segarkan"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Buat Proyek Baru"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Jalankan Proyek"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Pilih proyek [text]"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Proyek Aktif"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Buka Direktori"
+
+    # front_page.rpy:195
+    old "game"
+    new "Game"
+
+    # front_page.rpy:196
+    old "base"
+    new "Base"
+
+    # front_page.rpy:197
+    old "images"
+    new "Gambar"
+
+    # front_page.rpy:198
+    old "gui"
+    new "Gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Edit File"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Seluruh file script"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Navigasi Script"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Cek Script (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Ubah/Perbaharui GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Gant Tema"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Hapus Presistent"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Bangun Distribusi"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Hasilkan Terjemahan"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Extrak Dialog"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Mencek script untuk masalah yang berpotensial..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Menghapus data presistent"
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Mengcompile ulang semua file rpy ke rpyc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Pilih Accent Dan Warna Background"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Tolong klik skema warna yang ingin kamu pakai, lalu klik continue. Warna ini dapat di ubah dan di kostumisasi lagi nanti."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Peringatan{/b}\nMelanjutkan akan menimpa bar ,tombol ,slot save ,barscroll ,dan foto slider.\n\nApa yang ingin kamu lakukan?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Pilih warna baru, dan regenerasi file gambar."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerasi file gambar menggunakan warna di gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "NAMA PROYEK"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Tolong masukan nama proyek mu:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Nama proyek tidak boleh kosong"
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "Nama proyek [project_name!q] sudah tersedia, silahkan buat nama proyek yang berbeda."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] sudah tersedia, silahkan buat nama proyek yang berbeda."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "Resolusi apa yang harus di gunakan proyek? Ren'Py dapat mengubah ukuran jendela naik dan turun, ini adalah ukuran inisial dari jendela, ukuran yang menentukan aset manya yang harus di gambar, dan ukuran dimana aset akan menjadi lebih tajamm.\n\nSetelan default 1280x720 adalah ukuran yang paling bisa di kompromi."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Membuat proyek baru..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Mengupdate proyek..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Dokumentasi"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Website Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Daftar Game Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "Pembaharuan"
+
+    # interface.rpy:119
+    old "preferences"
+    new "Setting"
+
+    # interface.rpy:120
+    old "quit"
+    new "Keluar"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Karena limitasi format package ,format nama file dan direktori non-ASCII tidak di perbolehkan."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ERROR"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Ketika [what!q], Kesalahakn Terjadi:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Input text tidak boleh mengandung karakter {{ atau [[."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Nama file dan direktori tidak boleh mengandung / atau \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Nama file dan direktori harus terdiri dari karakter ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "MEMPROSES"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "PERTANYAAN"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "PILIHAN"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Untuk membangun package iOS, tolong download renios, unzip, dan taruh di direktori Ren'Pu, Lalu restart launcher Ren'Py."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Direktori dimana proyek Xcode akan di taruh belum di pilih, Silahkan 'Select Directory' untuk memilih."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "Tidak ada proyek Xcode yang terkoresponding dengan proyek Ren'Py. Pilih 'Create Xcode Project' Untuk membuat satu."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Xcode projek tersedia. Pilih 'Update Xcode Project'. untuk mengupdate nya dengan game file terbaru, atau gunakan Xcode untuk mebangaun dan pasang."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Mencoba untuk mengemulasi iPhone.\n\nInput Sentuh di emulasikan melalui mouse, tapi hanya jika tombol di tahan."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Mencoba untuk mengemulasi iPad.\n\nInput Sentuh di emulasikan melalui mouse, tapi hanya jika tombol di tahan."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Pilih direktori dimana Xcode akan di simpan."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Buat proyek Xcode yang berhubungan dengan proyek Ren'Py yang sekarang."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Update proyek Xcode dengan file game terbaru. Ini harus di lakukan setiap proyek Ren'Py berubah"
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Buka proyek Xcode di Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Buka direktori yang berisi proyek Xcode."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Proyek Xcode sudah tersedia. Maukah kamu untuk menamai ulang proyek lama ,dan mengganti nya dengan yang baru?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Pilih direktori proyek Xcode"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Buat proyek Xcode"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Update kode proyek Xcode"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Jalankan Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Buka direktori proyek Xcode"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Sebelum mem package aplikasi iOS, Kamu harus mendownload renios, Ren'Py iOS support. Maukah kamu mendownload renios sekarang?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "DIREKTORI PROYEK XCODE"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Tolong pilih direktori proyek Xcode menggunakan pemilih direktori.\n{b}Pemilih direktori mungkin terbuka di belakang window ini.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py sudah menset direktori proyek Xcode ke:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "Distribusi built tidak dapat di temukan. Tolong pilih 'Build' dan coba lagi."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "Tidak di temukan file yang bisa di upload. Tolong pilih 'Build' dan coba lagi."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "Program butler tidak di temukan."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Tolong pasang aplikasi itch.io, yang menginclude butler, dan coba lagi."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "Nama proyek itch belum di set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Tolong {a=https://itch.io/game/new}buat proyek mu{/a}, dan masukan line seperti \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} ke options.rpy. "
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navigasi: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Urutan:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "Alfabetical"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "Berdasarkan-file"
+
+    # navigation.rpy:182
+    old "natural"
+    new "Natural"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Kategori:"
+
+    # navigation.rpy:196
+    old "files"
+    new "File"
+
+    # navigation.rpy:197
+    old "labels"
+    new "Label"
+
+    # navigation.rpy:198
+    old "defines"
+    new "Definisi"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "Transform"
+
+    # navigation.rpy:200
+    old "screens"
+    new "Layar"
+
+    # navigation.rpy:201
+    old "callables"
+    new "Panggilan"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODOs"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Tambahkan file script"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Tidak ada komentar TODO di temukan.\n\nUntuk membuat nya,Masukan \"# TODO\" ke dalam script."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Daftar nama kosong."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "Interface GUI Baru"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Kedua interface sudah di terjemahkan ke bahasa mu."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Hanya gui baru yang sudah di terjemahkan ke bahasa mu."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Hanya tema legasi interface yang sudah di terjemahkan ke bahasa mu."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Interface belum di terjemahkan ke bahsa mu."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Direktori proyek tidak bisa di set."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Interface mana yang ingin kamu gunakan? GUI baru memiliki tampilan moderen, mendukung layar lebar dan perangkat mobile, dan lebih mudah di kustomisasi. Tema legasi lebih di peruntukan untuk di gunakan dengan kode yang lama.\n\n[language_support!t]\n\nJika begitu, pilih GUI baru, dan klikk 'Lanjutkan' di pojok kanan bawah."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Tema Interface Legacy"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Pilih template proyek"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Silahkan pilih template baru untuk proyek baru mu. Template set font deafult dan bahasa user interface. Jika bahasa mu tidak di dukung ,silahkan pilih 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Setting Launcher"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Direktori Proyek:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Direktori proyek: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Belum di Set"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Editor Text:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Text editor: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Channel Update:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Opsi Navigasi:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Ikutsertakan Nama Privat"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Ikutsertakan Nama Library"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Opsi Launcher:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Rendering Hardware"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Tunjukkan template"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Tunjukan bagian edit file"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Font besar"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Output konsol"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Buka proyek launcher"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Bahasa:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Setelah membuat perubahan pada script, tekan 'Shift+R' untuk mereload game."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Tekan 'Shift+O' (Tulisan) untuk mengakses konsol."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Tekan 'Shift+D' Untuk mengakses menu developer."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Apakah kamu sudah membackup proyek kamu?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Gagal menjalankan proyek."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Tolong pastikan proyek mu berjalan normal sebelum menjalankan perintah ini."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py sedang menscan proyek..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Menjalankan"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "DIREKTORI PROYEK"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Tolong pilih direktori proyek menggunakan pemilih direktori.\n{b}Pemilih direktori mungkin terbuka di blakang window ini.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Launcher akan menscan proyek di direktori ini, akan membuat proyek baru di direktori ini, dan akan menaruh proyek yang telah di buat ke direktori ini."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py telah menset direktori proyek ke:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Terjemahan: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "Bahasa yang akan di kerjakan. Hanya boleh bersisi huruf-kecil ASCII karakter dan garis bawah."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Buat string kosong untuk terjemahan"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generate atau perebaharui file terjemahan. File akan di taruh di game/tl/[persistent.translate_language!q]"
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extrak Terjemahan String"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Satukan Terjemahan String"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Timpa Terjemahan Yang Sudah Ada"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Bahasa terbalik"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "Perintah extrak memungkinkan kamu untuk mengextrak terjemahan string dari proyek ke file sementara.\n\nPerintah merge menyatukan terjemahan yang di extrak ke proyek lain."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py sedang membuat terjemahan..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py telah selesai membuat terjemahan bahasa [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py sedang mengextrak string terjemahan..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py telah selesai mengextrak string terjemahan [language]."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py sedang menyatukan terjemahan string..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py telah selesai menyatukan string terjemahan [language]"
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extrak Dialog: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-terbatas Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Text Dialog Saja (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Buang tag text dari dialog."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "tanda kutip dan karakter khusus lainnya"
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extrak semua string yang dapat di terjemahkan, bukan haya dialog."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py sedang mengextrak dialog..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py sudah selesai mengextrak dialog. Dialog yang di extrak dapat di temukan di direktori dasar dialogue.[persistent.dialogue_format] ."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Pilih Channel Update"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Channel update mengkontrol versi yang akan di download oleh Ren'Py updater. Tolong pilih channel update:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Release"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Di Rekomendasikan.{/b} Versi Ren'Py yang seharus nya di gunakan oleh game yang baru di rilis."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Prerelease"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Cuplikan dari versi Ren'Py berikut nya yang dapaat di gunakan untuk testing dan mengambil keuntungan dari fitur baru, tapi bukan untuk rilis final game."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Percobaan"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Versi experimental dari Ren'Py. Kamu tidak seharusnya memilih channel ini, kecuali di minta oleh developer Ren'Py."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Update berdarah dari pengembangan Ren'Py. Ini mungikin mempunyai fitur terbaru. Bahkan tidak jalan sama sekali."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Kesalahan telah terjadi:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Mencek untuk update."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Renpy sudah up to date."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "Versi [u.version] sekarang tersedia. Apakah kamu ingin memasang nya?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Bersiap mendownload update."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Mendownload update."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Meng unpack update."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Finalisasi."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Update telah terpasang. Ren'Py akan restart."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Update telah di pasang."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Update telah di batalkan."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Update Ren'Py."
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Lanjut."
+
+translate indonesian strings:
+
+    # choose_directory.rpy:104
+    old "The selected projects directory is not writable."
+    new "Direktori proyek terpilih tidak dapat di tulis (not writable)"
+
+    # distribute.rpy:1061
+    old "Signing the Macintosh application...\n(This may take a long time.)"
+    new "Menandatangani aplikasi Macintosh...\n(Ini mungkin memakan waktu lama.)"
+
+    # front_page.rpy:91
+    old "PROJECTS:"
+    new "PROYEK:"
diff --git a/launcher/game/tl/indonesian/navigation.rpy b/launcher/game/tl/indonesian/navigation.rpy
deleted file mode 100644
index 24acf89..0000000
--- a/launcher/game/tl/indonesian/navigation.rpy
+++ /dev/null
@@ -1,71 +0,0 @@
-
-translate indonesian strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Navigasi: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Urutan:"
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "Alfabetical"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "Berdasarkan-file"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "Natural"
-
-    # game/navigation.rpy:168
-    old "refresh"
-    new "Segarkan"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Kategori:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "File"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "Label"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "Definisi"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "Transform"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "Layar"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "Panggilan"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODOs"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Tambahkan file script"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Tidak ada komentar TODO di temukan.\n\nUntuk membuat nya,Masukan \"# TODO\" ke dalam script."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "Daftar nama kosong."
-
diff --git a/launcher/game/tl/indonesian/new_project.rpy b/launcher/game/tl/indonesian/new_project.rpy
deleted file mode 100644
index eeac560..0000000
--- a/launcher/game/tl/indonesian/new_project.rpy
+++ /dev/null
@@ -1,76 +0,0 @@
-
-translate indonesian strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Pilih template proyek"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
-    new "Tolong pilih template untuk proyek baru mu. Ren'Py datang dengan template default yang  membuat game dengan menggunakan bahasa-Inggris dan layar standar."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "NAMA PROYEK"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Tolong masukan nama proyek mu:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "Nama proyek tidak boleh kosong"
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "Nama proyek [project_name!q] sudah tersedia, silahkan buat nama proyek yang berbeda."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] sudah tersedia, silahkan buat nama proyek yang berbeda."
-
-
-translate indonesian strings:
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Silahkan pilih template baru untuk proyek baru mu. Template set font deafult dan bahasa user interface. Jika bahasa mu tidak di dukung ,silahkan pilih 'english'."
-
-
-translate indonesian strings:
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Direktori proyek tidak bisa di set."
-
-
-translate indonesian strings:
-
-    # game/new_project.rpy:38
-    old "New GUI Interface"
-    new "Interface GUI Baru"
-
-    # game/new_project.rpy:48
-    old "Both interfaces have been translated to your language."
-    new "Kedua interface sudah di terjemahkan ke bahasa mu."
-
-    # game/new_project.rpy:50
-    old "Only the new GUI has been translated to your language."
-    new "Hanya gui baru yang sudah di terjemahkan ke bahasa mu."
-
-    # game/new_project.rpy:52
-    old "Only the legacy theme interface has been translated to your language."
-    new "Hanya tema legasi interface yang sudah di terjemahkan ke bahasa mu."
-
-    # game/new_project.rpy:54
-    old "Neither interface has been translated to your language."
-    new "Interface belum di terjemahkan ke bahsa mu."
-
-    # game/new_project.rpy:69
-    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
-    new "Interface mana yang ingin kamu gunakan? GUI baru memiliki tampilan moderen, mendukung layar lebar dan perangkat mobile, dan lebih mudah di kustomisasi. Tema legasi lebih di peruntukan untuk di gunakan dengan kode yang lama.\n\n[language_support!t]\n\nJika begitu, pilih GUI baru, dan klikk 'Lanjutkan' di pojok kanan bawah."
-
-    # game/new_project.rpy:69
-    old "Legacy Theme Interface"
-    new "Tema Interface Legacy"
-
diff --git a/launcher/game/tl/indonesian/obsolete.rpy b/launcher/game/tl/indonesian/obsolete.rpy
new file mode 100644
index 0000000..5dafad0
--- /dev/null
+++ b/launcher/game/tl/indonesian/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate indonesian strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Mapping Joystick"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Slot Kosong"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Sebelumnya"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Selanjutnya"
+
diff --git a/launcher/game/tl/indonesian/options.rpy b/launcher/game/tl/indonesian/options.rpy
index 0a8c3ad..97e72a2 100644
--- a/launcher/game/tl/indonesian/options.rpy
+++ b/launcher/game/tl/indonesian/options.rpy
@@ -1,206 +1,200 @@
 
 translate indonesian strings:
 
-    # gui/game/options.rpy:1
+    # options.rpy:1
     old "## This file contains options that can be changed to customize your game."
     new "## File ini berisi opsi yang dapat di ubah untuk mengkustomisasi game mu."
 
-    # gui/game/options.rpy:4
+    # options.rpy:4
     old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
     new "## Baris yang di awali dengan dua 'tanda '#' adalah komentar, dan kamu tidak seharusnya menghapus nya. Baris dengan satu '#' adalah kode yang di komentari, kamu dapat menghapus tanda '#' jika di butuhkan.    "
 
-    # gui/game/options.rpy:10
+    # options.rpy:10
+    old "## Basics"
+    new "## Dasar"
+
+    # options.rpy:12
     old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
     new "## Nama game yang dapat dibaca oleh manusia. Ini digunakan untuk menset judul jendela, dan juga di tampilkan di antarmuka dan laporan kesalahan. "
 
-    # gui/game/options.rpy:13
+    # options.rpy:15
     old "## The _() surrounding the string marks it as eligible for translation."
     new "## Tanda _() yang mengelilingi string menandai itu dapat di terjemahkan."
 
-    # gui/game/options.rpy:15
+    # options.rpy:17
     old "Ren'Py 7 Default GUI"
     new "Default GUI Ren'Py 7"
 
-    # gui/game/options.rpy:18
+    # options.rpy:20
     old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
     new "## Meng determinasikan apakah judul yang di berikan di atas di tampilkan di menu utama. Set ini ke False untuk menyembunyikan judul."
 
-    # gui/game/options.rpy:24
+    # options.rpy:26
     old "## The version of the game."
     new "## Versi Permainan."
 
-    # gui/game/options.rpy:29
+    # options.rpy:31
     old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
     new "## Text yang di taruh di layar tentang permainan. Untuk menambahkan baris kosong antara paragraf, tulis \\\n\n."
 
-    # gui/game/options.rpy:32
-    old ""
-    new ""
-
-    # gui/game/options.rpy:35
+    # options.rpy:37
     old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
     new "## Nama pendek permainan yang di gunakan untuk executable dan direktori di bangunan distribusi. Ini harus hanya berisi karakter ASCII-saja, dan tidak boleh mengandung  spasi, koma, atau kutip."
 
-    # gui/game/options.rpy:43
+    # options.rpy:44
     old "## Sounds and music"
     new "## Suara dan musik"
 
-    # gui/game/options.rpy:46
+    # options.rpy:46
     old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
     new "## Tiga variabel ini mengendalikan mixer yang mana yang di tampilkan ke pemain secara default. Menset salah satu dari ini ke False akan menyembunyikan mixer tersebut."
 
-    # gui/game/options.rpy:55
+    # options.rpy:55
     old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
     new "## Untuk mengijinkan pengguna memainkan test suara di chanel suara atau musik, silahkan hapus tag komentar nya '#' dan set sampel suara untuk di mainkan."
 
-    # gui/game/options.rpy:62
+    # options.rpy:62
     old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
     new "## Silahkan hapus komentar dari baris berikut ini untuk men set file audio yang akan di mainkan ketika pemain berada di menu utama. File ini akan terus dimainkan sampai permainan di mulai, sampai di hentikan atau file lain di mainkan."
 
-    # gui/game/options.rpy:70
+    # options.rpy:69
     old "## Transitions"
     new "## Transisi"
 
-    # gui/game/options.rpy:72
+    # options.rpy:71
     old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
     new "## Variabel ini menset transisi yang digunakan ketika event tertentu terjadi. Setiap variabel harus di set ke transisi, atau 'None' Untuk mengindikasikan bahwa tidak ada transisi yang harus di gunakan."
 
-    # gui/game/options.rpy:76
+    # options.rpy:75
     old "## Entering or exiting the game menu."
     new "## Memasuki atau keluar dari menu permainan."
 
-    # gui/game/options.rpy:82
+    # options.rpy:81
     old "## A transition that is used after a game has been loaded."
     new "## Transisi yang di gunakan setelah game di load."
 
-    # gui/game/options.rpy:87
+    # options.rpy:86
     old "## Used when entering the main menu after the game has ended."
     new "## Digunakan ketika memasuki menu utama setelah game berakhir."
 
-    # gui/game/options.rpy:92
+    # options.rpy:91
     old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
     new "## Variabel untuk menset transisi yang digunakan ketika mulai game tidak tersedia. Melainkan, menggunakan pernyataan with setelah menunjukan layar tertentu."
 
-    # gui/game/options.rpy:98
-    old "## Window management."
-    new "## Managemen jendela"
+    # options.rpy:96
+    old "## Window management"
+    new "## Managemen Jendela"
 
-    # gui/game/options.rpy:100
+    # options.rpy:98
     old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
     new "## Ini mengendalikan kapan dialog di tampilkan. Jika \"show\", berarti selalu di tampilkan. Juka \"hide\", berarti itu hanya di tampilkan ketika dialog tersedia. jika \"auto\", jendela di sembunyikan sebelum pernyataan scene dan di tunjukkan kembali jika dialog ditampilkan."
 
-    # gui/game/options.rpy:105
+    # options.rpy:103
     old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
     new "## Setelah permainan di mulai, ini dapat di ganti dengan pernyataan \"window show\", \"window hide\", dan \"window auto\"."
 
-    # gui/game/options.rpy:111
+    # options.rpy:109
     old "## Transitions used to show and hide the dialogue window"
     new "## Transisi yang digunakan untuk menunjukan dan menampilkan jendela dialog"
 
-    # gui/game/options.rpy:118
+    # options.rpy:115
     old "## Preference defaults"
     new "## Preferensi defaults"
 
-    # gui/game/options.rpy:120
+    # options.rpy:117
     old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
     new "## Mengendalikan kecepatan text default. Default nya, 0, ini berarti infiniti, Sementara angka yang lain adalah berapa karakter per detik yang akan di tampilkan."
 
-    # gui/game/options.rpy:126
+    # options.rpy:123
     old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
     new "## Delay default otomatis-maju. Nomor yang lebih besar berujung kepada waktu menunggu lebih lama, 0 sampai 30 adalah jarak yang valid."
 
-    # gui/game/options.rpy:133
+    # options.rpy:129
     old "## Save directory"
     new "## Direktori penyimpanan"
 
-    # gui/game/options.rpy:135
+    # options.rpy:131
     old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
     new "## Mengendalikan tempat penyimpanan file save untuk game ini secara spesifik untuk setiap platform. File akan di taruh di:"
 
-    # gui/game/options.rpy:138
+    # options.rpy:134
     old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
     new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
 
-    # gui/game/options.rpy:140
+    # options.rpy:136
     old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
     new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
 
-    # gui/game/options.rpy:142
+    # options.rpy:138
     old "## Linux: $HOME/.renpy/<config.save_directory>"
     new "## Linux: $HOME/.renpy/<config.save_directory>"
 
-    # gui/game/options.rpy:144
+    # options.rpy:140
     old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
     new "## Ini shearus nya tidak usah di ganti, dan juga iya, harus selalu berisi string, bukan expresi."
 
-## Updated At Aug 13 2016 17:05
-translate indonesian strings:
-
-    # gui/game/options.rpy:10
-    old "## Basics"
-    new "## Dasar"
-
-    # gui/game/options.rpy:96
-    old "## Window management"
-    new "## Managemen Jendela"
-
-    # gui/game/options.rpy:146
+    # options.rpy:146
     old "## Icon ########################################################################'"
     new "## Ikon ########################################################################'"
 
-    # gui/game/options.rpy:148
+    # options.rpy:148
     old "## The icon displayed on the taskbar or dock."
     new "## Ikon yang di tampilkan di taskbar atau dock."
 
-    # gui/game/options.rpy:153
+    # options.rpy:153
     old "## Build configuration"
     new "## Pengaturan Build"
 
-    # gui/game/options.rpy:155
+    # options.rpy:155
     old "## This section controls how Ren'Py turns your project into distribution files."
     new "## Bagian ini mengendalikan bagaimana Ren'Py mengubah proyek mu ke file distribusi."
 
-    # gui/game/options.rpy:160
+    # options.rpy:160
     old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
     new "## Fungsi berikut mengambil pola file. Pola file merupakan case- insensitiv, dan sama dengan arah direktori dasar, dengan atau tanpa awalan /. Jika banyak pola sama, yang pertama yang akan di gunakan."
 
-    # gui/game/options.rpy:165
+    # options.rpy:165
     old "## In a pattern:"
     new "## Di dalam pola:"
 
-    # gui/game/options.rpy:167
+    # options.rpy:167
     old "## / is the directory separator."
     new "## / Ini adlaah"
 
-    # gui/game/options.rpy:169
+    # options.rpy:169
     old "## * matches all characters, except the directory separator."
     new "## * mencocokan semua karakter, kecuali pemisah direktori."
 
-    # gui/game/options.rpy:171
+    # options.rpy:171
     old "## ** matches all characters, including the directory separator."
     new "## ** mencocokan semua karakter, termasuk pemisah direktori."
 
-    # gui/game/options.rpy:173
+    # options.rpy:173
     old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
     new "## Contohnya, \"*.txt\" mencocokan file txt di direktori dasar, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
 
-    # gui/game/options.rpy:177
+    # options.rpy:177
     old "## Classify files as None to exclude them from the built distributions."
     new "## Mengklasifikasi file sebagai None  untuk memisahkannya dari distribusi build."
 
-    # gui/game/options.rpy:185
+    # options.rpy:185
     old "## To archive files, classify them as 'archive'."
     new "## Untuk mengarsipkan file, mengklasifikasikannya sebagai 'archive'."
 
-    # gui/game/options.rpy:190
+    # options.rpy:190
     old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
     new "## Alur Dokumentasi pencocokan file di duplikasikan di build app mac, jadi mereka tampil di kedua aplikasi dan juga file zip."
 
-    # gui/game/options.rpy:196
+    # options.rpy:196
     old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
     new "## Kunci Lisensi Google Play di butuhkan untuk mendownload file tambahan dan untuk dapat melakukan pembelian in-app. Itu dapat di temukan di halaman \"Services & APIs\" delveloper konsol Google Play."
 
-    # gui/game/options.rpy:203
+    # options.rpy:203
     old "## The username and project name associated with an itch.io project, separated by a slash."
     new "## Nama pengguna dan nama proyek yang di asosiasikan dengan proyek itch.io, di pisahkan dengan garis miring."
 
+translate indonesian strings:
+
+    # options.rpy:146
+    old "## Icon"
+    new "## Ikon"
diff --git a/launcher/game/tl/indonesian/preferences.rpy b/launcher/game/tl/indonesian/preferences.rpy
deleted file mode 100644
index 5720f9f..0000000
--- a/launcher/game/tl/indonesian/preferences.rpy
+++ /dev/null
@@ -1,92 +0,0 @@
-
-translate indonesian strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Setting Launcher"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Direktori Proyek:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "Belum di Set"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Editor Text:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Channel Update:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Opsi Navigasi:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Ikutsertakan Nama Privat"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Ikutsertakan Nama Library"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Opsi Launcher:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Rendering Hardware"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "Output konsol"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "Buka proyek launcher"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "Bahasa:"
-
-
-translate indonesian strings:
-
-    # game/preferences.rpy:164
-    old "Show templates"
-    new "Tunjukkan template"
-
-
-translate indonesian strings:
-
-    # game/preferences.rpy:91
-    old "Projects directory: [text]"
-    new "Direktori proyek: [text]"
-
-    # game/preferences.rpy:114
-    old "Text editor: [text]"
-    new "Text editor: [text]"
-
-    # game/preferences.rpy:171
-    old "Large fonts"
-    new "Font besar"
-
-
-translate indonesian strings:
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "Tunjukan bagian edit file"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "Buat string kosong untuk terjemahan"
-
diff --git a/launcher/game/tl/indonesian/project.rpy b/launcher/game/tl/indonesian/project.rpy
deleted file mode 100644
index f16cff4..0000000
--- a/launcher/game/tl/indonesian/project.rpy
+++ /dev/null
@@ -1,65 +0,0 @@
-
-translate indonesian strings:
-
-    # game/project.rpy:196
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py sedang menscan proyek..."
-
-    # game/project.rpy:485
-    old "PROJECTS DIRECTORY"
-    new "DIREKTORI PROYEK"
-
-    # game/project.rpy:485
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Tolong pilih direktori proyek menggunakan pemilih direktori.\n{b}Pemilih direktori mungkin terbuka di blakang window ini.{/b}"
-
-    # game/project.rpy:485
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Launcher akan menscan proyek di direktori ini, akan membuat proyek baru di direktori ini, dan akan menaruh proyek yang telah di buat ke direktori ini."
-
-    # game/project.rpy:525
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py tidak dapat menjalankan python dengan tkinter untuk memilih direktori proyek."
-
-    # game/project.rpy:529
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py telah menset direktori proyek ke:"
-
-
-translate indonesian strings:
-
-    # game/project.rpy:48
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Setelah membuat perubahan pada script, tekan 'Shift+R' untuk mereload game."
-
-    # game/project.rpy:49
-    old "Press shift+O (the letter) to access the console."
-    new "Tekan 'Shift+O' (Tulisan) untuk mengakses konsol."
-
-    # game/project.rpy:50
-    old "Press shift+D to access the developer menu."
-    new "Tekan 'Shift+D' Untuk mengakses menu developer."
-
-    # game/project.rpy:219
-    old "Launching the project failed."
-    new "Gagal menjalankan proyek."
-
-    # game/project.rpy:219
-    old "Please ensure that your project launches normally before running this command."
-    new "Tolong pastikan proyek mu berjalan normal sebelum menjalankan perintah ini."
-
-    # game/project.rpy:516
-    old "Launching"
-    new "Menjalankan"
-
-    # game/project.rpy:585
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren'Py tidak dapat menjalankan python dengann tkinter untuk memilih direktori proyek. Tolong pasang python-tk atau package tkinter"
-
-
-translate indonesian strings:
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "Apakah kamu sudah membackup proyek kamu?"
-
diff --git a/launcher/game/tl/indonesian/screens.rpy b/launcher/game/tl/indonesian/screens.rpy
new file mode 100644
index 0000000..98cdb4f
--- /dev/null
+++ b/launcher/game/tl/indonesian/screens.rpy
@@ -0,0 +1,680 @@
+
+translate indonesian strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Kembali"
+
+    # screens.rpy:262
+    old "History"
+    new "Riwayat"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Lompati"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Otomatis"
+
+    # screens.rpy:265
+    old "Save"
+    new "Simpan"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Simpan.C"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Muat.C"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Setting"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Mulai"
+
+    # screens.rpy:316
+    old "Load"
+    new "Muat"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Setting"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "Akhiri Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Menu Utama"
+
+    # screens.rpy:328
+    old "About"
+    new "Tentang"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Bantuan"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Keluar"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Kembali"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Versi [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Dibuat Dengan {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Halaman {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Otomatis save"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Save cepat"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "Slot Kosong"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}O"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}C"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Tampilam"
+
+    # screens.rpy:739
+    old "Window"
+    new "Window"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Layar Penuh"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Arah Rollback"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Matikan"
+
+    # screens.rpy:746
+    old "Left"
+    new "Kiri"
+
+    # screens.rpy:747
+    old "Right"
+    new "Kanan"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Belum Terlihat"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Setelah Pilihan"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transisi"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Kecepatan Text"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Waktu Otomatis-Maju"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Volume Musik"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Volume Suara"
+
+    # screens.rpy:791
+    old "Test"
+    new "Tes"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Volume Suara"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Senyapkan Semua"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "Riwayat dialog kosong."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Papanketik"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Dialog tingkat lanjut dan mengaktifkan antarmuka."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Spasi"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Dialog tingkat lanjut tanpa memilih pilihan."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Tombol Panah"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigasi di antarmuka"
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Akses menu permainan."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Lompati dialog ketika di tahan."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Nyala/Matikan lompati dialog."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Putar mundur ke dialog sebelumnya."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Putar maju ke dialog berikut."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Sembunyikan antarmuka."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Ambiil tangkapan layar."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Nyalakan assisten {a=https://www.renpy.org/l/voicing}suara-sendiri{/a}"
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Klik Kiri"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Klik Tengah"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Klik Kanan"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Roda Mouse Atas\nKlik Arah Rollback"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Roda Mouse Bawah"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Trigger Kanan\nA/Tombol Bawah"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Dialog tingkat lanjut dan mengaktifkan antarmuka."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Putar mundur ke dialog sebelumnya"
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Pundak Kanan"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Putar maju ke dialog berikut"
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Stick"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Mulai, Panduan"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Akses menu permainan."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Tombol Atas"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Kalibrasi"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Layar Tambahan"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Layar konfirmasi"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## Layar konfirmasi di panggil ketika Ren'Py mau menanyakan ke pemain pertanyaan ya atau tidak."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Memastikan layar lain tidak mendapatkan input ketika layar ini di panggil."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Ya"
+
+    # screens.rpy:1162
+    old "No"
+    new "Tidak"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Klik kanan dan jawaban escape \"Tidak\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Lompati indikator layar"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## layar skip_indicator di tampilkan untuk mengindikasian proses skipping sedang dalam proses."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Melompati"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## transform digunakan untuk mengkedipkan panah setelah yang lain."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Layar pemberitahuan"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## layar notify digunakan untuk menampilkan pesan kepada pemain. (Seperti, ketika game di simpan cepat atau screenshot di ambil.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## Layar NVL"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## Layar ini digunakan untuk dialog dan menu mode-NVL."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Menampilkan dialog pada vpgrid atau vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Menampilkan menu, jika di berikan. Menu mungkin akan di tampilkan secara tidak benar jika config.narrator_menu di set ke True, seperti di atas."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## Ini mengendalikan angka maksimum entri mode-NVL yang dapat di tampilkan sekaligus."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Versi Mobile(HP/Handphone/Android)"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Semenjak mouse tidak ada, kami mengganti menu cepat dengan yang menggunakan tombol yang lebih besar dan sedikit, yang memudahkan untuk di sentuh."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
+translate indonesian strings:
+
+    # screens.rpy:120
+    old "## Jika ada gambar di sisi, tampilkan di atas text. Jangan tampilkan di versi HP[Handphone)(Android) - Karena tidak ada ruang."
+    new "## Jika "
+
+    # screens.rpy:252
+    old "## Ensure this appears on top of other screens."
+    new "## Memastikan ini muncul di atas layar yang lain."
+
+    # screens.rpy:291
+    old "## Main and Game Menu Screens"
+    new "## Layar Menu Utama dan Menu Permainan"
+
+    # screens.rpy:361
+    old "## This ensures that any other menu screen is replaced."
+    new "## Ini Memastikan Layar Menu Yang Lain Telah Di Timpa"
+
+    # screens.rpy:368
+    old "## This empty frame darkens the main menu."
+    new "## Frame kosong ini menggelap di menu utama."
+
+    # screens.rpy:439
+    old "## Reserve space for the navigation section."
+    new "## Memesan tempat untuk bagian navigasi."
+
+    # screens.rpy:619
+    old "## The page name, which can be edited by clicking on a button."
+    new "## Nama halaman, yang dapat di edit dengan mengklik tombol."
+
+    # screens.rpy:674
+    old "## range(1, 10) gives the numbers from 1 to 9."
+    new "## antara(1,10) beri nomor antara 1 sampai 9."
+
+    # screens.rpy:1079
+    old "Left Trigger\nLeft Shoulder"
+    new "Trigger Kiri\nBahu Kiri"
diff --git a/launcher/game/tl/indonesian/script.rpy b/launcher/game/tl/indonesian/script.rpy
deleted file mode 100644
index 7fd5da1..0000000
--- a/launcher/game/tl/indonesian/script.rpy
+++ /dev/null
@@ -1,31 +0,0 @@
-
-translate indonesian strings:
-
-    # gui/game/script.rpy:1
-    old "## The script of the game goes in this file."
-    new "## Script game di taruh di file ini."
-
-    # gui/game/script.rpy:3
-    old "## Declare characters used by this game. The color argument colorizes the name of the character."
-    new "## Mengdeklarasikan karakter yang di gunakan di game ini. Agrumen warna memberikan warna ke pada nama karakter."
-
-    # gui/game/script.rpy:9
-    old "## The game starts here."
-    new "## Game dimulai di sini."
-
-    # gui/game/script.rpy:13
-    old "## Show a background. This uses a placeholder by default, but you can add a file (named either \"bg room.png\" or \"bg room.jpg\") to the images directory to show it."
-    new "## Menunjukkan latar belakang. Ini digunakan untuk placeholder secara default, tapi kamu dapat menambakan file (yang di beri nama \"bg room.png\" atau \"bg room.jpg\") ke direktori gambar untuk menampilkan nya."
-
-    # gui/game/script.rpy:19
-    old "## This shows a character sprite. A placeholder is used, but you can replace it by adding a file named \"eileen happy.png\" to the images directory."
-    new "## Ini menunjukkan sprite karakter. Placeholder di gunakan, tapi kamu bisa mengganti nya dengan menamai nya \"eileen happy.png\" Ke direktori gambar."
-
-    # gui/game/script.rpy:25
-    old "## These display lines of dialogue."
-    new "## Ini menampilkan baris dialog."
-
-    # gui/game/script.rpy:33
-    old "## This ends the game."
-    new "## Ini mengakhiri permainan."
-
diff --git a/launcher/game/tl/indonesian/script.rpym b/launcher/game/tl/indonesian/script.rpym
new file mode 100644
index 0000000..f6fa475
--- /dev/null
+++ b/launcher/game/tl/indonesian/script.rpym
@@ -0,0 +1,18 @@
+# Kamu dapat taruh script game mu di file ini.
+
+# Deklarasikan gambar di bawah line ini, menggunakan pernyataan image.
+# cnth. image eileen happy = "eileen_happy.png"
+image bg blck = "images/blck.png"
+
+# Deklarasikan karakter yang digunakan di game.
+define e = Character('Eileen', color="#c8ffc8")
+
+# Game dimulai disini.
+label start:
+
+    scene bg blck with dissolve
+    e "Kamu telah membuat game Ren'Py baru."
+
+    e "Setelah kamu menambahkan cerita, gambar, dan musik, kamu bisa merilis nya ke dunia!"
+
+    return
diff --git a/launcher/game/tl/indonesian/style.rpy b/launcher/game/tl/indonesian/style.rpy
index c9d4aa1..b651d4c 100644
--- a/launcher/game/tl/indonesian/style.rpy
+++ b/launcher/game/tl/indonesian/style.rpy
@@ -1,16 +1,6 @@
 translate indonesian python:
-    idn = "DejaVuSans.ttf"
-    style.l_default.font = idn
-    style.l_default.size = 10
-    style.l_button_text.selected_font = idn
-    style.l_button_text.selected_bold = True
-    style.l_link_text.font = idn
-    style.l_alternate_text.font = idn
-    style.l_navigation_button_text.font = idn
-    style.l_navigation_text.font = idn
-    style.l_navigation_text.bold = True
-    style.l_checkbox_text.selected_font = idn
-    style.l_nonbox_text.selected_font = idn
-    style.hyperlink_text.font = idn
+    gui.REGULAR_FONT = "DejaVuSans.ttf"
+    gui.LIGHT_FONT = "DejaVuSans.ttf"
+    gui.FONT_SCALE = .9
+    gui.REGULAR_BOLD = True
 
-    config.rtl = True
diff --git a/launcher/game/tl/indonesian/translations.rpy b/launcher/game/tl/indonesian/translations.rpy
deleted file mode 100644
index bb1c942..0000000
--- a/launcher/game/tl/indonesian/translations.rpy
+++ /dev/null
@@ -1,121 +0,0 @@
-
-translate indonesian strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Buat atau Update Terjemahan"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Tolong buat nama dari bahasa yang mau kamu update terjemahan nya."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "Nama bahasa tidak boleh kosong."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Py sedang membuat terjemahan..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py telah selesai membuat terjemahan bahasa [language]."
-
-
-translate indonesian strings:
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "Format apa yang ingin kamu buat untuk dialog yang di extrak?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py sedang mengextrak dialog..."
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py telah selessai mengextrak dialog. Dialog yang di extrak dapat di temukan di dialog.[format] di direktori dasar."
-
-
-translate indonesian strings:
-
-    # game/translations.rpy:63
-    old "Translations: [project.current.name!q]"
-    new "Terjemahan: [project.current.name!q]"
-
-    # game/translations.rpy:104
-    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
-    new "Bahasa yang akan di kerjakan. Hanya boleh bersisi huruf-kecil ASCII karakter dan garis bawah."
-
-    # game/translations.rpy:148
-    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
-    new "Generate atau perebaharui file terjemahan. File akan di taruh di game/tl/[persistent.translate_language!q]"
-
-    # game/translations.rpy:168
-    old "Extract String Translations"
-    new "Extrak Terjemahan String"
-
-    # game/translations.rpy:170
-    old "Merge String Translations"
-    new "Satukan Terjemahan String"
-
-    # game/translations.rpy:175
-    old "Replace existing translations"
-    new "Timpa Terjemahan Yang Sudah Ada"
-
-    # game/translations.rpy:176
-    old "Reverse languages"
-    new "Bahasa terbalik"
-
-    # game/translations.rpy:194
-    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
-    new "Perintah extrak memungkinkan kamu untuk mengextrak terjemahan string dari proyek ke file sementara.\n\nPerintah merge menyatukan terjemahan yang di extrak ke proyek lain."
-
-    # game/translations.rpy:242
-    old "Ren'Py is extracting string translations..."
-    new "Ren'Py sedang mengextrak string terjemahan..."
-
-    # game/translations.rpy:245
-    old "Ren'Py has finished extracting [language] string translations."
-    new "Ren'Py telah selesai mengextrak string terjemahan [language]."
-
-    # game/translations.rpy:265
-    old "Ren'Py is merging string translations..."
-    new "Ren'Py sedang menyatukan terjemahan string..."
-
-    # game/translations.rpy:268
-    old "Ren'Py has finished merging [language] string translations."
-    new "Ren'Py telah selesai menyatukan string terjemahan [language]"
-
-    # game/translations.rpy:280
-    old "Extract Dialogue: [project.current.name!q]"
-    new "Extrak Dialog: [project.current.name!q]"
-
-    # game/translations.rpy:296
-    old "Format:"
-    new "Format:"
-
-    # game/translations.rpy:304
-    old "Tab-delimited Spreadsheet (dialogue.tab)"
-    new "Tab-terbatas Spreadsheet (dialogue.tab)"
-
-    # game/translations.rpy:305
-    old "Dialogue Text Only (dialogue.txt)"
-    new "Text Dialog Saja (dialogue.txt)"
-
-    # game/translations.rpy:318
-    old "Strip text tags from the dialogue."
-    new "Buang tag text dari dialog."
-
-    # game/translations.rpy:319
-    old "Escape quotes and other special characters."
-    new "tanda kutip dan karakter khusus lainnya"
-
-    # game/translations.rpy:320
-    old "Extract all translatable strings, not just dialogue."
-    new "Extrak semua string yang dapat di terjemahkan, bukan haya dialog."
-
-    # game/translations.rpy:352
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
-    new "Ren'Py sudah selesai mengextrak dialog. Dialog yang di extrak dapat di temukan di direktori dasar dialogue.[persistent.dialogue_format] ."
-
diff --git a/launcher/game/tl/indonesian/updater.rpy b/launcher/game/tl/indonesian/updater.rpy
deleted file mode 100644
index 0127f9e..0000000
--- a/launcher/game/tl/indonesian/updater.rpy
+++ /dev/null
@@ -1,98 +0,0 @@
-
-translate indonesian strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Pilih Channel Update"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Channel update mengkontrol versi yang akan di download oleh Ren'Py updater. Tolong pilih channel update:"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Release"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Di Rekomendasikan.{/b} Versi Ren'Py yang seharus nya di gunakan oleh game yang baru di rilis."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Prerelease"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Cuplikan dari versi Ren'Py berikut nya yang dapaat di gunakan untuk testing dan mengambil keuntungan dari fitur baru, tapi bukan untuk rilis final game."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Percobaan"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Versi experimental dari Ren'Py. Kamu tidak seharusnya memilih channel ini, kecuali di minta oleh developer Ren'Py."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Kesalahan telah terjadi:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Mencek untuk update."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Renpy sudah up to date."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "Versi [u.version] sekarang tersedia. Apakah kamu ingin memasang nya?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Bersiap mendownload update."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Mendownload update."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Meng unpack update."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Finalisasi."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "Update telah terpasang. Ren'Py akan restart."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "Update telah di pasang."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "Update telah di batalkan."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Update Ren'Py."
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Lanjut."
-
-
-translate indonesian strings:
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Update berdarah dari pengembangan Ren'Py. Ini mungikin mempunyai fitur terbaru. Bahkan tidak jalan sama sekali."
-
diff --git a/launcher/game/tl/italian/about.rpy b/launcher/game/tl/italian/about.rpy
deleted file mode 100644
index c7e8e9a..0000000
--- a/launcher/game/tl/italian/about.rpy
+++ /dev/null
@@ -1,9 +0,0 @@
-translate italian strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "Leggi licenza"
diff --git a/launcher/game/tl/italian/add_file.rpy b/launcher/game/tl/italian/add_file.rpy
deleted file mode 100644
index efd56ed..0000000
--- a/launcher/game/tl/italian/add_file.rpy
+++ /dev/null
@@ -1,21 +0,0 @@
-translate italian strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "Nome del file"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Inserisci il nome del file di script da creare."
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "Il file deve avere estensione .rpy."
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "Il file esiste già."
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py carica automaticamente tutti i file di script che finiscono con .rpy.\nPer usare questo file, definisci una label e saltaci (jump) da un altro file."
diff --git a/launcher/game/tl/italian/android.rpy b/launcher/game/tl/italian/android.rpy
deleted file mode 100644
index 4c5f34d..0000000
--- a/launcher/game/tl/italian/android.rpy
+++ /dev/null
@@ -1,162 +0,0 @@
-translate italian strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Per compilare un pacchetto di Android si prega di scaricare RAPT, estrarlo e posizionarlo nella cartella di Ren'Py e riavviare il launcher di Ren'Py."
-
-    # game/android.rpy:13
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "La versione a 32-bit del Java Development Kit é necessaria per compilare pacchetti Android su Windows. Il JDK é diverso dal JRE ed é quindi possibile che tu abbia installato Java senza però aver installato il JDK.\n\n Si prega di {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}scaricare ed installare il JDK{/a} e, successivamente, riavviare il launcher di Ren'Py."
-
-    # game/android.rpy:14
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Per compilare i pacchetti di Android, si prega di scaricare RAPT (da {a=http://www.renpy.org/dl/android}qui{/a}), estrarlo, posizionarlo nella cartella di Ren'Py ed infine riavviare il launcher di Ren'Py."
-
-    # game/android.rpy:15
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT é stato installato ma devi ancora installare l'Android SDK prima di poter compilare pacchetti per Android; scegli \"Install SDK\" per farlo."
-
-    # game/android.rpy:16
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT é stato installato ma la chiave non é stata configurata. Si prega di creare una chiave o di ripristinare android.keystore."
-
-    # game/android.rpy:17
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Il progetto corrente non é stato configurato. Usa \"Configura\" per configurarlo prima della compilazione."
-
-    # game/android.rpy:18
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Scegli \"Compila\" per compilare il progetto corrente o collega un dispositivo Android e scegli \"Compila ed Installa\" per compilarlo ed installarlo sul dispositivo."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Prova ad emulare un dispositivo Android.\n\nL'input tattile viene emulato attraverso il mouse e soltanto quando il tasto rimane premuto. Esc é assegnato al pulsante \"menu\" e PaginaSu é assegnato al pulsante \"indietro\"."
-
-    # game/android.rpy:21
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Prova ad emulare un tablet Android.\n\nL'input tattile viene emulato attraverso il mouse e soltanto quando il tasto é tenuto premuto. Esc é assegnato al pulsante \"menu\" e PaginaSu é assegnato al pulsante \"indietro\"."
-
-
-    # game/android.rpy:22
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Prova ad emulare una console OUYA.\n\nL'input del controller é assegnato alle freccie direzionali, Invio é assegnato al tasto \"select\", \"Esc\" é assegnato al tasto \"menu\" e PaginaSu é assegnato al tasto \"back\"."
-
-    # game/android.rpy:23
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Scarica ed installa l'Android SDK ed i pacchetti di supporto. Opzionalmente, genera le chiavi richieste per firmare il pacchetto."
-
-    # game/android.rpy:24
-    old "Configures the package name, version, and other information about this project."
-    new "Configure il nome del pacchetto, la versione ed altre informazioni su questo progetto."
-
-    # game/android.rpy:25
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Apre il file contenente le chiavi di Google Play nell'editor.\n\nQuesto serve solamente se l'applicazione sta usando un APK di espansione. Leggi la documentazione per maggiori dettagli."
-
-    # game/android.rpy:26
-    old "Builds the Android package."
-    new "Compila il pacchetto di Android."
-
-    # game/android.rpy:27
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Compila il pacchetto di Android e lo installa su un dispositivo connesso al tuo computer."
-
-    # game/android.rpy:148
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:157
-    old "QUESTION"
-    new "DOMANDA"
-
-    # game/android.rpy:367
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:387
-    old "Emulation:"
-    new "Emulazione:"
-
-    # game/android.rpy:395
-    old "Phone"
-    new "Telefono"
-
-    # game/android.rpy:399
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:403
-    old "Television / OUYA"
-    new "Televisione / OUYA"
-
-    # game/android.rpy:415
-    old "Build:"
-    new "Compila:"
-
-    # game/android.rpy:423
-    old "Install SDK & Create Keys"
-    new "Installa SDK e Crea Chiavi"
-
-    # game/android.rpy:427
-    old "Configure"
-    new "Configura"
-
-    # game/android.rpy:431
-    old "Build Package"
-    new "Compila pacchetto"
-
-    # game/android.rpy:435
-    old "Build & Install"
-    new "Compila ed Installa"
-
-    # game/android.rpy:486
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Prima di pacchettizzare le applicazioni di Android hai bisogno di scaricare RAPT (Ren'Py Android Packaging Tool). Vuoi scaricarlo adesso?"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Prova ed emulare una console connessa a televisore come OUYA o Fire TV.\n\nL'input del controller é assegnato alle freccie direzionali, Invio é assegnato al tasto \"select\", \"Esc\" é assegnato al tasto \"menu\" e PageUp é assegnato al tasto \"back\". "
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Connette ad un dispositivo Android che esegue ADB in modalità TCP/IP."
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Disconnette da un dispositivo Android che esegue ADB in modalità TCP/IP."
-
-    # game/android.rpy:516
-    old "Other:"
-    new "Altro:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "Connessione remota ad ADB"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "Disconessione remota da ADB"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "Indirizzo remoto di ADB"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Si prega di inserire l'indirizzo IP ed il numero della porta a cui connettersi nel formato \"192.168.1.143:5555\". Consulta le istruzioni del tuo dispositivo per determinare se questo supporta ADB e con quali numeri di indirizzo e porta."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "Indirizzo remoto di ADB invalido"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "L'indirizzo deve contenere esattamente un ':'."
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "L'host non può contenere spazi vuoti."
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "La porta deve essere un numero."
diff --git a/launcher/game/tl/italian/choose_theme.rpy b/launcher/game/tl/italian/choose_theme.rpy
deleted file mode 100644
index cff4752..0000000
--- a/launcher/game/tl/italian/choose_theme.rpy
+++ /dev/null
@@ -1,37 +0,0 @@
-translate italian strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Non é stato possibile cambiare il tema. Forse options.rpy é stato modificato troppo radicalmente."
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Schermo"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Finestra"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Schermo intero"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Volume audio"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Scegli tema"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "Tema"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "Schema di colore"
diff --git a/launcher/game/tl/italian/common.rpy b/launcher/game/tl/italian/common.rpy
index 9925c8e..cf6b3dc 100644
--- a/launcher/game/tl/italian/common.rpy
+++ b/launcher/game/tl/italian/common.rpy
@@ -1,498 +1,335 @@
-#translation: renpy/common/00action_file.rpy
+
 translate italian strings:
 
-    # renpy/common/00action_file.rpy:124
-    old "%b %d, %H:%M"
-    new "%d %b, %H:%M"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "Salvataggio rapido completato."
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-#translation: renpy/common/00gallery.rpy
-translate italian strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "Immagine [index] di [count] bloccata."
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "prec"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "succ"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "presentazione"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "ritorna"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-#translation: renpy/common/00gltest.rpy
-translate italian strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Accelerazione grafica"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Scegli automaticamente"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Forza renderer via Angle/DirectX"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "Forza renderer via OpenGL"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Forza renderer via software"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Le modifiche prenderanno effetto al prossimo avvio di questo programma."
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "Esci"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Ritorna"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Avviso di prestazioni"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Questo computer sta usando il rendering via software."
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Questo computer non fa uso degli shaders."
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Questo computer sta visualizzando la grafica lentamente."
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Questo computer ha un problema a visualizzare la grafica: [problem]."
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "I suoi driver video potrebbero essere vecchi o non funzionanti correttamente. Questo potrebbe portare a visualizzare la grafica lentamente o impropriamente. Aggiornare DirectX potrebbe risolvere questo problema."
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "I suoi driver video potrebbero essere vecchi o non funzionanti correttamente. Questo potrebbe portare a visualizzare la grafica lentamente o impropriamente."
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "Aggiorna DirectX"
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Continua, Mostra questo avviso nuovamente"
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Continua, Non mostrare più questo avviso"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "Aggiornando DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "Il programma di installazione web di DirectX è stato avviato e potrebbe essere minimizzato nella barra delle applicazioni. Prego seguire le istruzioni per installare DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Nota:{/b} Il programma di installazione web di DirectX di Microsoft proverà ad installare la barra di Bing. Per evitare che ciò accada, spunta l'opzione appropriata"
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "Una volta finita l'installazione, si prega di cliccare qui in basso per riavviare questo programma."
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Riavvia"
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
 
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
 
-#translation: renpy/common/00keymap.rpy
-translate italian strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
 
-    # renpy/common/00keymap.rpy:168
-    old "Saved screenshot as %s."
-    new "Screenshot salvato come %s."
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
-#translation: renpy/common/00layout.rpy
-translate italian strings:
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%d %b, %H:%M"
 
-    # renpy/common/00layout.rpy:421
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Salvataggio rapido completato."
+
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Confermi?"
 
-    # renpy/common/00layout.rpy:422
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Confermi di voler cancellare questo salvataggio?"
 
-    # renpy/common/00layout.rpy:423
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Confermi di voler sovrascrivere questo salvataggio?"
 
-    # renpy/common/00layout.rpy:424
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Caricare causerà la perdita di progressi non salvati.\n Confermi?"
 
-    # renpy/common/00layout.rpy:425
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Confermi di voler uscire?"
 
-    # renpy/common/00layout.rpy:426
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Confermi di voler tornare al menù principale?\nQuesto causerà la perdita di progressi non salvati."
 
-    # renpy/common/00layout.rpy:427
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Confermi di voler iniziare a saltare?"
 
-    # renpy/common/00layout.rpy:428
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Confermi di voler saltare alla prossima scelta?"
 
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Confermi di voler saltare al dialogo non letto o alla prossima scelta?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Screenshot salvato come %s."
 
-#translation: renpy/common/00library.rpy
-translate italian strings:
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
+
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
+
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
-    # renpy/common/00library.rpy:77
+    # 00library.rpy:179
     old "Skip Mode"
     new "Modalità salto"
 
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Modalità salto rapido"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Clipboard voicing abilitato. Premi 'shift+C' per disabilitarlo."
 
-#translation: renpy/common/00updater.rpy
-translate italian strings:
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Self-voicing abilitato. Premi 'v' per disabilitarlo."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
+
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "L'aggiornamento di Ren'Py non è supportato nei dispositivi mobili."
+
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "Un errore viene simulato."
+
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "O questo progetto non supporta l'aggiornamento, o è stato cancellato il file col suo stato."
+
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "Questo account non ha i permessi per effettuare un aggiornamento."
+
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "Questo account non ha i permessi per scrivere il log degli aggiornamenti."
 
-    # renpy/common/00updater.rpy:1258
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "La firma per l'aggiornamento non può essere verificata."
+
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "Il file di aggiornamento non è stato scaricato."
+
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "Il file di aggiornamento non ha il digest corretto - potrebbe essere corrotto."
+
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "Durante lo spacchettamento {}, tipo sconosciuto {}."
+
+    # 00updater.rpy:1393
     old "Updater"
     new "Updater"
 
-    # renpy/common/00updater.rpy:1267
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Questo programma è aggiornato."
 
-    # renpy/common/00updater.rpy:1269
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] è disponibile. Vuoi installarla?"
 
-    # renpy/common/00updater.rpy:1271
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Preparando lo scaricamento dell'aggiornamento."
 
-    # renpy/common/00updater.rpy:1273
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Scaricando l'aggiornamento."
 
-    # renpy/common/00updater.rpy:1275
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Estraendo l'aggiornamento."
 
-    # renpy/common/00updater.rpy:1279
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "L'aggiornamento è stato installato. Il programma verrà riavviato."
 
-    # renpy/common/00updater.rpy:1281
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "L'aggiornamento è stato installato."
 
-    # renpy/common/00updater.rpy:1283
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "L'aggiornamento è stato annullato."
 
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Immagine [index] di [count] bloccata."
 
-#translation: renpy/common/_compat/gamemenu.rpym
-translate italian strings:
-
-    # renpy/common/_compat/gamemenu.rpym:180
-    old "Empty Slot."
-    new "Slot Vuoto."
-
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Precedente"
-
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Successivo"
-
-
-#translation: renpy/common/_compat/preferences.rpym
-translate italian strings:
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "Mapping del Joystick"
-
-
-#translation: renpy/common/_errorhandling.rpym
-translate italian strings:
-
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "Si è verificata un'eccezione."
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Regredisci"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Prova a regredire ad una data precedente, permettendoti di salvare o selezionare un'altra scelta."
-
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "Ignora"
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Ignore l'eccezione, permettendoti di continuare. Spesso introduce nuovi errori."
-
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "Ricarica"
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Ricarica il gioco dal disco, salvando e ripristinando lo stato di gioco se possibile."
-
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "Apri Traceback"
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Apri il file traceback.txt in un editor di testo."
-
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "Esce dal gioco."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "L'analisi dello script ha fallito."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Apri errori di analisi"
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Apre il file errors.txt in un editor di testo."
-
-
-#translation: renpy/common/_layout/classic_load_save.rpym
-translate italian strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
-
-    # renpy/common/_developer/inspector.rpym:25
-    old "Displayable Inspector"
-    new "Ispettore di displayable"
-
-    # renpy/common/_developer/inspector.rpym:31
-    old "Nothing to inspect."
-    new "Niente da ispezionare."
-
-    # renpy/common/_developer/inspector.rpym:40
-    old "Size"
-    new "Dimensione"
-
-    # renpy/common/_developer/inspector.rpym:45
-    old "Style"
-    new "Stile"
-
-    # renpy/common/_developer/inspector.rpym:105
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Ispezionando stili di [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:117
-    old "displayable:"
-    new "visualizzabile:"
-
-    # renpy/common/_developer/inspector.rpym:124
-    old "        (no properties affect the displayable)"
-    new "        (nessuna proprietà ha effetto sul displayable)"
-
-    # renpy/common/_developer/inspector.rpym:126
-    old "        (default properties omitted)"
-    new "        (proprietà predefinite omesse)"
-
-    # renpy/common/_developer/inspector.rpym:156
-    old "<repr() failed>"
-    new "<repr() fallito>"
-
-    # renpy/common/_developer/developer.rpym:46
-    old "Reload Game (Shift+R)"
-    new "Ricarica Gioco (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:49
-    old "Variable Viewer"
-    new "Visualizzatore di variabili"
-
-    # renpy/common/_developer/developer.rpym:52
-    old "Theme Test"
-    new "Prova tema"
-
-    # renpy/common/_developer/developer.rpym:58
-    old "Image Location Picker"
-    new "Selettore dell'ubicazione delle immagini"
-
-    # renpy/common/_developer/developer.rpym:61
-    old "Filename List"
-    new "Lista dei file"
-
-    # renpy/common/_developer/developer.rpym:307
-    old "Undefined Images"
-    new "Immagini non definite"
-
-    # renpy/common/_developer/developer.rpym:410
-    old "Mouse position: %r"
-    new "Posizione del mouse: %r"
-
-    # renpy/common/_developer/developer.rpym:412
-    old "Right-click or escape to quit."
-    new "Click destro o Esc per uscire."
-
-    # renpy/common/_developer/developer.rpym:465
-    old "Done"
-    new "Fatto"
-
-    # renpy/common/_developer/developer.rpym:44
-    old "Developer Menu"
-    new "Menù dello sviluppatore"
-
-    # renpy/common/_developer/developer.rpym:405
-    old "Rectangle: %r"
-    new "Rettangolo: %r"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Console (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Mostra log di caricamento delle immagini"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Nascondi log di caricamento delle immagini"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "Nessuna variabile è stata cambiata dall'ultima esecuzione del gioco."
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "Ritorna al menù dello sviluppatore"
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "Versione della console %(version)s, autori originali Shiz, C e delta.\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Premi <esc> per uscire dalla console. Scrivi \"help\" per aiuto.\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "Script di Ren'Py abilitato."
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "Script di Ren'Py disabilitato."
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: mostra questo aiuto"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "comandi:\n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new " <comando renpy script>: esegui il comando\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <espressione o comando python>: esegui l'espressione o il comando"
-
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: pulisci la cronologia della console"
-
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: esci dalla console"
-
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: carica il gioco dallo slot"
-
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: salva il gioco nello slot"
-
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: ricarica il gioco, aggiornando gli script"
-
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <espressione>: osserva un'espressione Python"
-
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <espressione>: smetti di osservare un'espressione"
+    # 00gallery.rpy:583
+    old "prev"
+    new "prec"
 
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: smetti di osservare tutte le espressioni"
+    # 00gallery.rpy:584
+    old "next"
+    new "succ"
 
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: salta alla label"
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "presentazione"
 
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}Immagini mancanti{/b}"
+    # 00gallery.rpy:586
+    old "return"
+    new "ritorna"
 
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "Autoricarica"
diff --git a/launcher/game/tl/italian/developer.rpy b/launcher/game/tl/italian/developer.rpy
new file mode 100644
index 0000000..aeb375d
--- /dev/null
+++ b/launcher/game/tl/italian/developer.rpy
@@ -0,0 +1,179 @@
+
+translate italian strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Menù dello sviluppatore"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Ricarica Gioco (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Console (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Visualizzatore di variabili"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Prova tema"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Selettore dell'ubicazione delle immagini"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Lista dei file"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Mostra log di caricamento delle immagini"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Nascondi log di caricamento delle immagini"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Niente da ispezionare."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Ritorna al menù dello sviluppatore"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rettangolo: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Posizione del mouse: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Click destro o Esc per uscire."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rettangolo copiato nella clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Posizione copiata nella clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Ispettore di displayable"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Dimensione"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Stile"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Posizione"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Ispezionando stili di [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "visualizzabile:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (nessuna proprietà ha effetto sul displayable)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (proprietà predefinite omesse)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() fallito>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Premi <esc> per uscire dalla console. Scrivi \"help\" per aiuto.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Script di Ren'Py abilitato."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Script di Ren'Py disabilitato."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: mostra questo aiuto"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "comandi:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <comando renpy script>: esegui il comando\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <espressione o comando python>: esegui l'espressione o il comando"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: pulisci la cronologia della console"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: esci dalla console"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: carica il gioco dallo slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: salva il gioco nello slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: ricarica il gioco, aggiornando gli script"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <espressione>: osserva un'espressione Python"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <espressione>: smetti di osservare un'espressione"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: smetti di osservare tutte le espressioni"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: salta alla label"
+
diff --git a/launcher/game/tl/italian/distribute.rpy b/launcher/game/tl/italian/distribute.rpy
deleted file mode 100644
index 32b9c4b..0000000
--- a/launcher/game/tl/italian/distribute.rpy
+++ /dev/null
@@ -1,37 +0,0 @@
-translate italian strings:
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Nessun pacchetto selezionato, nessun compito da eseguire."
-
-    # game/distribute.rpy:363
-    old "Scanning project files..."
-    new "Analizzando i file del progetto..."
-
-    # game/distribute.rpy:373
-    old "Scanning Ren'Py files..."
-    new "Analizzando i file di Ren'Py..."
-
-    # game/distribute.rpy:421
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Tutti i pacchetti sono stati compilati.\n\nData la presenza di informazioni sui permessi, estrarre e ri-archiviare le distribuzioni Linux e Macintosh su Windows non é supportato."
-
-    # game/distribute.rpy:545
-    old "Archiving files..."
-    new "Archiviando i file..."
-
-    # game/distribute.rpy:801
-    old "Writing the [variant] [format] package."
-    new "Scrivendo il pacchetto [variant] [format]."
-
-    # game/distribute.rpy:814
-    old "Making the [variant] update zsync file."
-    new "Creando il file di aggiornamento di zync per [variant]"
-
-    # game/distribute.rpy:910
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Processati {b}[complete]{/b} file su {b}[total]{/b}."
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Compilazione delle distribuzioni fallita:\n\nLa variable build.directory_name non può includere spazi, due punti e punti e virgole."
diff --git a/launcher/game/tl/italian/distribute_gui.rpy b/launcher/game/tl/italian/distribute_gui.rpy
deleted file mode 100644
index 51e0f12..0000000
--- a/launcher/game/tl/italian/distribute_gui.rpy
+++ /dev/null
@@ -1,45 +0,0 @@
-translate italian strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Compila distrubuzioni: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Nome della cartella:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Nome dell'eseguibile:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "Azioni:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "Modifica options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Aggiorna"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Compila pacchetti:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "Compila aggiornamenti"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "Compila"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Errori riscontrati durante l'esecuzione del progetto. Prego assicurarsi che il progetto possa essere eseguito senza errori prima di compilare distrubuzioni."
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Il tuo progetto non contiene informazioni di compilazione. Vuoi aggiungere informazioni di compilazione alla fine di options.rpy?"
diff --git a/launcher/game/tl/italian/editor.rpy b/launcher/game/tl/italian/editor.rpy
deleted file mode 100644
index 71b13ee..0000000
--- a/launcher/game/tl/italian/editor.rpy
+++ /dev/null
@@ -1,65 +0,0 @@
-translate italian strings:
-
-    # description for the option: "Editra"
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Raccomandato.{/b} Un editor in fase Beta con un'interfaccia facile da usare e funzionalità adatte allo sviluppo come il controllo ortografico. Editra al momento non ha il supporto IMO richiesto per Cinese, Giapponese e Coreano."
-
-
-    # description for "Editra" on Linux
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Raccomandato.{/b} Un editor in fase Beta con un'interfaccia facile da usare e funzionalità adatte allo sviluppo come il controllo ortografico. Editra al momento non ha il supporto IMO richiesto per Cinese, Giapponese e Coreano e richiede wxPython su Linux."
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Potrebbe essersi verificato per via dell'assenza di wxPython su questo sistema."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Richiesti fino a 22 MB."
-
-    # description for the option: "JEdit"
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Un editor maturo che richiede Java."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "Download di 1.8 MB richiesto."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Potrebbe essersi verificato per l'assenza di Java su questo sistema."
-
-    # option: "System Editor"
-    # game/editor.rpy:163
-    old "System Editor"
-    new "Editor di sistema"
-
-    # description for the option: "System Editor"
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Invoca l'editor che il tuo sistema operativo ha associato con i file .rpy."
-
-    # option: "None"
-    # game/editor.rpy:179
-    old "None"
-    new "Nessuno"
-
-    # description for the option: "None"
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Non permette a Ren'Py di aprire un editor di testo."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Si é verificata un'eccezione durante il lancio dell'editor:\n[exception!q]"
-
-    # game/editor.rpy:423
-    old "Select Editor"
-    new "Seleziona editor"
-
-    # game/editor.rpy:438
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "L'editor di testo é il programma che viene usato per modificare i file di script di Ren'Py. Qui puoi selezionare l'editor da usare con Ren'Py. Se assente, l'editor verrà automaticamente scaricato ed installato."
diff --git a/launcher/game/tl/italian/error.rpy b/launcher/game/tl/italian/error.rpy
new file mode 100644
index 0000000..f191d0d
--- /dev/null
+++ b/launcher/game/tl/italian/error.rpy
@@ -0,0 +1,179 @@
+
+translate italian strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Accelerazione grafica"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Scegli automaticamente"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Forza renderer via Angle/DirectX"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Forza renderer via OpenGL"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Forza renderer via software"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Le modifiche prenderanno effetto al prossimo avvio di questo programma."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Avviso di prestazioni"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Questo computer sta usando il rendering via software."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Questo computer non fa uso degli shaders."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Questo computer sta visualizzando la grafica lentamente."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Questo computer ha un problema a visualizzare la grafica: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "I suoi driver video potrebbero essere vecchi o non funzionanti correttamente. Questo potrebbe portare a visualizzare la grafica lentamente o impropriamente. Aggiornare DirectX potrebbe risolvere questo problema."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "I suoi driver video potrebbero essere vecchi o non funzionanti correttamente. Questo potrebbe portare a visualizzare la grafica lentamente o impropriamente."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Aggiorna DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Continua, Mostra questo avviso nuovamente"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Continua, Non mostrare più questo avviso"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Aggiornando DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Il programma di installazione web di DirectX è stato avviato e potrebbe essere minimizzato nella barra delle applicazioni. Prego seguire le istruzioni per installare DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Nota:{/b} Il programma di installazione web di DirectX di Microsoft proverà ad installare la barra di Bing. Per evitare che ciò accada, spunta l'opzione appropriata"
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Una volta finita l'installazione, si prega di cliccare qui in basso per riavviare questo programma."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Riavvia"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Apri Traceback"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Apri il file traceback.txt in un editor di testo."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Si è verificata un'eccezione."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Regredisci"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Prova a regredire ad una data precedente, permettendoti di salvare o selezionare un'altra scelta."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Ignora"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Ignore l'eccezione, permettendoti di continuare. Spesso introduce nuovi errori."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Ricarica"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Ricarica il gioco dal disco, salvando e ripristinando lo stato di gioco se possibile."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Esce dal gioco."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "L'analisi dello script ha fallito."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Apri errori di analisi"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Apre il file errors.txt in un editor di testo."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/italian/front_page.rpy b/launcher/game/tl/italian/front_page.rpy
deleted file mode 100644
index c4d6ccb..0000000
--- a/launcher/game/tl/italian/front_page.rpy
+++ /dev/null
@@ -1,93 +0,0 @@
-translate italian strings:
-
-    # game/font_page.rpy 65
-    old "PROJECTS:"
-    new "PROGETTI:"
-
-    # game/front_page.rpy:67
-    old "refresh"
-    new "aggiorna"
-
-    # game/front_page.rpy:94
-    old "+ Create New Project"
-    new "+ Crea un nuovo progetto"
-
-    # game/front_page.rpy:106
-    old "Launch Project"
-    new "Avvia progetto"
-
-    # game/front_page.rpy:122
-    old "[p.name!q] (template)"
-    new "[p.name!q] (modello)"
-
-    # game/front_page.rpy:127
-    old "Tutorial"
-    new "Tutorial"
-
-    # game/front_page.rpy:128
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:144
-    old "Active Project"
-    new "Progetto attivo"
-
-    # game/front_page.rpy:152
-    old "Open Directory"
-    new "Apri cartella"
-
-    # game/front_page.rpy:157
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:158
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:164
-    old "Edit File"
-    new "Modifica file"
-
-    # game/front_page.rpy:172
-    old "All script files"
-    new "Tutti i file di script"
-
-    # game/front_page.rpy:181
-    old "Navigate Script"
-    new "Naviga script"
-
-    # game/front_page.rpy:192
-    old "Check Script (Lint)"
-    new "Controlla script (Lint)"
-
-    # game/front_page.rpy:193
-    old "Change Theme"
-    new "Cambia tema"
-
-    # game/front_page.rpy:194
-    old "Delete Persistent"
-    new "Cancella dati persistenti"
-
-    # game/front_page.rpy:202
-    old "Build Distributions"
-    new "Compila distribuzioni"
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:205
-    old "Generate Translations"
-    new "Genera traduzioni"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "Estrai dialoghi"
-
-    # game/front_page.rpy:222
-    old "Checking script for potential problems..."
-    new "Controllando lo script per potenziali problemi..."
-
-    # game/front_page.rpy:237
-    old "Deleting persistent data..."
-    new "Eliminando dati persistenti..."
diff --git a/launcher/game/tl/italian/gui.rpy b/launcher/game/tl/italian/gui.rpy
new file mode 100644
index 0000000..d3b56df
--- /dev/null
+++ b/launcher/game/tl/italian/gui.rpy
@@ -0,0 +1,411 @@
+
+translate italian strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/italian/interface.rpy b/launcher/game/tl/italian/interface.rpy
deleted file mode 100644
index 21b0bea..0000000
--- a/launcher/game/tl/italian/interface.rpy
+++ /dev/null
@@ -1,93 +0,0 @@
-translate italian strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Documentazione"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Sito di Ren'Py"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Lista dei giochi Ren'Py"
-
-    # game/interface.rpy:92
-    old "About"
-    new "Informazioni"
-
-    # game/interface.rpy:99
-    old "update"
-    new "aggiorna"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "preferenze"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "esci"
-
-    # game/interface.rpy:174
-    old "Yes"
-    new "Si"
-
-    # game/interface.rpy:176
-    old "No"
-    new "No"
-
-    # game/interface.rpy:182
-    old "Back"
-    new "Indietro"
-
-    # game/interface.rpy:184
-    old "Cancel"
-    new "Annulla"
-
-    # game/interface.rpy:187
-    old "Continue"
-    new "Continua"
-
-    # game/interface.rpy:211
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Per via delle limitazioni del formato del pacchetto, file e cartelle con nomi non-ASCII non sono permessi."
-
-    # game/interface.rpy:213
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:299
-    old "ERROR"
-    new "ERRORE"
-
-    # game/interface.rpy:328
-    old "While [what!q], an error occured:"
-    new "Durante [what!q], si é verificato un errore:"
-
-    # game/interface.rpy:329
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:347
-    old "Text input may not contain the {{ or [[ characters."
-    new "Il testo inserito non può contenere i caratteri {{ o [[."
-
-    # game/interface.rpy:352
-    old "File and directory names may not contain / or \\."
-    new "I nomi di file e cartelle non possono contenere / o \\."
-
-    # game/interface.rpy:358
-    old "File and directory names must consist of ASCII characters."
-    new "I nomi di file e cartelle possono solo contenere caratteri ASCII."
-
-    # game/interface.rpy:379
-    old "INFORMATION"
-    new "INFORMAZIONE"
-
-    # game/interface.rpy:422
-    old "PROCESSING"
-    new "PROCESSANDO"
-
-    # game/interface.rpy:452
-    old "CHOICE"
-    new "SELEZIONA"
diff --git a/launcher/game/tl/italian/launcher.rpy b/launcher/game/tl/italian/launcher.rpy
new file mode 100644
index 0000000..a326493
--- /dev/null
+++ b/launcher/game/tl/italian/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate italian strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Leggi licenza"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "Nome del file"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Inserisci il nome del file di script da creare."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Il file deve avere estensione .rpy."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Il file esiste già."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py carica automaticamente tutti i file di script che finiscono con .rpy.\nPer usare questo file, definisci una label e saltaci (jump) da un altro file."
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Per compilare un pacchetto di Android si prega di scaricare RAPT, estrarlo e posizionarlo nella cartella di Ren'Py e riavviare il launcher di Ren'Py."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "La versione a 32-bit del Java Development Kit é necessaria per compilare pacchetti Android su Windows. Il JDK é diverso dal JRE ed é quindi possibile che tu abbia installato Java senza però aver installato il JDK.\n\n Si prega di {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}scaricare ed installare il JDK{/a} e, successivamente, riavviare il launcher di Ren'Py."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT é stato installato ma devi ancora installare l'Android SDK prima di poter compilare pacchetti per Android; scegli \"Install SDK\" per farlo."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT é stato installato ma la chiave non é stata configurata. Si prega di creare una chiave o di ripristinare android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Il progetto corrente non é stato configurato. Usa \"Configura\" per configurarlo prima della compilazione."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Scegli \"Compila\" per compilare il progetto corrente o collega un dispositivo Android e scegli \"Compila ed Installa\" per compilarlo ed installarlo sul dispositivo."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Prova ad emulare un dispositivo Android.\n\nL'input tattile viene emulato attraverso il mouse e soltanto quando il tasto rimane premuto. Esc é assegnato al pulsante \"menu\" e PaginaSu é assegnato al pulsante \"indietro\"."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Prova ad emulare un tablet Android.\n\nL'input tattile viene emulato attraverso il mouse e soltanto quando il tasto é tenuto premuto. Esc é assegnato al pulsante \"menu\" e PaginaSu é assegnato al pulsante \"indietro\"."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Prova ed emulare una console connessa a televisore come OUYA o Fire TV.\n\nL'input del controller é assegnato alle freccie direzionali, Invio é assegnato al tasto \"select\", \"Esc\" é assegnato al tasto \"menu\" e PageUp é assegnato al tasto \"back\". "
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Scarica ed installa l'Android SDK ed i pacchetti di supporto. Opzionalmente, genera le chiavi richieste per firmare il pacchetto."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Configure il nome del pacchetto, la versione ed altre informazioni su questo progetto."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Apre il file contenente le chiavi di Google Play nell'editor.\n\nQuesto serve solamente se l'applicazione sta usando un APK di espansione. Leggi la documentazione per maggiori dettagli."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Compila il pacchetto di Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Compila il pacchetto di Android e lo installa su un dispositivo connesso al tuo computer."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Connette ad un dispositivo Android che esegue ADB in modalità TCP/IP."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Disconnette da un dispositivo Android che esegue ADB in modalità TCP/IP."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Emulazione:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Telefono"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Television"
+
+    # android.rpy:353
+    old "Build:"
+    new "Compila:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Installa SDK e Crea Chiavi"
+
+    # android.rpy:365
+    old "Configure"
+    new "Configura"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Compila pacchetto"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Compila ed Installa"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Build, Install & Launch"
+
+    # android.rpy:388
+    old "Other:"
+    new "Altro:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Connessione remota ad ADB"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Disconessione remota da ADB"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Prima di pacchettizzare le applicazioni di Android hai bisogno di scaricare RAPT (Ren'Py Android Packaging Tool). Vuoi scaricarlo adesso?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Indirizzo remoto di ADB"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Si prega di inserire l'indirizzo IP ed il numero della porta a cui connettersi nel formato \"192.168.1.143:5555\". Consulta le istruzioni del tuo dispositivo per determinare se questo supporta ADB e con quali numeri di indirizzo e porta."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Indirizzo remoto di ADB invalido"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "L'indirizzo deve contenere esattamente un ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "L'host non può contenere spazi vuoti."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "La porta deve essere un numero."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Non é stato possibile cambiare il tema. Forse options.rpy é stato modificato troppo radicalmente."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Scegli tema"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Tema"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Schema di colore"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Continua"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMAZIONE"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Analizzando i file del progetto..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Compilazione delle distribuzioni fallita:\n\nLa variable build.directory_name non può includere spazi, due punti e punti e virgole."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Nessun pacchetto selezionato, nessun compito da eseguire."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Analizzando i file di Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Tutti i pacchetti sono stati compilati.\n\nData la presenza di informazioni sui permessi, estrarre e ri-archiviare le distribuzioni Linux e Macintosh su Windows non é supportato."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Archiviando i file..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Scrivendo il pacchetto [variant] [format]."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Creando il file di aggiornamento di zync per [variant]"
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Processati {b}[complete]{/b} file su {b}[total]{/b}."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Compila distrubuzioni: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Nome della cartella:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Nome dell'eseguibile:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Azioni:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Modifica options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Add from clauses to calls, once"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Aggiorna"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Compila pacchetti:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Options:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Compila aggiornamenti"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Add from clauses to calls"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Force Recompile"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Compila"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Adding from clauses to call statements that do not have them."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Errori riscontrati durante l'esecuzione del progetto. Prego assicurarsi che il progetto possa essere eseguito senza errori prima di compilare distrubuzioni."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Il tuo progetto non contiene informazioni di compilazione. Vuoi aggiungere informazioni di compilazione alla fine di options.rpy?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Raccomandato.{/b} Un editor in fase Beta con un'interfaccia facile da usare e funzionalità adatte allo sviluppo come il controllo ortografico. Editra al momento non ha il supporto IMO richiesto per Cinese, Giapponese e Coreano."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Raccomandato.{/b} Un editor in fase Beta con un'interfaccia facile da usare e funzionalità adatte allo sviluppo come il controllo ortografico. Editra al momento non ha il supporto IMO richiesto per Cinese, Giapponese e Coreano e richiede wxPython su Linux."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Potrebbe essersi verificato per via dell'assenza di wxPython su questo sistema."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Richiesti fino a 22 MB."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Un editor maturo che richiede Java."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "Download di 1.8 MB richiesto."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Potrebbe essersi verificato per l'assenza di Java su questo sistema."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Invoca l'editor che il tuo sistema operativo ha associato con i file .rpy."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Non permette a Ren'Py di aprire un editor di testo."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Si é verificata un'eccezione durante il lancio dell'editor:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Seleziona editor"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "L'editor di testo é il programma che viene usato per modificare i file di script di Ren'Py. Qui puoi selezionare l'editor da usare con Ren'Py. Se assente, l'editor verrà automaticamente scaricato ed installato."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Cancelar"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Open [text] directory."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "aggiorna"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Crea un nuovo progetto"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Avvia progetto"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (modello)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Select project [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Progetto attivo"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Apri cartella"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Modifica file"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Tutti i file di script"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Naviga script"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Controlla script (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Cambia tema"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Cancella dati persistenti"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Compila distribuzioni"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Genera traduzioni"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Estrai dialoghi"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Controllando lo script per potenziali problemi..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Eliminando dati persistenti..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Recompiling all rpy files into rpyc files..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "NOME DEL PROGETTO"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Inserisci il nome del tuo progetto:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Il nome del progetto non può essere nullo."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] esiste già. Si prega scegliere un altro nome."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] esiste già. Si prega di scegliere un altro nome."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Documentazione"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Sito di Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Lista dei giochi Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "aggiorna"
+
+    # interface.rpy:119
+    old "preferences"
+    new "preferenze"
+
+    # interface.rpy:120
+    old "quit"
+    new "esci"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Per via delle limitazioni del formato del pacchetto, file e cartelle con nomi non-ASCII non sono permessi."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ERRORE"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Durante [what!q], si é verificato un errore:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Il testo inserito non può contenere i caratteri {{ o [[."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "I nomi di file e cartelle non possono contenere / o \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "I nomi di file e cartelle possono solo contenere caratteri ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "PROCESSANDO"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "DOMANDA"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "SELEZIONA"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Selects the directory where Xcode projects will be placed."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Creates an Xcode project corresponding to the current Ren'Py project."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Opens the Xcode project in Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Opens the directory containing Xcode projects."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Select Xcode Projects Directory"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Create Xcode Project"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Update Xcode Project"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Launch Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Open Xcode Projects Directory"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py has set the Xcode Projects Directory to:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navigando: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Ordine: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "alfabetico"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "per file"
+
+    # navigation.rpy:182
+    old "natural"
+    new "naturale"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Categoria:"
+
+    # navigation.rpy:196
+    old "files"
+    new "file"
+
+    # navigation.rpy:197
+    old "labels"
+    new "label"
+
+    # navigation.rpy:198
+    old "defines"
+    new "define"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "transform"
+
+    # navigation.rpy:200
+    old "screens"
+    new "screen"
+
+    # navigation.rpy:201
+    old "callables"
+    new "callable"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODO"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Aggiungi file di script"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Nessun commento TODO trovato.\n\nPer crearne uno, includi \"# TODO\" in your script."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "La lista dei nomi è vuota."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Non è stato possibile impostare la cartella del progetto. Abbandonando."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Scegli un modello di progetto"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Scegli un modello da usare per il tuo nuovo progetto. Il modello imposta il font predefinito e la lingua dell'interfaccia. Se la tua lingua non è supportata, scegli 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Preferenze del Launcher"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Cartella dei progetti:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Projects directory: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Non impostato"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Editor di testo:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Text editor: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Canale di aggiornamento:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Opzioni di navigazione:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Includi nomi privati"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Includi nomi di libreria"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Opzioni del Launcher:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Rendering via hardware"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Mostra modelli"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Show edit file section"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Large fonts"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Output console"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Apri progetto del Launcher"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Lingua:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Dopo aver modificato lo script, premi Shift+R per ricaricare il gioco."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Premi Shift+O (la lettera O) per apire la console."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Premi Shift+D per accedere al menú dello sviluppatore."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Have you backed up your projects recently?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Avvio del progetto fallito."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Prego verificare che il progetto si avvii normalmente prima di eseguire questo comando."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py sta analizzando il progetto..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Avviando"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "CARTELLA DEI PROGETTI"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Si prega di scegliere la cartella dei progetti tramite il selettore di cartella.\n{b}Il selettore di cartella potrebbe essersi aperto dietro questa finestra.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Questo launcher cercherà i progetti in questa cartella, creerà i nuovi progetti in questa cartella e posizionerà i progetti già compilati in questa cartella."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py ha impostato la cartella dei progetti a:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Generate empty strings for translations"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py sta generando le traduzioni..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py ha finito di generare le traduzioni in [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py sta estrendo il dialogo..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Seleziona un canale di aggiornamento"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Il canale di aggiornamento determina la versione di Ren'Py che l'updater scaricherà. Prego scegliere un canale di aggiornamento:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Release"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Raccomandato.{/b} La versione di Ren'Py che dovrebbe essere usata in tutti i giochi più recenti."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Prerelease"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Un'anteprima della prossima versione di Ren'Py che può essere usata per provare le nuove funzionalità ma non per il rilascio finale dei giochi"
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Experimental"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Versioni sperimentali di Ren'Py. Di interesse soltanto per gli sviluppatori di Ren'Py."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "La versione più recente di Ren'Py. Potrebbe avere maggiori funzionalità come anche non funzionare affatto."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Si è verificato un errore:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Controllando gli aggiornamenti."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py è aggiornato."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] è disponibile. Vuoi installarla?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Preparando lo scaricamento dell'aggiornamento."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Scaricando l'aggiornamento."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Estraendo l'aggiornamento."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Finalizando."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "L'aggiornamento è stato installato. Ren'Py verrà riavviato."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "L'aggiornamento è stato installato."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "L'aggiornamento è stato annullato."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Aggiornamento di Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Procedi"
+
diff --git a/launcher/game/tl/italian/navigation.rpy b/launcher/game/tl/italian/navigation.rpy
deleted file mode 100644
index b1dc377..0000000
--- a/launcher/game/tl/italian/navigation.rpy
+++ /dev/null
@@ -1,65 +0,0 @@
-translate italian strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Navigando: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Ordine: "
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "alfabetico"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "per file"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "naturale"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Categoria:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "file"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "label"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "define"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "transform"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "screen"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "callable"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODO"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Aggiungi file di script"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Nessun commento TODO trovato.\n\nPer crearne uno, includi \"# TODO\" in your script."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "La lista dei nomi è vuota."
diff --git a/launcher/game/tl/italian/new_project.rpy b/launcher/game/tl/italian/new_project.rpy
deleted file mode 100644
index b0733ff..0000000
--- a/launcher/game/tl/italian/new_project.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate italian strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Scegli un modello di progetto"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Scegli un modello da usare per il tuo nuovo progetto. Il modello imposta il font predefinito e la lingua dell'interfaccia. Se la tua lingua non è supportata, scegli 'english'."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "NOME DEL PROGETTO"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Inserisci il nome del tuo progetto:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "Il nome del progetto non può essere nullo."
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] esiste già. Si prega scegliere un altro nome."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] esiste già. Si prega di scegliere un altro nome."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Non è stato possibile impostare la cartella del progetto. Abbandonando."
diff --git a/launcher/game/tl/italian/obsolete.rpy b/launcher/game/tl/italian/obsolete.rpy
new file mode 100644
index 0000000..6bd3204
--- /dev/null
+++ b/launcher/game/tl/italian/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate italian strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Mapping del Joystick"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Slot Vuoto."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Precedente"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Successivo"
+
diff --git a/launcher/game/tl/italian/options.rpy b/launcher/game/tl/italian/options.rpy
new file mode 100644
index 0000000..51544a5
--- /dev/null
+++ b/launcher/game/tl/italian/options.rpy
@@ -0,0 +1,195 @@
+
+translate italian strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/italian/preferences.rpy b/launcher/game/tl/italian/preferences.rpy
deleted file mode 100644
index 295dd91..0000000
--- a/launcher/game/tl/italian/preferences.rpy
+++ /dev/null
@@ -1,61 +0,0 @@
-translate italian strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Preferenze del Launcher"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Cartella dei progetti:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "Non impostato"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Editor di testo:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Canale di aggiornamento:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Opzioni di navigazione:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Includi nomi privati"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Includi nomi di libreria"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Opzioni del Launcher:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Rendering via hardware"
-
-    # game/preferences.rpy:146
-    old "Show templates"
-    new "Mostra modelli"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "Output console"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "Apri progetto del Launcher"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "Lingua:"
diff --git a/launcher/game/tl/italian/project.rpy b/launcher/game/tl/italian/project.rpy
deleted file mode 100644
index 7967146..0000000
--- a/launcher/game/tl/italian/project.rpy
+++ /dev/null
@@ -1,53 +0,0 @@
-translate italian strings:
-
-    # game/project.rpy:201
-    old "Launching the project failed."
-    new "Avvio del progetto fallito."
-
-    # game/project.rpy:201
-    old "Please ensure that your project launches normally before running this command."
-    new "Prego verificare che il progetto si avvii normalmente prima di eseguire questo comando."
-
-    # game/project.rpy:204
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py sta analizzando il progetto..."
-
-    # game/project.rpy:503
-    old "PROJECTS DIRECTORY"
-    new "CARTELLA DEI PROGETTI"
-
-    # game/project.rpy:503
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Si prega di scegliere la cartella dei progetti tramite il selettore di cartella.\n{b}Il selettore di cartella potrebbe essersi aperto dietro questa finestra.{/b}"
-
-    # game/project.rpy:503
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Questo launcher cercherà i progetti in questa cartella, creerà i nuovi progetti in questa cartella e posizionerà i progetti già compilati in questa cartella."
-
-    # game/project.rpy:543
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py non ha potuto eseguire Python con TKinter per selezionare la cartella dei progetti."
-
-    # game/project.rpy:547
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py ha impostato la cartella dei progetti a:"
-
-    # game/project.rpy:30
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Dopo aver modificato lo script, premi Shift+R per ricaricare il gioco."
-
-    # game/project.rpy:31
-    old "Press shift+O (the letter) to access the console."
-    new "Premi Shift+O (la lettera O) per apire la console."
-
-    # game/project.rpy:32
-    old "Press shift+D to access the developer menu."
-    new "Premi Shift+D per accedere al menú dello sviluppatore."
-
-    # game/project.rpy:496
-    old "Launching"
-    new "Avviando"
-
-    # game/project.rpy:584
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren'Py non ha potuto eseguire Python con tkinter per selezionare la cartella dei progetti. Si prega di reinstallare i pacchetti python-tk o tkinter."
diff --git a/launcher/game/tl/italian/screens.rpy b/launcher/game/tl/italian/screens.rpy
new file mode 100644
index 0000000..21e422a
--- /dev/null
+++ b/launcher/game/tl/italian/screens.rpy
@@ -0,0 +1,643 @@
+
+translate italian strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Indietro"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Salva"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Salva"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Salva V."
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Carica V."
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Preferenze"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Preferenze"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Menù Principale"
+
+    # screens.rpy:328
+    old "About"
+    new "Informazioni"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Aiuto"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Esci"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Ritorna"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Schermo"
+
+    # screens.rpy:739
+    old "Window"
+    new "Finestra"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Schermo intero"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Dopo le Scelte"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transizioni"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Velocità del Testo"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Avanza automaticamente"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Volume Musica"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Volume Suono"
+
+    # screens.rpy:791
+    old "Test"
+    new "Prova"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Volume Voce"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Si"
+
+    # screens.rpy:1162
+    old "No"
+    new "No"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/italian/script.rpym b/launcher/game/tl/italian/script.rpym
new file mode 100644
index 0000000..5b78453
--- /dev/null
+++ b/launcher/game/tl/italian/script.rpym
@@ -0,0 +1,18 @@
+# Puoi inserire lo script (sceneggiatura) del tuo gioco in questo file.
+
+# Declare images below this line, using the image statement.
+# Dichiare le immagini sotto questa line usando il comando "image", esempio:
+# image eileen happy = "eileen_happy.png"
+
+# Dichiara i personaggi usati in questo gioco
+define e = Character('Eileen', color="#c8ffc8")
+
+
+# Inizio del gioco
+label start:
+
+    e "Hai creato un nuovo gioco di Ren'Py."
+
+    e "Ed appena avrai aggiunto storia, immagini e musica potrai mostrarlo a tutto il mondo!"
+
+    return
diff --git a/launcher/game/tl/italian/translations.rpy b/launcher/game/tl/italian/translations.rpy
deleted file mode 100644
index 0146f37..0000000
--- a/launcher/game/tl/italian/translations.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate italian strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Crea o Aggiorna Traduzioni"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Per favore inserisci il nome del linguaggio per cui vuoi creare o aggiornare le traduzioni."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "Il nome del linguaggio non può essere la stringa vuota."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Py sta generando le traduzioni..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py ha finito di generare le traduzioni in [language]."
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "Che formato preferisci per il dialogo estratto?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py sta estrendo il dialogo..."
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py ha finito di estrarre il dialogo. Il dialogo estratto può essere trovato in dialogue.[format] nella cartella di base."
diff --git a/launcher/game/tl/italian/updater.rpy b/launcher/game/tl/italian/updater.rpy
deleted file mode 100644
index 5dadb6f..0000000
--- a/launcher/game/tl/italian/updater.rpy
+++ /dev/null
@@ -1,93 +0,0 @@
-translate italian strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Seleziona un canale di aggiornamento"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Il canale di aggiornamento determina la versione di Ren'Py che l'updater scaricherà. Prego scegliere un canale di aggiornamento:"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Release"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Raccomandato.{/b} La versione di Ren'Py che dovrebbe essere usata in tutti i giochi più recenti."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Prerelease"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Un'anteprima della prossima versione di Ren'Py che può essere usata per provare le nuove funzionalità ma non per il rilascio finale dei giochi"
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Experimental"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Versioni sperimentali di Ren'Py. Di interesse soltanto per gli sviluppatori di Ren'Py."
-
-    # game/updater.rpy:106
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:112
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "La versione più recente di Ren'Py. Potrebbe avere maggiori funzionalità come anche non funzionare affatto."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Si è verificato un errore:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Cercando aggiornamenti."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren'Py è aggiornato."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] è disponibile. Vuoi installarla?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Preparando lo scaricamento dell'aggiornamento."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Scaricando l'aggiornamento."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Estraendo l'aggiornamento."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Finalizzando."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "L'aggiornamento è stato installato. Ren'Py verrà riavviato."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "L'aggiornamento è stato installato."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "L'aggiornamento è stato annullato."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Aggiornamento di Ren'Py"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Procedi"
diff --git a/launcher/game/tl/japanese/MTLc3m-LICENSE b/launcher/game/tl/japanese/MTLc3m-LICENSE
deleted file mode 100644
index 5f91705..0000000
--- a/launcher/game/tl/japanese/MTLc3m-LICENSE
+++ /dev/null
@@ -1,17 +0,0 @@
-MTLc3m.ttf is destributed under Apache License 2.0.
---------------------------------
-
-Copyright (C) 2008 The Android Open Source Project
-Copyright (C) 2010 MOTOYA CO.,LTD.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-  
-     http://www.apache.org/licenses/LICENSE-2.0
-  
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/launcher/game/tl/japanese/about.rpy b/launcher/game/tl/japanese/about.rpy
deleted file mode 100644
index 1f83a1c..0000000
--- a/launcher/game/tl/japanese/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate japanese strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "ライセンス"
-
-    # game/about.rpy:27
-    old "Back"
-    new "戻る"
-
diff --git a/launcher/game/tl/japanese/add_file.rpy b/launcher/game/tl/japanese/add_file.rpy
deleted file mode 100644
index 40a59fe..0000000
--- a/launcher/game/tl/japanese/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate japanese strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "ファイル名"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "作成するスクリプトファイル名を入力してください。"
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "ファイル名は拡張子 .rpy を持つ必要があります。"
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "ファイルは既に存在します。"
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Pyは .rpy で終わるすべてのスクリプトファイルを自動的にロードします。このファイルを使用するためにはラベルを定義し、他のファイルからそこにジャンプしてください。\n"
-
diff --git a/launcher/game/tl/japanese/android.rpy b/launcher/game/tl/japanese/android.rpy
deleted file mode 100644
index 68d032a..0000000
--- a/launcher/game/tl/japanese/android.rpy
+++ /dev/null
@@ -1,175 +0,0 @@
-
-translate japanese strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Androidパッケージをビルドするためには{a=http://www.renpy.org/dl/android}RAPT{/a}をダウンロードして解凍し、Ren'Py ディレクトリーに配置してランチャーを再起動してください。"
-
-    # game/android.rpy:13
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT はインストールされましたが、Androidパッケージをビルドする前に Android SDK もインストールする必要があります。SDKをインストールしてください。"
-
-    # game/android.rpy:14
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT はインストールされましたが、キーが設定されていません。新しいキーを作成するか、android.keystore を復帰させてください。"
-
-    # game/android.rpy:15
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "現在のプロジェクトは設定がされていません。「設定」を使用してビルド前に設定してください。"
-
-    # game/android.rpy:16
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "「ビルド」を選択して現在のプロジェクトをビルドするか、Android デバイスを接続して「ビルド & インストール」を選択し、ビルド後そのデバイスにインストールしてください。"
-
-    # game/android.rpy:18
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Android Phoneをエミュレートします。\n\nタッチ入力はマウスを利用してエミュレートされますが、ボタン押下時のみ反応します。Escapeはメニューボタン、PageUpはバックボタンに割り当てられています。"
-
-    # game/android.rpy:19
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Android tabletをエミュレートします。\n\nタッチ入力はマウスを利用してエミュレートされますが、ボタン押下時のみ反応します。Escapeはメニューボタン、PageUpはバックボタンに割り当てられています。"
-
-    # game/android.rpy:20
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Android OUYAをエミュレートします。\n\nコントローラーの入力は矢印キー、Enterはセレクトボタン、Escapeはメニューボタン、PageUpはバックボタンに割り当てられています。"
-
-    # game/android.rpy:22
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Android SDKをダウンロード後インストールします。サインに必要なキーを任意で生成します。"
-
-    # game/android.rpy:23
-    old "Configures the package name, version, and other information about this project."
-    new "このプロジェクトについてパッケージ名とバージョン、その他の情報を設定してください。"
-
-    # game/android.rpy:24
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Google Play key を含むファイルをエディターで開いてください。\n\nこれはアプリが拡張APKを使用する場合のみ必要となります。詳細はドキュメントを参照してください。"
-
-    # game/android.rpy:25
-    old "Builds the Android package."
-    new "Androidパッケージをビルドします。"
-
-    # game/android.rpy:26
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Androidパッケージをビルドし、コンピューターに接続されたAndroidデバイスにインストールします。"
-
-    # game/android.rpy:142
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:151
-    old "QUESTION"
-    new "質問"
-
-    # game/android.rpy:351
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:371
-    old "Emulation:"
-    new "エミュレーター:"
-
-    # game/android.rpy:379
-    old "Phone"
-    new "Phone"
-
-    # game/android.rpy:383
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:387
-    old "Television / OUYA"
-    new "Television / OUYA"
-
-    # game/android.rpy:399
-    old "Build:"
-    new "ビルド:"
-
-    # game/android.rpy:407
-    old "Install SDK & Create Keys"
-    new "SDKのインストール & キーの作成"
-
-    # game/android.rpy:411
-    old "Configure"
-    new "設定"
-
-    # game/android.rpy:415
-    old "Build Package"
-    new "パッケージのビルド"
-
-    # game/android.rpy:419
-    old "Build & Install"
-    new "ビルド & インストール"
-
-    # game/android.rpy:13
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Windowsでは、Androidパッケージのビルドに32-bitのJava開発キットが必要です。JDKはJREとは異なるため、JDKが無くてもJavaが利用できます。\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}JDKのダウンロードとインストール{/a}を行い、Ren'Pyランチャーを再起動して下さい。"
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Androidパッケージをビルドするには、RAPTをダウンロード・展開し、Ren'Pyのディレクトリーに設置して下さい。その後、Ren'Pyを再起動して下さい。"
-
-    # game/android.rpy:504
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Androidアプリをパッケージングする前に、RAPT(Ren'Py Android Packaging Tool)をダウンロードする必要があります。今すぐダウンロードしますか?"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "OUYAやFire TVのようなテレビで動作する Android デバイスをエミュレートします。\n\nコントローラーの入力は矢印キー、Enterはセレクトボタン、Escapeはメニューボタン、PageUpはバックボタンに割り当てられています。"
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "TCP/IPモードでADBを実行し、Androidデバイスに接続します。"
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "TCP/IPモードでADBを実行し、Androidデバイスとの接続を解除します。"
-
-    # game/android.rpy:516
-    old "Other:"
-    new "その他"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "リモートADB接続"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "リモートADB接続解除"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "リモートADBアドレス"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "接続先のIPアドレスとポート番号を\"192.168.1.143:5555\"の形式で入力して下さい。あなたのデバイスがのドキュメントを読んでリモートADB接続をサポートしているかを確認してください。サポートしているなら、そのアドレスとポート番号を使用してください。"
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "不正なリモートADBアドレスです。"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "アドレスは必ずひとつ ':' を含まなければなりません。"
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "ホストは空白を含まなくともよいです。"
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "ポートは数字でなければなりません。"
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Android パッケージをビルドして、接続された Android にインストール、 そのデバイスでアプリを起動します。"
-
-    # game/android.rpy:288
-    old "Television"
-    new "Television"
-
-    # game/android.rpy:324
-    old "Build, Install & Launch"
-    new "ビルドとインストール、起動"
-
diff --git a/launcher/game/tl/japanese/choose_directory.rpy b/launcher/game/tl/japanese/choose_directory.rpy
deleted file mode 100644
index 01d561d..0000000
--- a/launcher/game/tl/japanese/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate japanese strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py  は tkinter でディレクトリーを選択出来ません。 python-tk か tkinter をインストールしてください。"
-
diff --git a/launcher/game/tl/japanese/choose_theme.rpy b/launcher/game/tl/japanese/choose_theme.rpy
deleted file mode 100644
index 82feef0..0000000
--- a/launcher/game/tl/japanese/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate japanese strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "テーマを変更出来ません。 options.rpy が変更されすぎているかもしれません。"
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Display"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Window"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Fullscreen"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Sound Volume"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Choose Theme"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "テーマ"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "カラースキーム"
-
-    # game/choose_theme.rpy:444
-    old "Continue"
-    new "続行"
-
diff --git a/launcher/game/tl/japanese/common.rpy b/launcher/game/tl/japanese/common.rpy
index 8b4c099..aa3aa2b 100644
--- a/launcher/game/tl/japanese/common.rpy
+++ b/launcher/game/tl/japanese/common.rpy
@@ -1,539 +1,335 @@
-# Translation updated at 2013-02-18 11:40
-
+
 translate japanese strings:
 
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "スキップモード"
-
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "高速スキップモード"
-
-    # renpy/common/00updater.rpy:1255
-    old "Updater"
-    new "アップデーター"
-
-    # renpy/common/00updater.rpy:1264
-    old "This program is up to date."
-    new "このプログラムは最新の状態です。"
-
-    # renpy/common/00updater.rpy:1266
-    old "[u.version] is available. Do you want to install it?"
-    new "[u.version] が利用可能です。インストールしますか?"
-
-    # renpy/common/00updater.rpy:1268
-    old "Preparing to download the updates."
-    new "ダウンロードする準備をしています。"
-
-    # renpy/common/00updater.rpy:1270
-    old "Downloading the updates."
-    new "アップデートをダウンロードしています。"
-
-    # renpy/common/00updater.rpy:1272
-    old "Unpacking the updates."
-    new "アップデートを展開しています。"
-
-    # renpy/common/00updater.rpy:1276
-    old "The updates have been installed. The program will restart."
-    new "アップデートがインストールされました。プログラムを再起動します。"
-
-    # renpy/common/00updater.rpy:1278
-    old "The updates have been installed."
-    new "アップデートが完了しました。"
-
-    # renpy/common/00updater.rpy:1280
-    old "The updates were cancelled."
-    new "アップデートがキャンセルされました。"
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "ジョイスティックの割り当て"
-
-    # renpy/common/00layout.rpy:421
-    old "Are you sure?"
-    new "続けますか?"
-
-    # renpy/common/00layout.rpy:422
-    old "Are you sure you want to delete this save?"
-    new "このセーブデータを消去しますか?"
-
-    # renpy/common/00layout.rpy:423
-    old "Are you sure you want to overwrite your save?"
-    new "このセーブデータに上書きしますか?"
-
-    # renpy/common/00layout.rpy:424
-    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
-    new "セーブされていないデータは失われます\n続けますか?"
-
-    # renpy/common/00layout.rpy:425
-    old "Are you sure you want to quit?"
-    new "終了しますか?"
-
-    # renpy/common/00layout.rpy:426
-    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
-    new "メインメニューに戻りますか?\nセーブされていないデータは破棄されます"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}月曜日"
 
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "例外が発生しました。"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}火曜日"
 
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "ロールバック"
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}水曜日"
 
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "セーブまたは他の選択肢が選べるように、ロールバックを使って直前に戻ります。"
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}木曜日"
 
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "無視"
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}金曜日"
 
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "例外を無視してゲームを続行します。連鎖的にエラーが発生する可能性があります。"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}土曜日"
 
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "リロード"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}日曜日"
 
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "ディスクからゲームをリロードして、現在の状況を保存、可能であれば復元します。"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}月"
 
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "トレースバックを開く"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}火"
 
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "テキストエディターで traceback.txt を開きます。"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}水"
 
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "ゲームを終了します。"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}木"
 
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "スクリプトの変換に失敗しました。"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}金"
 
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "変換エラーを開く"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}土"
 
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "テキストエディターで errors.txt を開きます。"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}日"
 
-    # renpy/common/00keymap.rpy:167
-    old "Saved screenshot as %s."
-    new "スクリーンショットを %s に保存しました。"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}1月"
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "グラフィック・アクセラレーション"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}2月"
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "自動で選択する"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}3月"
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Angle/DirectX レンダラーを使う"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}4月"
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "OpenGL レンダラーを使う"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}5月"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "ソフトウェアレンダラーを使う"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}6月"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "変更は次回起動時から適用されます"
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}7月"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "パフォーマンスに関する注意"
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}8月"
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "このコンピューターはソフトウェアレンダリングを使用しています。"
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}9月"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "このコンピューターはシェーダーを使用していません。"
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}10月"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "このコンピューターは描画速度が遅いです。"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}11月"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "このコンピューターではグラフィックに以下の問題があります:[problem] "
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}12月"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "グラフィックドライバーが古いか、正常に動作していません。表示が遅れたり、正しく表示されない可能性があります。DirectX を更新すると解決することがあります。"
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}1月"
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "グラフィックドライバーが古いか、正常に動作していません。表示が遅れたり、正しく表示されない可能性があります。"
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}2月"
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "DirectXのアップデート"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}3月"
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "次回もこの注意を表示する。"
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}4月"
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "次回はこの注意を表示しない。"
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}5月"
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "DirectXのアップデート中"
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}6月"
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "DirectX ウェブセットアップを開始しました。タスクバーに最小化されていることがありますが、指示通りにインストールしてください。"
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}7月"
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}注意:{/b} MicrosoftのDirectXウェブセットアッププログラムは、デフォルトでBingツールバーをインストールします。このツールバーが不要な場合は、対応したチェックボックスを解除して下さい。"
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}8月"
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "セットアップが完了したら、下のボタンを押して再起動してください。"
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}9月"
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "再起動"
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}10月"
 
-    # renpy/common/_layout/imagemap_load_save.rpym:115
-    old "a"
-    new "a"
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}11月"
 
-    # renpy/common/_layout/imagemap_load_save.rpym:124
-    old "q"
-    new "q"
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}12月"
 
-    # renpy/common/00action_file.rpy:118
+    # 00action_file.rpy:235
     old "%b %d, %H:%M"
     new "%m月%d日, %H:%M"
 
-    # renpy/common/00layout.rpy:427
-    old "Are you sure you want to begin skipping?"
-    new "スキップを開始しますか?"
-
-    # renpy/common/00layout.rpy:428
-    old "Are you sure you want to skip to the next choice?"
-    new "次の選択肢までスキップしますか?"
-
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "次の選択肢または未読までスキップしますか?"
-
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "画像 [index] / [count] はロックされています。"
-
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "前へ"
-
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "次へ"
-
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "スライドショー"
-
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "戻る"
-
-    # renpy/common/00action_file.rpy:587
+    # 00action_file.rpy:820
     old "Quick save complete."
     new "クイックセーブ完了。"
 
-    # renpy/common/_developer/inspector.rpym:43
-    old "Displayable Inspector"
-    new "Displayable インスペクター"
-
-    # renpy/common/_developer/inspector.rpym:49
-    old "Nothing to inspect."
-    new "インスペクトするものがありません"
-
-    # renpy/common/_developer/inspector.rpym:58
-    old "Size"
-    new "サイズ"
-
-    # renpy/common/_developer/inspector.rpym:63
-    old "Style"
-    new "スタイル"
-
-    # renpy/common/_developer/inspector.rpym:123
-    old "Inspecting Styles of [displayable_name!q]"
-    new "[displayable_name!q] のスタイルをインスペクト中"
-
-    # renpy/common/_developer/inspector.rpym:135
-    old "displayable:"
-    new "Displayable:"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "        (no properties affect the displayable)"
-    new "        (Displayable に影響しているプロパティーはありません)"
-
-    # renpy/common/_developer/inspector.rpym:144
-    old "        (default properties omitted)"
-    new "        (デフォルトのプロパティーは省略します)"
-
-    # renpy/common/_developer/inspector.rpym:174
-    old "<repr() failed>"
-    new "<repr() 失敗>"
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "開発者メニュー"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "ゲームのリロード (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "コンソール (Shift+D)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "変数ビューアー"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "テーマのテスト"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "画像位置ピッカー"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "ファイル名のリスト"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "画像ロード履歴の表示"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "画像ロード履歴の非表示"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "ゲーム起動時から変更された変数はありません。"
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "開発者メニューに戻ります"
-
-    # renpy/common/_developer/developer.rpym:309
-    old "Undefined Images"
-    new "未定義の画像"
-
-    # renpy/common/_developer/developer.rpym:409
-    old "Rectangle: %r"
-    new "矩形: %r"
-
-    # renpy/common/_developer/developer.rpym:414
-    old "Mouse position: %r"
-    new "マウス位置: %r"
-
-    # renpy/common/_developer/developer.rpym:416
-    old "Right-click or escape to quit."
-    new "右クリックまたはEscで終了。"
-
-    # renpy/common/_developer/developer.rpym:467
-    old "Done"
-    new "完了"
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)s コンソール, 作成者: Shiz, C, delta\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "<esc> を押して終了。help と入力してヘルプを表示。\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "Ren'Py スクリプト有効。"
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "Ren'Py スクリプト無効。"
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: このヘルプを表示"
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "続けますか?"
 
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "コマンド:\n"
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "このセーブデータを消去しますか?"
 
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new " <Ren'Py スクリプトステートメント>: ステートメントを実行\n"
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "このセーブデータに上書きしますか?"
 
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <Python 式またはステートメント>: 式またはステートメントを実行"
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "ロードすると、セーブされていない進行状況は失われます。\nロードしますか?"
 
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: コンソール履歴を消去"
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "終了しますか?"
 
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: コンソールを終了"
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "メインメニューに戻りますか?\nセーブされていない進行状況は失われます。"
 
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <スロット>: スロットからゲームをロード"
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "リプレイを終了しますか?"
 
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <スロット>: スロットにゲームを保存"
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "スキップを開始しますか?"
 
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: ゲームをリロードしてスクリプトを再読み込み"
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "次の選択肢までスキップしますか?"
 
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <式>: Python 式をウォッチ"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "次の選択肢まで、未読テキストをスキップしますか?"
 
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <式>: Python 式のウォッチを解除"
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "スクリーンショットを %s に保存しました。"
 
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: すべての式のウォッチを解除"
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "セルフボイシング無効化。"
 
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <ラベル>: ラベルにジャンプ"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "クリップボードボイシング有効化。"
 
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "オートリロード"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "セルフボイシング有効化。"
 
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}M画像が見付かりません{/b}"
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "スキップモード"
 
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "ファイル"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "本プログラムは、MIT License や GNU Lesser General Public License など、様々なライセンスのフリーウェアを含んでいます。 フルソースコードへのリンクを含む、完全なソフトウェアのリストは、{a=https://www.renpy.org/l/license}ここ{/a}にあります。"
 
-    # renpy/common/00preferences.rpy:387
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
-    new "クリップボードボイシングが有効化しました。 'shift+C'で無効化します。"
-
-    # renpy/common/00preferences.rpy:389
-    old "Self-voicing enabled. Press 'v' to disable."
-    new "セルフボイシングが有効化しました。 'v' で無効化します。"
-
-    # renpy/common/_developer/developer.rpym:437
-    old "Rectangle copied to clipboard."
-    new "クリップボードに矩形領域がコピーされました"
-
-    # renpy/common/_developer/developer.rpym:440
-    old "Position copied to clipboard."
-    new "クリップボードに座標がコピーされました"
+    new "クリップボードボイシングを有効化しました。 'shift+C'で無効化します。"
 
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "セルフボイシングは次のように話します。 \"[renpy.display.tts.last]\". 'alt+shift+V' で無効化します。"
 
-##Lancherでのみ必要###########################################
-    # renpy/common/00gltest.rpy:95
-    old "Quit"
-    new "終了"
-
-    # renpy/common/00gltest.rpy:100
-    old "Return"
-    new "戻る"
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "空のスロット"
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
-    new "前へ"
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "セルフボイシングを有効化しました。 'v' で無効化します。"
 
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
-    new "次へ"
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "App Store にコンタクトしています。\nしばらくお待ちください…"
 
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
-    new "モバイル板でのアップデートはサポートしていません。"
+    new "モバイルデバイスでのアップデートはサポートしていません。"
 
-    # renpy/common/00updater.rpy:478
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "エラーがシミュレートされました。"
 
-    # renpy/common/00updater.rpy:654
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
-    new "このプロジェクトはアップデートをサポートしていないか、アップデート用のファイルが削除されました。"
+    new "このプロジェクトはアップデートをサポートしていないか、アップデート用のファイルが削除されています。"
 
-    # renpy/common/00updater.rpy:668
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "このアカウントにはアップデート処理の権限がありません。"
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "このアカウントにはアップデートログを記録する権限がありません。"
 
-    # renpy/common/00updater.rpy:696
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "アップデートシグネチャーを認証出来ません。"
 
-    # renpy/common/00updater.rpy:956
+    # 00updater.rpy:975
     old "The update file was not downloaded."
-    new "アップデートファイルがダウンロードされませんでした。"
+    new "アップデートファイルをダウンロードできませんでした。"
 
-    # renpy/common/00updater.rpy:974
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "アップデートファイルは正しい digest を持っていません - 破損の可能性がありまます。"
 
-    # renpy/common/00updater.rpy:1030
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "{} を解凍中に、未知のタイプ {} を検出しました。"
 
-##templateでのみ必要############################################
-    #
-    # # renpy/common/00updater.rpy:1385
-    # old "An error has occured:"
-    # new "エラーが派生しました。"
-    #
-    # # renpy/common/00updater.rpy:1387
-    # old "Checking for updates."
-    # new "更新をチェックしています。"
-    #
-    # # renpy/common/00updater.rpy:1399
-    # old "Finishing up."
-    # new "更新を完了しました。"
-    #
-    # # renpy/common/00updater.rpy:1419
-    # old "Proceed"
-    # new "処理中"
-    #
-    # # renpy/common/00updater.rpy:1422
-    # old "Cancel"
-    # new "キャンセル"
+    # 00updater.rpy:1393
+    old "Updater"
+    new "アップデーター"
+
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "このプログラムは最新の状態です。"
+
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] が利用可能です。インストールしますか?"
+
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "ダウンロードする準備をしています。"
+
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "アップデートをダウンロードしています。"
+
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "アップデートを展開しています。"
+
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "アップデートをインストールしました。プログラムを再起動します。"
+
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "アップデートが完了しました。"
+
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "アップデートをキャンセルしました。"
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "画像 [index] / [count] はロックされています。"
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "前へ"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "次へ"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "スライドショー"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "戻る"
+
diff --git a/launcher/game/tl/japanese/developer.rpy b/launcher/game/tl/japanese/developer.rpy
new file mode 100644
index 0000000..07b9146
--- /dev/null
+++ b/launcher/game/tl/japanese/developer.rpy
@@ -0,0 +1,179 @@
+
+translate japanese strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "開発者メニュー"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "ゲームのリロード (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "コンソール (Shift+D)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "変数ビューアー"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "テーマのテスト"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "画像位置ピッカー"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "ファイル名のリスト"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "画像ロード履歴の表示"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "画像ロード履歴の非表示"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "インスペクトするものがありません"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "開発者メニューに戻ります"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "矩形: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "マウス位置: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "右クリックまたはEscで終了。"
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "クリップボードに矩形領域をコピーしました"
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "クリップボードに座標をコピーしました"
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ 予測済みの画像 (good){/color}\n{color=#fcc}✘ 未予測の画像 (bad){/color}\n{color=#fff}ドラッグすると動かせます。{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable インスペクター"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "サイズ"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "スタイル"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "ファイル"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "[displayable_name!q] のスタイルをインスペクト中"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "Displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (Displayable に影響しているプロパティーはありません)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (デフォルトのプロパティーは省略します)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() 失敗>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "<esc> を押して終了。help と入力してヘルプを表示。\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren'Py スクリプト有効。"
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren'Py スクリプト無効。"
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: このヘルプを表示"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "コマンド:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <Ren'Py スクリプトステートメント>: ステートメントを実行\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <Python 式またはステートメント>: 式またはステートメントを実行"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: コンソール履歴を消去"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: コンソールを終了"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <スロット>: スロットからゲームをロード"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <スロット>: スロットにゲームを保存"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: ゲームをリロードしてスクリプトを再読み込み"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <式>: Python 式をウォッチ"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <式>: Python 式のウォッチを解除"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: すべての式のウォッチを解除"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <ラベル>: ラベルにジャンプ"
+
diff --git a/launcher/game/tl/japanese/distribute.rpy b/launcher/game/tl/japanese/distribute.rpy
deleted file mode 100644
index d9a28aa..0000000
--- a/launcher/game/tl/japanese/distribute.rpy
+++ /dev/null
@@ -1,42 +0,0 @@
-
-translate japanese strings:
-
-    # game/distribute.rpy:335
-    old "Nothing to do."
-    new "何もしません。"
-
-    # game/distribute.rpy:339
-    old "Scanning project files..."
-    new "プロジェクトをスキャンしています…"
-
-    # game/distribute.rpy:346
-    old "Scanning Ren'Py files..."
-    new "Ren'Pyファイルをスキャンしています…"
-
-    # game/distribute.rpy:496
-    old "Archiving files..."
-    new "ファイルをアーカイブしています…"
-
-    # game/distribute.rpy:747
-    old "Writing the [variant] [format] package."
-    new "[variant] [format] パッケージを書き出しています。."
-
-    # game/distribute.rpy:760
-    old "Making the [variant] update zsync file."
-    new "[variant] のアップデート用 zsync ファイルを書き出しています。"
-
-    # game/distribute.rpy:856
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "{b}[total]{/b} 中 {b}[complete]{/b} ファイルが処理されました。"
-
-    # game/distribute.rpy:917
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "すべてのパッケージがビルドされました。\n\nパーミッション情報のために、Windows上でのLinuxやMacintosh用の配布物の解凍、再圧縮はサポートされません。"
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "パッケージが選択されていないため、何もすることがありません。"
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "配布物のビルドに失敗しました:\n\nbuild.directory_name 変数にスペース、コロン、セミコロンを含めてはいけません。"
diff --git a/launcher/game/tl/japanese/distribute_gui.rpy b/launcher/game/tl/japanese/distribute_gui.rpy
deleted file mode 100644
index 76ff19a..0000000
--- a/launcher/game/tl/japanese/distribute_gui.rpy
+++ /dev/null
@@ -1,63 +0,0 @@
-
-translate japanese strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "配布物のビルド: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "ディレクトリー名:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "実行ファイル名:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "アクション:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "options.rpy を編集"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "更新"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "パッケージをビルド"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "アップデートをビルド"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "ビルド"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "プロジェクトの実行時にエラーが検出されました。配布物をビルドする前にエラーなしでプロジェクトが実行するようにしてください。"
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "プロジェクトにビルド情報がありません。options.rpy の末尾にビルド情報を追加しますか?"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "from 節を call に加える"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "設定:"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "from 節を call ステートメントに加える"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "from 節がない call ステートメントに from 節を加えています"
-
diff --git a/launcher/game/tl/japanese/editor.rpy b/launcher/game/tl/japanese/editor.rpy
deleted file mode 100644
index 179c1d9..0000000
--- a/launcher/game/tl/japanese/editor.rpy
+++ /dev/null
@@ -1,58 +0,0 @@
-
-translate japanese strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}推奨{/b} スペルチュックのような開発目的のインターフェースや機能を簡単に使用可能なベータエディターです。Editraは現在中国、韓国、日本語の入力に必要な IME のサポートに欠陥があります。"
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}推奨{/b} スペルチェックのような開発目的のインターフェースや機能を簡単に使用可能なベータエディターです。Editraは現在中国、韓国、日本語の入力に必要な IME のサポートに欠陥があります。LinuxではEditraはwxpythonを必要とします。"
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "これはおそらくwxPythonがこのシステムにインストールされていないため発生しました。"
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "22MB までのダウンロードが必要です。"
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "1.8 MB のダウンロードが必要です。"
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "これはおそらくJavaがこのシステムにインストールされていないため発生しました。"
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "テキストエディターの選択中にエラーが発生しました:\n[exception!q]"
-
-    # game/editor.rpy:423
-    old "Select Editor"
-    new "エディターを選択"
-
-    # game/editor.rpy:438
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "テキストエディタはRen'Pyスクリプトファイルを編集するためのプログラムです。ここではRen'Pyが使用するエディターを選択可能です。存在しなければエディターは自動的にダウンロードされインストールされます。"
-
-    # game/editor.rpy:460
-    old "Cancel"
-    new "キャンセル"
-
-
-translate japanese strings:
-
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Javaを必要とする成熟したエディターです。"
-
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "オペレーティングシステムで .rpy ファイルに関連づけたエディターを実行します。"
-
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Ren'Pyのテキストエディターの実行を停止します。"
-
diff --git a/launcher/game/tl/japanese/error.rpy b/launcher/game/tl/japanese/error.rpy
new file mode 100644
index 0000000..6951b4d
--- /dev/null
+++ b/launcher/game/tl/japanese/error.rpy
@@ -0,0 +1,179 @@
+
+translate japanese strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "グラフィック・アクセラレーション"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "自動で選択する"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Angle/DirectX レンダラーを使う"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "OpenGL レンダラーを使う"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "ソフトウェアレンダラーを使う"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "有効"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "変更は次回起動時から適用されます"
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "パフォーマンスに関する注意"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "このコンピューターはソフトウェアレンダリングを使用しています。"
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "このコンピューターはシェーダーを使用していません。"
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "このコンピューターは描画速度が遅いです。"
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "このコンピューターではグラフィックに以下の問題があります: [problem] "
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "グラフィックドライバーが古いか、正常に動作していません。表示が遅れたり、正しく表示されない可能性があります。DirectX を更新すると解決することがあります。"
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "グラフィックドライバーが古いか、正常に動作していません。表示が遅れたり、正しく表示されない可能性があります。"
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "DirectXのアップデート"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "次回もこの警告を表示する"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "次回はこの警告を表示しない"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "DirectXのアップデート中"
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX ウェブセットアップを開始しました。タスクバーに最小化されていることがありますが、指示通りにインストールしてください。"
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}注意:{/b} Microsoft の DirectX ウェブセットアッププログラムは、デフォルトで Bing ツールバーをインストールします。このツールバーが不要な場合は、対応したチェックボックスを解除して下さい。"
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "セットアップが完了したら、下のボタンを押して再起動してください。"
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "再起動"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "キャリブレートするゲームパッドを選択してください。"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "有効なゲームパッドがありません。"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "キャリブレート [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "[control!r] [kind] を押すか、倒すかしてください。"
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new " スキップ (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new " 戻る (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "トレースバックを開く"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "テキストエディターで traceback.txt を開きます。"
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "クリップボードにコピー"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "traceback.txt をクリップボードにコピーします。"
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "例外が発生しました。"
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "ロールバック"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "セーブまたは他の選択肢が選べるように、ロールバックを使って直前に戻ります。"
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "無視"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "例外を無視してゲームを続行します。連鎖的にエラーが発生する可能性があります。"
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "リロード"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "ディスクからゲームをリロードして、現在の状況を保存、可能であれば復元します。"
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "ゲームを終了します。"
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "スクリプトの変換に失敗しました。"
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "変換エラーを開く"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "テキストエディターで errors.txt を開きます。"
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "errors.txt をクリップボードにコピーします。"
+
diff --git a/launcher/game/tl/japanese/front_page.rpy b/launcher/game/tl/japanese/front_page.rpy
deleted file mode 100644
index 7afe123..0000000
--- a/launcher/game/tl/japanese/front_page.rpy
+++ /dev/null
@@ -1,111 +0,0 @@
-
-translate japanese strings:
-
-    # game/front_page.rpy:67
-    old "refresh"
-    new "更新"
-
-    # game/front_page.rpy:94
-    old "+ Create New Project"
-    new "+ 新規プロジェクトの作成"
-
-    # game/front_page.rpy:106
-    old "Launch Project"
-    new "プロジェクトの起動"
-
-    # game/front_page.rpy:127
-    old "Tutorial"
-    new "Tutorial"
-
-    # game/front_page.rpy:128
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:144
-    old "Active Project"
-    new "アクティブなプロジェクト"
-
-    # game/front_page.rpy:152
-    old "Open Directory"
-    new "ディレクトリーを開く"
-
-    # game/front_page.rpy:157
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:158
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:164
-    old "Edit File"
-    new "ファイル編集"
-
-    # game/front_page.rpy:172
-    old "All script files"
-    new "すべてのスクリプト"
-
-    # game/front_page.rpy:181
-    old "Navigate Script"
-    new "スクリプトのナビゲート"
-
-    # game/front_page.rpy:192
-    old "Check Script (Lint)"
-    new "スクリプトチェック(Lint)"
-
-    # game/front_page.rpy:193
-    old "Change Theme"
-    new "テーマ変更"
-
-    # game/front_page.rpy:194
-    old "Delete Persistent"
-    new "永続データ削除"
-
-    # game/front_page.rpy:202
-    old "Build Distributions"
-    new "配布物のビルド"
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:205
-    old "Generate Translations"
-    new "翻訳の生成"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "台詞の抽出"
-
-    # game/front_page.rpy:222
-    old "Checking script for potential problems..."
-    new "潜在的な問題のためにスクリプトをチェックしています…"
-
-    # game/front_page.rpy:237
-    old "Deleting persistent data..."
-    new "永続データを削除しています…"
-
-    # game/front_page.rpy:122
-    old "[p.name!q] (template)"
-    new "[p.name!q] (テンプレート)"
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "[text] ディレクトリーを開きます。"
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "プロジェクト [text] を選択します。"
-
-    # game/front_page.rpy:234
-    old "Force Recompile"
-    new "強制再コンパイル"
-
-    # game/front_page.rpy:285
-    old "Recompiling all rpy files into rpyc files..."
-    new "すべての rpy ファイルを rpyc ファイルにコンパイルしています。"
-
-    # game/front_page.rpy:245
-    old "iOS"
-    new "iOS"
-
diff --git a/launcher/game/tl/japanese/gui.rpy b/launcher/game/tl/japanese/gui.rpy
new file mode 100644
index 0000000..9ceb3a0
--- /dev/null
+++ b/launcher/game/tl/japanese/gui.rpy
@@ -0,0 +1,436 @@
+
+translate japanese strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## 初期化"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## このファイルは GUI をカスタマイズする基本的なオプションを記載しています。次の init offset 文は、このファイルの init コードを他のファイルよりも先に実行しています。"
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## まず最初に gui.init を実行して、スタイルを扱いやすい初期値にリセットし、ゲームの横幅と縦幅を設定します。"
+
+    # gui.rpy:17
+    old "## GUI Configuration Variables"
+    new "## GUI 設定変数"
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## カラー"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## インターフェースのテキストのカラー。"
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## アクセントカラー。タイトル・ラベル・ハイライトされたテキスト・ボタンの背景・スライダーのつまみ等、インターフェイスの様々な場所で使います。"
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## selected(選択中)でも hover(フォーカス中)でもない状態のテキストボタンのカラー。"
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## スモールカラー。明るさを調節する必要のあるクイックメニューなどの小さなテキストボタンに使います。"
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## hover(フォーカス中)のテキストボタンのカラー。また、バーの充足部分(左側)・hover のスライダーのつまみ等の画像を再生成するときにも使われます。"
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## selected(選択中)のテキストボタンのカラー。ボタンは、現在の環境設定の値や表示中のスクリーンと一致するものが選択中になります。"
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## insensitive (選択不可能)なテキストボタンのカラー。"
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## バーの非充足部分(右側)やスライダーの背景部分のカラー。バーやスライダーのカラーは、ゲームでは直接使われず GUI を変更・更新した場合の画像生成に使われます。"
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## 次の text_color は台詞や選択肢のテキストのカラーです。その次の interface_text_color はヒストリーやヘルプなどそれ以外のテキストのカラーです。"
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## フォントとフォントサイズ"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## ゲーム内の台詞や選択肢に使われるフォント。"
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## キャラクターの名前に使われるフォント。"
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## ゲームメニューなどのインターフェースに使われるテキストのフォント。"
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## 一般的な台詞のテキストサイズ。"
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## キャラクターの名前のテキストサイズ。"
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## インターフェースのテキストサイズ。"
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## インターフェースのラベル(見出し)のテキストサイズ。"
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## notify(通知)スクリーンのテキストサイズ。"
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## ゲームタイトルのテキストサイズ。"
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## メインメニューとゲームメニュー"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## メインメニューとゲームメニューの背景画像。メインメニューはゲーム起動時に最初に表示されるメニュー、ゲームメニューはゲーム中右クリックで呼び出せるメニューです。画像を変えたい場合は gui ディレクトリーにある該当の画像を入れ替えてください。"
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## メインメニューにゲームタイトルとそのバージョンを表示するかどうか。True なら表示します。(この変数は options.rpy で再定義されるため、options.rpy の同じコードを消去しないと反映されません)"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## ダイアローグ(台詞)"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## 以下の変数は、一度に表示される台詞とキャラクターの名前を、どのようにスクリーンに表示するか制御します。"
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## 台詞を表示するテキストボックスの高さ。テキストボックスの画像を変えたい場合は gui/textbox.png の画像を入れ替えます。"
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## 画面に対する、テキストボックスの垂直方向の位置。 0.0 は上端、0.5 は中央、 1.0 は下端になります。"
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## テキストボックスに対する、キャラクター名の位置。左上からのピクセル数で指定するか 0.0 から 1.0 までの小数で指定します。 0.5 は中央に表示。"
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## キャラクター名の文字揃え。 0.0 は左揃え、0.5 は中央揃え、 1.0 は右揃えになります。0.0 以外にした場合、キャラクター名の位置の調整も必要になります。"
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## キャラクター名を表示するネームボックスのサイズ。None にすると、自動的に決定されます。画像を変えたい場合は gui/textbox.png の画像を入れ替えます(デフォルト画像は透明なので表示されません)。"
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## ネームボックスのボーダーのサイズ。左、上、右、下の順で指定します。ボックスのサイズは、その中に表示されるキャラクター名のサイズから更にボーダー分拡張したサイズになります。"
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## True に設定すると、ネームボックスの背景画像をスケーリングではなくタイリングで表示します。"
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## テキストボックスに対する、台詞の位置。左上からのピクセル数で指定するか 0.0 から 1.0 までの小数で指定します。 0.5 だと中央に表示。"
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## 台詞の最大ピクセル幅。このピクセル幅以上の台詞は折り返して表示されます。"
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## 台詞の文字揃え。 0.0 は左揃え、0.5 は中央揃え、 1.0 は右揃えになります。0.0 以外にした場合、台詞の位置の調整も必要になります。"
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## ボタン"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## 以下の変数は、ボタンをどのように表示するか制御します。画像を変えたい場合は gui/button ディレクトリーにある各 background.png の画像を入れ替えます(デフォルト画像は透明なので表示されません)。ボタンの状態に合わせて画像を変えたい場合は、ファイル名に idle_、hover_、selected_、selected_hover_ の接頭辞を付けます。"
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## ボタンの縦幅と横幅。None にすると自動的に計算されます。"
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## ボタンのボーダーのサイズ。左、上、右、下の順で指定します。ボタンのサイズは、その中のテキストやオブジェクトのサイズから更にボーダー分拡張したサイズになります。"
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## True に設定すると、ボタンの背景画像をスケーリングではなくタイリングで表示します。"
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## ボタンのテキストに使用するフォント。"
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## ボタンのテキストのサイズ。"
+
+    # gui.rpy:168
+    old "## The color of button text in various states."
+    new "## 状態別のボタンのテキストのカラー。idle は選択可能、hover はフォーカス中、selected は選択中、insensitive は選択不可能な状態です。"
+
+    # gui.rpy:174
+    old "## The horizontal alignment of the button text. (0.0 is left, 0.5 is center, 1.0 is right)."
+    new "## ボタンのフレームに対する、テキストの文字揃え。 0.0 は左揃え、0.5 は中央揃え、 1.0 は右揃えになります。"
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## 以下の変数は、様々なボタンの種類ごとにボタンの基本設定を上書きします。詳細は gui ドキュメンテーションを参考にしてください。"
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## デフォルトのインターフェースには、radio、check、confirm、page、quick、navigation、choice、slot、test、help、nvl のボタンが用意されています。\
+radio と check は環境設定の各項目のボタン(デフォルトでは同じ画像)。confirm は確認画面の選択肢、page は セーブ・ロード画面のページ切り替え、quick はクイックメニュー、 navigation はゲームメニューのメニュー切り替えに使うボタンです。"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## 上記以外にも、接頭辞と接尾辞を適切に組み合わせた変数名を追加すれば、様々なカスタマイズが可能になります。例えば、次の行をアンコメントすると navigation(メニュー切り替え)ボタンの横幅を指定することができます。"
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice(選択)ボタン"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice ボタンは、ゲーム内の選択肢に使うボタンです。"
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot(ファイルスロット)ボタン"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## File slot は特別なボタンで、セーブデータのサムネイル画像と詳細情報を含んでいます。他のボタンと同じように gui/button ディレクトリーにある slot_ の接頭辞が付いた背景画像を使います。"
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## File slot ボタンの設定。"
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## File slot に使われるサムネイル画像の横幅と縦幅。"
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## 1ページあたりの File slot の列数(cols)と行数(rows)。"
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## 配置と間隔"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## 以下の変数は、インターフェースの様々な要素の位置と間隔を制御します。"
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## 画面左端からの navigation(メニュー切り替え)ボタンの位置。"
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## 画面上端からの skip indicator(スキップ表示)スクリーンの位置。"
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## 画面上端からの notify(通知)スクリーンの位置。"
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## ゲーム中の choice(選択)ボタンの間隔。"
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## メインメニューやゲームメニューの navigation(メニュー切り替え)ボタンの間隔。"
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## 環境設定の各項目の間隔。"
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## 環境設定の各項目にある、各ボタンの間隔。"
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## セーブ・ロード画面の file page(ページ切り替え)ボタンの間隔。"
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## セーブ・ロード画面の file slot(ファイルスロット)ボタン間隔。."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## フレーム"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## 以下の変数は、インターフェースのコンポーネントを収納するフレームを制御します。フレームは、ウィンドウやオーバーレイが用いられない場面で使われます。"
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## 一般的なフレーム。デフォルトのインターフェースでは使われず、開発者の書いたコードでのみ使用します。画像は gui/frame.png。"
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## confirm(確認)スクリーンに使用するフレーム。画像は gui/overlay/confirm.png。"
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## skip indicator(スキップ表示)スクリーンに使用するフレーム。画像は gui/skip.png。"
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## notify(通知)スクリーンに使用するフレーム。画像は gui/notify.png。"
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## True に設定すると、フレームの背景画像をスケーリングではなくタイリングで表示します。"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## バー・スクロールバー・スライダー"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## 以下の変数は、バー・スライダー・スクロールバーの外見を制御します。"
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## デフォルトの GUI はスライダーと垂直スクロールバーだけを使用します。他のバーは開発者が追加したコードでのみ使われます。"
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## バー・スクロールバー・スライダーの各々の太さ(水平バーでは縦幅、垂直バーでは横幅)。"
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True に設定すると、バーの背景をスケーリングではなくタイリングで表示します。"
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## 水平バーのボーダー。画像はそれぞれ、 gui/bar/left.png 及び right.png、gui/slider/horizontal_**.png、gui/scrollbar/horizontal_**.png。"
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## 垂直バーのボーダー。画像はそれぞれ、gui/bar/bottom.png 及び top.png、gui/slider/vertical_**.png、gui/scrollbar/vartical_**.png。"
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## スクロール不可能なスクロールバーをどう扱うか。 \"hide\" なら非表示、None なら表示します。"
+
+    # gui.rpy:331
+    old "## History"
+    new "## ヒストリー"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## History(履歴)スクリーンは、プレイヤーが見終わった台詞を表示します。"
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## ヒストリーのエントリー(1台詞)を最大いくつまで保持するか。"
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## History スクリーンにおける、エントリーの高さ。None にすると可変になりますが、パフォーマンスが低下します。"
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## キャラクター名の縦座標・横座標・横幅・文字揃え。"
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## 台詞の縦座標・横座標・横幅・文字揃え。"
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL モード"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## NVL(ノベル)スクリーンは、 NVL モード(全画面方式)のキャラクターの台詞を表示するスクリーンです。"
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## NVL モードに使用する背景のボーダー。画像は gui/nvl.png。"
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## NVL モードにおける、エントリー(1台詞)の高さ。None にすると可変になります。"
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## NVL モードにおいて、gui.nvl_height を None に設定した場合の各エントリーの間隔。また、台詞と選択肢との間隔にも使われます。"
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## nvl_thought(モノローグ)の縦座標・横座標・横幅・文字揃え。"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## NVL モードにおける、選択肢の横座標と文字揃え。"
+
+    # gui.rpy:398
+    old "## Mobile devices"
+    new "## モバイルデバイス"
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## タブレットやスマートフォンでタッチしやすいように、 quick ボタンのサイズを大きくします。"
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## スマートフォンで見やすいように、GUI の各要素のサイズと間隔を変更します。"
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## フォントサイズ。"
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## テキストボックスの位置を調整。"
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## ゲームメニューの各項目のサイズと間隔を変更。"
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## ファイルスロットの配置。"
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL モード。"
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick ボタン。"
+
+    # gui.rpy:395
+    old "## Localization"
+    new "## 多言語対応"
+
+    # gui.rpy:397
+    old "## This controls where a line break is permitted. The default is suitable for most languages. A list of available values can be found at https://www.renpy.org/doc/html/style_properties.html#style-property-language"
+    new "## 次の変数は改行・禁則処理を制御します。デフォルトの値が推奨です。他の値は https://www.renpy.org/doc/html/style_properties.html#style-property-language を参照してください。"
+
diff --git a/launcher/game/tl/japanese/interface.rpy b/launcher/game/tl/japanese/interface.rpy
deleted file mode 100644
index 69045b0..0000000
--- a/launcher/game/tl/japanese/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate japanese strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "ドキュメント"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Ren'Pyサイト"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Ren'Pyゲームリスト"
-
-    # game/interface.rpy:92
-    old "About"
-    new "About"
-
-    # game/interface.rpy:99
-    old "update"
-    new "アップデート"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "設定"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "終了"
-
-    # game/interface.rpy:174
-    old "Yes"
-    new "Yes"
-
-    # game/interface.rpy:176
-    old "No"
-    new "No"
-
-    # game/interface.rpy:211
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "パッケージフォーマットの制限により、アスキーコード以外のファイル、ディレクトリー名は許可されません。"
-
-    # game/interface.rpy:213
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:299
-    old "ERROR"
-    new "エラー"
-
-    # game/interface.rpy:328
-    old "While [what!q], an error occured:"
-    new "[what!q] 中にエラーが発生しました。:"
-
-    # game/interface.rpy:329
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:347
-    old "Text input may not contain the {{ or [[ characters."
-    new "{{ または [[ はテキスト入力出来ません。"
-
-    # game/interface.rpy:352
-    old "File and directory names may not contain / or \\."
-    new "ファイル、ディレクトリーが / または \\. を含んでいるかもしれません。"
-
-    # game/interface.rpy:358
-    old "File and directory names must consist of ASCII characters."
-    new "ファイル、ディレクトリー名はアスキーコードの文字列で構成される必要があります。"
-
-    # game/interface.rpy:379
-    old "INFORMATION"
-    new "情報"
-
-    # game/interface.rpy:422
-    old "PROCESSING"
-    new "処理中"
-
-    # game/interface.rpy:452
-    old "CHOICE"
-    new "選択"
-
diff --git a/launcher/game/tl/japanese/ios.rpy b/launcher/game/tl/japanese/ios.rpy
deleted file mode 100644
index 18ffe90..0000000
--- a/launcher/game/tl/japanese/ios.rpy
+++ /dev/null
@@ -1,99 +0,0 @@
-
-translate japanese strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "iOS パッケージをビルドするには、  renios をダウンロードして、Ren'Py ディレクトリーに配置、ランチャーを再起動してください。"
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "'Select Directory' から、 xcode プロジェクトが配置されるディレクトリーを選択してください。"
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "現在の Ren'Py プロジェクトに対応する Xcode プロジェクトがありません。'Create Xcode Project' から作成してください。"
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Xcode プロジェクトが存在します。'Update Xcode Project' を選択して最新のゲームファイルに更新するか、 Xcode を使用してそれをビルド、インストールしてください。"
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "iPhone をエミュレートします。\n\nタッチ入力はマウスを利用してエミュレートされますが、ボタン押下時のみ反応します"
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "iPad をエミュレートします。\n\nタッチ入力はマウスを利用してエミュレートされますが、ボタン押下時のみ反応します"
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Xcode プロジェクトが配置されるディレクトリーを選択します。"
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "現在の Ren'PY プロジェクトに対応する Xcode プロジェクトを作成します。"
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "最新のゲームファイルに Xcode プロジェクトを更新します。これは Ren'Py プロジェクトが変更される度に行わなければなりません。"
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Xcode から Xcode プロジェクトを開きます。"
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "対応する Xcode プロジェクトを開きます。"
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "その Xcode プロジェクトは既に存在します。古いプロジェクトをリネームするか、新しいもので置き換えますか?"
-
-    # game/ios.rpy:202
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:231
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:235
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:255
-    old "Select Xcode Projects Directory"
-    new "Xcode プロジェクトディレクトリー選択"
-
-    # game/ios.rpy:259
-    old "Create Xcode Project"
-    new "Xcode プロジェクト作成"
-
-    # game/ios.rpy:263
-    old "Update Xcode Project"
-    new "Xcode プロジェクト更新"
-
-    # game/ios.rpy:268
-    old "Launch Xcode"
-    new "Xcode 起動"
-
-    # game/ios.rpy:303
-    old "Open Xcode Projects Directory"
-    new "Xcode プロジェクトディレクトリー開く"
-
-    # game/ios.rpy:336
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "iOS アプリをパッケージする前に、reniosをダウンロードする必要があります。 renios をダウンロードしますか?"
-
-    # game/ios.rpy:345
-    old "XCODE PROJECTS DIRECTORY"
-    new "XCODE PROJECTS DIRECTORY"
-
-    # game/ios.rpy:345
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Xcode プロジェクトディレクトリーを選択してください。\n{b}ディレクトリー選択ウィンドウはこのウィンドウの裏に開くかもしれません。{/b}"
-
-    # game/ios.rpy:350
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py は Xcode プロジェクトディレクトリーを以下に設定しました。:"
-
diff --git a/launcher/game/tl/japanese/launcher.rpy b/launcher/game/tl/japanese/launcher.rpy
new file mode 100644
index 0000000..de4fafb
--- /dev/null
+++ b/launcher/game/tl/japanese/launcher.rpy
@@ -0,0 +1,1199 @@
+
+translate japanese strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "ライセンス"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "ファイル名"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "作成するスクリプトファイル名を入力してください。"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "ファイル名は拡張子 .rpy を持つ必要があります。"
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "ファイルは既に存在します。"
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py は .rpy で終わるすべてのスクリプトファイルを自動的にロードします。このファイルを使用するためにはラベルを定義し、他のファイルからそこにジャンプしてください。\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Android パッケージをビルドするには、RAPT をダウンロード・展開し、Ren'Py のディレクトリーに設置して下さい。その後、Ren'Py を再起動して下さい。"
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Windows では、Android パッケージのビルドに 32-bit の Java 開発キットが必要です。JDK は JRE とは異なるため、JDK が無くても Java が利用できます。\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}JDK のダウンロードとインストール{/a}を行い、Ren'Py ランチャーを再起動して下さい。"
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT のインストールは終了しましたが、Android パッケージをビルドする前に Android SDK もインストールする必要があります。SDKをインストールしてください。"
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT のインストールは終了しましたが、キーが設定されていません。新しいキーを作成するか、android.keystore を修復してください。"
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "現在のプロジェクトは設定がされていません。「設定」を使用してビルド前に設定してください。"
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "「ビルド」を選択して現在のプロジェクトをビルドするか、Android デバイスを接続して「ビルド & インストール」を選択し、ビルド後そのデバイスにインストールしてください。"
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Android Phone をエミュレートします。\n\nタッチ入力のエミュレートはマウスを利用しますが、ボタン押下時のみ反応します。Escape はメニューボタン、PageUp はバックボタンに割り当てられています。"
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Android tablet をエミュレートします。\n\nタッチ入力のエミュレートはマウスを利用しますが、ボタン押下時のみ反応します。Escape はメニューボタン、PageUp はバックボタンに割り当てられています。"
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "OUYA や Fire TV のようなテレビで動作する Android デバイスをエミュレートします。\n\nコントローラーの入力は矢印キー、Enter はセレクトボタン、Escape はメニューボタン、PageUp はバックボタンに割り当てられています。"
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Android SDK をダウンロード後インストールします。署名に必要なキーを任意で生成します。"
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "このプロジェクトについてパッケージ名とバージョン、その他の情報を設定してください。"
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Google Play key を含むファイルをエディターで開いてください。\n\nこの処理はアプリが拡張 APK を使用する場合のみ必要となります。詳細はドキュメントを参照してください。"
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Android パッケージをビルドします。"
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Android パッケージをビルドし、コンピューターに接続された Android デバイスにインストールします。"
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Android パッケージをビルドして、接続された Android にインストール、 そのデバイスでアプリを起動します。"
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "TCP/IP モードで ADB を実行し、Android デバイスに接続します。"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "TCP/IP モードで ADB を実行し、Android デバイスとの接続を解除します。"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Android デバイスからログを獲得し、ファイルに書き出します。"
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Android ファイルを distributions ディレクトリにコピーしています。"
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "エミュレーター:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Phone"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Television"
+
+    # android.rpy:353
+    old "Build:"
+    new "ビルド:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "SDKのインストール & キーの作成"
+
+    # android.rpy:365
+    old "Configure"
+    new "設定"
+
+    # android.rpy:369
+    old "Build Package"
+    new "パッケージのビルド"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "ビルド & インストール"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "ビルドとインストール、起動"
+
+    # android.rpy:388
+    old "Other:"
+    new "その他:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "リモートADB接続"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "リモートADB接続解除"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Android アプリをパッケージングする前に、RAPT (Ren'Py Android Packaging Tool) をダウンロードする必要があります。今すぐダウンロードしますか?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "リモート ADB アドレス"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "接続先の IP アドレスとポート番号を \"192.168.1.143:5555\" の形式で入力して下さい。デバイスのドキュメントを読んでリモート ADB 接続をサポートしているかを確認してください。サポートしているなら、そのアドレスとポート番号を使用してください。"
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "不正なリモート ADB アドレスです。"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "アドレスは必ずひとつ ':' を含まなければなりません。"
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "ホストは空白を含んではいけません。"
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "ポートは数字でなければなりません。"
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "デバイスから logcat のインフォメーションを獲得しています。"
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py は tkinter でディレクトリーを選択出来ません。 python-tk か tkinter をインストールしてください。"
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "テーマを変更出来ません。 options.rpy が変更されすぎているかもしれません。"
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "プラネタリウム"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "テーマ選択"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "テーマ"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "カラースキーム"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "続行"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "情報"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "このコマンドは、OS のコンソールウィンドウで実行されています。"
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "プロジェクトをスキャンしています…"
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "配布物のビルドに失敗しました:\n\nbuild.directory_name 変数にスペース、コロン、セミコロンを含めてはいけません。"
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "パッケージが選択されていないため、何もすることがありません。"
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Ren'Py ファイルをスキャンしています…"
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "全てのパッケージのビルドを終了しました。\n\nパーミッション情報のために、Windows 上での Linux や Macintosh 用の配布物の解凍、再圧縮はサポートされません。"
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "ファイルをアーカイブしています…"
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "署名のため、Macintosh application を展開しています…"
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Macintosh application に署名しています…"
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Macintosh DMG を作成しています…"
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Macintosh DMG に署名しています…"
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "[variant] [format] パッケージを書き出しています。"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "[variant] のアップデート用 zsync ファイルを書き出しています。"
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "{b}[total]{/b} 中 {b}[complete]{/b} ファイルを処理しました。"
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "配布物のビルド: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "ディレクトリー名:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "実行ファイル名:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "アクション:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "options.rpyを編集"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "from節をcallに加える"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "更新"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "itch.ioにアップロードする"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "ビルドするパッケージ:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "設定:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "アップデートをビルド"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "from 節を call ステートメントに加える"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "強制再コンパイル"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "ビルド"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "from 節がない call ステートメントに from 節を加えています"
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "プロジェクトの実行時にエラーを検出しました。配布物をビルドする前に、エラーなしでプロジェクトが実行するようにしてください。"
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "プロジェクトにビルド情報がありません。options.rpy の末尾にビルド情報を追加しますか?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}推奨{/b} 使いやすいインターフェースと、スペルチュックのような開発を補助する機能を持つベータエディターです。Editra は現在、中国、韓国、日本語の入力に必要な IME のサポートに欠陥があります。"
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}推奨{/b} 使いやすいインターフェースと、スペルチュックのような開発を補助する機能を持つベータエディターです。Editra は現在、中国、韓国、日本語の入力に必要な IME のサポートに欠陥があります。Linux では Editra は wxpython を必要とします。"
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "このエラーは wxPython がこのシステムにインストールされていないため発生したと思われます。"
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "最大 22 MB のダウンロードが必要です。"
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Java を必要とする成熟したエディターです。"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB のダウンロードが必要です。"
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "このエラーは Java がこのシステムにインストールされていないため発生しましたと思われます。"
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "オペレーティングシステムで .rpy ファイルに関連づけたエディターを実行します。"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Ren'Py のテキストエディターの実行を停止します。"
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "テキストエディターの選択中にエラーが発生しました:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "エディターを選択してください"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "テキストエディタは Ren'Py スクリプトファイルを編集するためのプログラムです。ここで Ren'Py が使用するエディターを選択できます。選択したエディターが存在しなければ、自動的にダウンロード・インストールされます。"
+
+    # editor.rpy:494
+    old "Cancel"
+    new "キャンセル"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "[text] ディレクトリーを開きます。"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "更新"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+新規プロジェクトの作成"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "プロジェクトの起動"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (テンプレート)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "プロジェクト [text] を選択します。"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "アクティブなプロジェクト"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "ディレクトリーを開く"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "ファイルを編集する"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "すべてのスクリプト"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "スクリプトのナビゲート"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "スクリプトチェック(Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "GUIを変更・更新"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "テーマ変更"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "永続データ削除"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "配布物のビルド"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "翻訳の生成"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "台詞の抽出"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "スクリプトの潜在的な問題をチェックしています…"
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "永続データを削除しています…"
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "すべての rpy ファイルを rpyc ファイルにコンパイルしています。"
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "アクセントカラーとバックグラウンドカラーを選択"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "使用したいカラースキームをクリックした後、続行をクリックしてください。カラーは後で変更・カスタマイズすることができます。"
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}警告{/b}\n続行すると、カスタマイズしたバー・ボタン・セーブスロット・スクロールバー・スライダーの画像が上書きされます。\n\nそれでもよろしいでしょうか?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "新しいカラーを選び、画像を再生成する"
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "gui.rpy のカラーを元に、画像を再生成する"
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "プロジェクト名"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "プロジェクト名を入力してください:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "プロジェクト名が空です。"
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] は既に存在します。違う名前を選択してください。"
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] は既に存在します。違う名前を選択してください。"
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "どの解像度をこのプロジェクトに使用しますか? Ren'py はウィンドウを拡大縮小することができますが、この設定は初期のウィンドウサイズ、描画される各アセットのサイズ、アセットが最もシャープに見えるサイズを決定します。\n\nデフォルトの 1280x720 が合理的な妥協サイズです。"
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "新しいプロジェクトを作成中…"
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "プロジェクトを更新しています…"
+
+    # interface.rpy:107
+    old "Documentation"
+    new "ドキュメント"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren'Pyサイト"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Ren'Pyゲームリスト"
+
+    # interface.rpy:117
+    old "update"
+    new "アップデート"
+
+    # interface.rpy:119
+    old "preferences"
+    new "設定"
+
+    # interface.rpy:120
+    old "quit"
+    new "終了"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "パッケージフォーマットの制限により、アスキーコード以外のファイル、ディレクトリー名は許可されません。"
+
+    # interface.rpy:327
+    old "ERROR"
+    new "エラー"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "[what!q] 中にエラーが発生しました:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "{{ または [[ はテキスト入力出来ません。"
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "ファイル、ディレクトリーが / または \\. を含んでいるかもしれません。"
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "ファイル、ディレクトリー名はアスキーコードの文字列で構成される必要があります。"
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "処理中"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "質問"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "選択"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "iOS パッケージをビルドするには、  renios をダウンロードして、Ren'Py ディレクトリーに配置、ランチャーを再起動してください。"
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "'Select Directory' から、 xcode プロジェクトが配置されるディレクトリーを選択してください。"
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "現在の Ren'Py プロジェクトに対応する Xcode プロジェクトがありません。'Create Xcode Project' から作成してください。"
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Xcode プロジェクトが存在します。'Update Xcode Project' を選択して最新のゲームファイルに更新するか、 Xcode を使用してそれをビルド、インストールしてください。"
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "iPhone をエミュレートします。\n\nタッチ入力のエミュレートはマウスを利用しますが、ボタン押下時のみ反応します"
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "iPad をエミュレートします。\n\nタッチ入力のエミュレートはマウスを利用しますが、ボタン押下時のみ反応します"
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Xcode プロジェクトが配置されるディレクトリーを選択します。"
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "現在の Ren'PY プロジェクトに対応する Xcode プロジェクトを作成します。"
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "最新のゲームファイルに Xcode プロジェクトを更新します。更新は Ren'Py プロジェクトが変更される度に行わなければなりません。"
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Xcode から Xcode プロジェクトを開きます。"
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "対応する Xcode プロジェクトを開きます。"
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "その Xcode プロジェクトは既に存在します。古いプロジェクトをリネームするか、新しいもので置き換えますか?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Xcode プロジェクトディレクトリー選択"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Xcode プロジェクト作成"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Xcode プロジェクト更新"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Xcode 起動"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Xcode プロジェクトディレクトリー開く"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "iOS アプリをパッケージする前に、renios をダウンロードする必要があります。 renios をダウンロードしますか?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Xcode プロジェクトディレクトリーを選択してください。\n{b}ディレクトリー選択ウィンドウはこのウィンドウの裏に開くかもしれません。{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py は Xcode プロジェクトディレクトリーを以下に設定しました:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "ビルドされた配布物が見つかりません。ビルドを選択し、やり直してください。"
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "アップロードできるファイルが見つかりません。ビルドを選択し、やり直してください。"
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "butler プログラムが見つかりません。"
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "butler を含む itch.io app をインストールして、やり直してください。"
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "itch project の名前が設定されていません。"
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "{a=https://itch.io/game/new}プロジェクトを作成{/a}して、options.rpy に次のような命令を追加してください。\n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5}"
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "ナビゲーション: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "並び順:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "アルファベット順"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "ファイル順"
+
+    # navigation.rpy:182
+    old "natural"
+    new "記載順"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "カテゴリー:"
+
+    # navigation.rpy:196
+    old "files"
+    new "ファイル"
+
+    # navigation.rpy:197
+    old "labels"
+    new "ラベル"
+
+    # navigation.rpy:198
+    old "defines"
+    new "定義"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "変換"
+
+    # navigation.rpy:200
+    old "screens"
+    new "スクリーン"
+
+    # navigation.rpy:201
+    old "callables"
+    new "関数"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODO"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+スクリプトファイルを追加する。"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "TODO コメントは見つかりません。\n\n作成には \"# TODO\" をスクリプトに加えてください。"
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "名前のリストはありません。"
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI インターフェース"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "どちらのインターフェースも日本語に翻訳されています。"
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "New GUI のみが日本語に翻訳されています。"
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Legacy Theme のみが日本語に翻訳されています。"
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "どちらのインターフェースも日本語に翻訳されていません。"
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "プロジェクトディレクトリーを設定出来ません。キャンセルします。"
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "どちらのインターフェースを使用しますか? New GUI はモダンな外見で、ワイドスクリーンとモバイルデバイスをサポートし、カスタマイズも容易です。Legacy Theme は古いコード例を利用するのに必要になるでしょう。\n\n[language_support!t]\n\n判断がつかない場合は、New GUI を選択して、右下の続行をクリックしてください。"
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme インターフェース"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "テンプレートを選んでください"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "新しいプロジェクトで使用するテンプレートを選択してください。Ren'Py はデフォルトのフォントとユーザーインターフェイスの言語を設定します。あなたの言語がサポートされていないなら 'english' を選択してください。"
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "ランチャー設定"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "プロジェクトディレクトリー:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "プロジェクトディレクトリー: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "未設定"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "テキストエディター:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "テキストエディター: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "アップデートチャンネル:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "ナビゲートオプション:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "内部使用の名前を含める"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "本体の名前を含める"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "ランチャー設定:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "ハードウェアレンダリング"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "テンプレートの表示"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "ファイル編集を表示する"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "フォントを大きくする"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "コンソール出力"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "ランチャーのプロジェクトを開く"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "言語:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "スクリプトに変更を加えた後、Shift+R を押すとゲームをリロードします。"
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Shift+O(英字)を押すとコンソールを表示します。"
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Shift+D を押すと開発者メニューを表示します。"
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "最近ゲームのバックアップはしましたか?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "プロジェクトの起動に失敗しました。"
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "このコマンドを実行する前に、プロジェクトが通常通り起動することを確認して下さい。"
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py プロジェクトをスキャンしています…"
+
+    # project.rpy:568
+    old "Launching"
+    new "起動中"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "プロジェクトディレクトリー"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "プロジェクトディレクトリーを選択してください。\n{b}ディレクトリー選択画面がこのウィンドウの下に隠れている場合があります。{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "ランチャーはこのディレクトリーでプロジェクトをスキャンし、新しいプロジェクトを作成し、ビルドしたプロジェクトを出力します。"
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py は以下にプロジェクトディレクトリーを設定します:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "翻訳: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "翻訳に使う言語。半角小文字の ASCII 文字とアンダースコアのみが使用できます。"
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "翻訳を空の文字列で生成する"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "翻訳ファイルを生成、または更新します。翻訳ファイルは、game/tl/[persistent.translate_language!q] に置かれます。"
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "文字列の翻訳を抽出"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "文字列の翻訳を併合"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "既にある翻訳を置き換える"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "言語を反転させる"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "デフォルトインターフェースの翻訳を更新する"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "抽出コマンドは、既存のプロジェクトから文字列の翻訳(台詞以外の翻訳)を一時ファイルとして抽出します。\n\n併合コマンドは、抽出した翻訳を他のプロジェクトに併合します。"
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py は翻訳を生成しています…"
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py は [language] の翻訳ファイルを生成しました。"
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py は文字列の翻訳を抽出しています…"
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py は [language] の文字列の翻訳を抽出しました。"
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py は文字列の翻訳を併合しています…"
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py は [language] の文字列の翻訳を併合しました。"
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "デフォルトインターフェースの翻訳を更新しています…"
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "台詞の抽出: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "フォーマット:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "タブ区切りのスプレッドシート (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "台詞のテキストのみ (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "台詞からテキストタグを取り除く"
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "引用符や他の特殊文字をエスケープする"
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "台詞だけでなく、翻訳可能なすべての文字列を抽出する"
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py は台詞を抽出しています…"
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py は台詞の抽出を終了しました。抽出した台詞は、base ディレクトリーの、[persistent.dialogue_format] にあります。"
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "アップデートチャンネルを選択してください"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "アップデートチャンネルはアップデーターがダウンロードする Ren'Py のバージョンを制御します。アップデートチャンネルを選択してください。"
+
+    # updater.rpy:91
+    old "Release"
+    new "Release"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}推奨{/b} 新しくリリースする全てのゲームに使用すべき Ren'Py のバージョンです。"
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Prerelease"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "テストや新機能利用のために使用される Ren'Py の次期バージョンのプレビューです。\nゲームの最終リリースには向きません。"
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Experimental"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Ren'Py の試験的なバージョンです。開発者に頼まれない限りこのバージョンを使用するべきではありません。"
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Ren'Py の開発版で極めて不安定です。このバージョンには最新の機能が含まれていますが、全く動かないかもしれません。"
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "エラーが発生しました。"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "更新をチェックしています。"
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py は最新です。"
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] が利用可能です。インストールしますか?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "アップデートのダウンロード準備をしています。"
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "アップデートをダウンロードしています。"
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "アップデートを解凍しています。"
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "更新を完了しました。"
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "アップデートをインストールしました。Ren'Py を再起動します。"
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "アップデートをインストールしました。"
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "アップデートをキャンセルしました。"
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ren'Py アップデート"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "続行"
+
+    # choose_directory.rpy:104
+    old "The selected projects directory is not writable."
+    new "選択されたプロジェクトディレクトリーは、書き込み不可です。"
+
+    # distribute.rpy:1061
+    old "Signing the Macintosh application...\n(This may take a long time.)"
+    new "Macintosh application に署名しています…\n(この処理にはしばらくかかります。)"
+
+    # front_page.rpy:91
+    old "PROJECTS:"
+    new "プロジェクト:"
+
diff --git a/launcher/game/tl/japanese/navigation.rpy b/launcher/game/tl/japanese/navigation.rpy
deleted file mode 100644
index f5dbd2a..0000000
--- a/launcher/game/tl/japanese/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate japanese strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "ナビゲーション: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "並び順:"
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "アルファベット順"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "ファイル順"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "natural"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "カテゴリー:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "ファイル"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "ラベル"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "定義"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "変換"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "スクリーン"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "関数"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODO"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ スクリプトファイルを追加する。"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "TODOコメントは見つかりません。\n\n作成には \"# TODO\" をスクリプトに加えてください。"
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "名前のリストは空です。"
-
diff --git a/launcher/game/tl/japanese/new_project.rpy b/launcher/game/tl/japanese/new_project.rpy
deleted file mode 100644
index d8237a4..0000000
--- a/launcher/game/tl/japanese/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate japanese strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "テンプレートを選んでください"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "新しいプロジェクトで使用するテンプレートを選択してください。Ren'Pyはデフォルトのフォントとユーザーインターフェイスの言語を設定します。あなたの言語がサポートされていないなら 'english' を選択してください。"
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "プロジェクト名"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "プロジェクト名を入力してください:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "プロジェクト名が空です。"
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] は既に存在します。違う名前を選択してください。"
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] は既に存在します。違う名前を選択してください。"
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "プロジェクトディレクトリーを設定出来ません。キャンセルしています。"
-
diff --git a/launcher/game/tl/japanese/obsolete.rpy b/launcher/game/tl/japanese/obsolete.rpy
new file mode 100644
index 0000000..dacdaf5
--- /dev/null
+++ b/launcher/game/tl/japanese/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate japanese strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "ジョイスティックの割り当て"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "空きスロット"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "前へ"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "次へ"
+
diff --git a/launcher/game/tl/japanese/options.rpy b/launcher/game/tl/japanese/options.rpy
new file mode 100644
index 0000000..355675d
--- /dev/null
+++ b/launcher/game/tl/japanese/options.rpy
@@ -0,0 +1,196 @@
+
+translate japanese strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## このファイルはゲームをカスタマイズする基本的なオプションを記載しています。"
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## 二つの'#'で始まる行はコメントなのでアンコメント(#を消してコメントをコードに戻すこと)してはいけません。一つの'#'で始まる行はコメントアウト(#を加えてコードをコメント化し、実行できなくすること)されたコードで、必要に応じてアンコメントできます。"
+
+    # options.rpy:10
+    old "## Basics"
+    new "## 基本"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## 人が読みやすいゲーム名。ゲーム名はデフォルトのウィンドウタイトルに使われる他、インターフェースやエラーリポートにも表示されます。"
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## _() で囲まれた文字列は翻訳時に生成されるファイルに記載されます。"
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## 上で定義したタイトルをメインメニュースクリーン(ゲーム起動後、最初に表示されるスクリーン)に表示するかどうか決めます。False にすると表示しません。"
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## ゲームのバージョン。"
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## About(バージョン情報)スクリーンに表示されるテキスト。パラグラフ間に空白の行を挿入したい場合は、\\n\\n と書いてください。"
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## 実行ファイルやビルドされた配布物のディレクトリー名に使われる、ゲームの簡易名。簡易名は ASCII 文字(半角英数字)のみで構成され、スペース・コロン・セミコロンなどを含んでは行けません。"
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## サウンドと音楽"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## 以下の変数はデフォルトで使用されるミキサー(同じ効果を共有するチャンネルの集まり)を制御します。False にしたミキサーは利用できなくなります。"
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## サウンドやボイスの設定画面でユーザーがテストサウンドを再生できるようにしたい場合、以下の行をアンコメントしてサンプルサウンドを指定します。"
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## 次の行をアンコメントしてオーディオファイルを指定すると、メインメニューで再生することができます。このファイルは、停止するか他の音楽が再生されない限りゲーム中で流れ続けます。"
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## トランジション(画面遷移効果)"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## 以下の変数は、メニュー切り替えなどのイベントに対するトランジションを設定します。各変数にはトランジションオブジェクトを指定します。トランジションを使わない場合は None に設定します。"
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## ゲームメニュー(ゲーム中、右クリックで表示されるメニュー)を開いたり閉じたりする時のトランジション。"
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## ゲームデータをロードした後に使われるトランジション。"
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## ゲーム終了後、メインメニューに戻る時のトランジション。"
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## メインメニューからゲームを開始する時のトランジションは、ここでは設定できません。代わりに、ゲーム開始後の最初のシーンで with ステートメント(文)を使ってください。"
+
+    # options.rpy:96
+    old "## Window management"
+    new "## テキストウィンドウの管理"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## 次の変数は、台詞を表示するテキストウィンドウの挙動を制御します。\"show\" であれば常に表示、\"hide\" であれば台詞が表示されているときにのみ表示します。\"auto\" であれば scene ステートメントの直前に非表示にして、say ステートメントの直前に再表示します。"
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## ゲーム開始後は、\"window show\"、\"window hide\"、\"window auto\" ステートメントで変更することができます。"
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## テキストウィンドウを表示したり、非表示にしたりする時のトランジション。"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## 環境設定のデフォルト"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## デフォルトの文字表示速度。数字は一秒に表示する文字数で、デフォルト値の 0 は無限(一瞬で表示)を意味します。"
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## デフォルトのオート待ち時間。0 から 30 までの数字を取り、数字が大きいほど待ち時間が長くなります。"
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## セーブディレクトリー"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## プラットフォームごとの Ren'Py がゲームのセーブデータを作成する場所を制御します。セーブファイルは以下の場所に作成されます:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## この値は一般的に変更するべきではありません。もし変更する場合、式や変数ではなく文字列で直接指定しなければなりません。"
+
+    # options.rpy:146
+    old "## Icon"
+    new "## アイコン"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## タスクバーやダックに表示されるアイコン。"
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## ビルド設定"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## このセクションは、プロジェクトを配布物にビルドするときの挙動を制御します。"
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## 以下の機能はファイルパターン(ワイルドカード等で複数ファイルを指定する文字列)を利用します。ファイルパターンは、大文字小文字を区別せず、ベースディレクトリーからの相対パスを参照します(最初の / は無視します)。複数のパターンが一致した場合、先に定義した方が優先されます。"
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## パターンは以下の記号を使用します:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / はディレクトリーのセパレーターです。"
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * はディレクトリーセパレーターを除く、すべての文字に一致します。"
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** はディレクトリーセパレーターを含む、すべての文字に一致します。"
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## 例えば、\"*.txt\" はベースディレクトリーにある全ての txt ファイルに一致し、 \"game/**.ogg\" はゲームディレクトリー及びそのサブディレクトリーにある全ての ogg ファイルに一致し、\"**.psd\" はプロジェクトのあらゆる psd ファイルに一致します。"
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## classify(分類)を None に設定したファイルは配布物から除外されます。"
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## アーカイブ(書庫化・暗号化)したいファイルは 'archive'(または任意の文字列)に分類します。"
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## documentation(ドキュメント)に指定したパターンと一致するファイルは mac 用アプリのビルドで複製され、app と zip のどちらにも含まれるようになります。"
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## 拡張をダウンロードしたり、アプリ内課金を行う場合には、Google Play ライセンスキーが必要です。キーは Google Play developer console の \"Services & APIs\" にあります。"
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## itch.io project に関連付けられたユーザー名とプロジェクト名。二つの名前はスラッシュで分けてください。"
+
+
diff --git a/launcher/game/tl/japanese/preferences.rpy b/launcher/game/tl/japanese/preferences.rpy
deleted file mode 100644
index e9fdf8e..0000000
--- a/launcher/game/tl/japanese/preferences.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate japanese strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "ランチャー設定"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "プロジェクトディレクトリー:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "未設定"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "テキストエディター:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "アップデートチャンネル:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "ナビゲートオプション:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "内部使用の名前を含める"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "本体の名前を含める"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "ランチャー設定:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "ハードウェアレンダリング"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "コンソール出力"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "ランチャーのプロジェクトを開く"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "言語:"
-
-    # game/preferences.rpy:146
-    old "Show templates"
-    new "テンプレートの表示"
-
-    # game/preferences.rpy:165
-    old "Large fonts"
-    new "フォントを大きくする"
-
-    # game/preferences.rpy:91
-    old "Projects directory: [text]"
-    new "プロジェクトディレクトリー: [text]"
-
-    # game/preferences.rpy:114
-    old "Text editor: [text]"
-    new "テキストエディター: [text]"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "ファイル編集を表示する"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "空の文字列でも翻訳を生成する"
-
diff --git a/launcher/game/tl/japanese/project.rpy b/launcher/game/tl/japanese/project.rpy
deleted file mode 100644
index 7d30b11..0000000
--- a/launcher/game/tl/japanese/project.rpy
+++ /dev/null
@@ -1,59 +0,0 @@
-
-translate japanese strings:
-
-    # game/project.rpy:204
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py プロジェクトをスキャンしています…"
-
-    # game/project.rpy:503
-    old "PROJECTS DIRECTORY"
-    new "プロジェクトディレクトリー"
-
-    # game/project.rpy:503
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "プロジェクトディレクトリーを選択してください。\n{b}ディレクトリー選択画面がこのウィンドウの下に隠れている場合があります。{/b}"
-
-    # game/project.rpy:503
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "ランチャーはこのディレクトリーでプロジェクトをスキャンし、新しいプロジェクトを作成し、ビルドしたプロジェクトを出力します。"
-
-    # game/project.rpy:543
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py はプロジェクトディレクトリーを選択するために tkinter でpythonを実行することは出来ません。"
-
-    # game/project.rpy:547
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py は以下にプロジェクトディレクトリーを設定します:"
-
-    # game/project.rpy:48
-    old "After making changes to the script, press shift+R to reload your game."
-    new "スクリプトに変更を加えた後、Shift+Rを押すとゲームをリロードします。"
-
-    # game/project.rpy:49
-    old "Press shift+O (the letter) to access the console."
-    new "Shift+O(英字)を押すとコンソールを表示します。"
-
-    # game/project.rpy:50
-    old "Press shift+D to access the developer menu."
-    new "Shift+Dを押すと開発者メニューを表示します。"
-
-    # game/project.rpy:219
-    old "Launching the project failed."
-    new "プロジェクトの起動に失敗しました。"
-
-    # game/project.rpy:219
-    old "Please ensure that your project launches normally before running this command."
-    new "このコマンドを実行する前に、プロジェクトが通常通り起動することを確認して下さい。"
-
-    # game/project.rpy:515
-    old "Launching"
-    new "起動中"
-
-    # game/project.rpy:584
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren'Pyはプロジェクトディレクトリー選択のためのtkinterをPythonの実行時に読み込めませんでした。python-tkもしくはtkinterパッケージをインストールして下さい。"
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "最近ゲームのバックアップはしましたか?"
-
diff --git a/launcher/game/tl/japanese/screens.rpy b/launcher/game/tl/japanese/screens.rpy
new file mode 100644
index 0000000..b4dbdcd
--- /dev/null
+++ b/launcher/game/tl/japanese/screens.rpy
@@ -0,0 +1,661 @@
+
+translate japanese strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## スタイル"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## ゲーム内のスクリーン"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say(発話)スクリーン"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## Say スクリーンはプレイヤーにダイアローグ(台詞)を表示するのに使います。who、what の二つのパラメーターをとり、who は発話しているキャラクターの名前、what は表示されるテキストを意味します。(キャラクターの名前がない場合 who は None になります)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## このスクリーンは、テキストを表示するために \"what\" のIDを持つ text displayable(表示可能オブジェクト)を必ず作成しなければなりません。また、スタイルのプロパティを適用するために、ID \"who\" とID \"window\" を持つ text displayable も作成するといいでしょう。"
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:119
+    old "## If there's a side image, display it above the text. Do not display on the phone variant - there's no room."
+    new "## サイドイメージ(テキストボックス横に表示するイメージ)があれば、テキストの上に表示します。ただし variant(画面のタイプ)が phone の場合は、スペースが足りないので表示しません。"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input(入力)スクリーン"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## renpy.input を表示するのに使うスクリーンです。prompt のパラメーターは、プロンプト(入力ボックスの隣に表示されるテキスト)を表示するのに使います。"
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## このスクリーンは input のパラメーター を受け付けるために \"input\" をIDに持つ input displayable(表示可能オブジェクト)を作成する必要があります。"
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice(選択)スクリーン"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## このスクリーンは、ゲーム内の選択肢を表示するのに使います。items のパラメーターは caption(選択肢のテキスト)と action(クリック時の実行内容)を要素に持つオブジェクトのリスト(配列)です。"
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## 次が True の場合、menu の見出しテキストを narrator を使って say(発話)スクリーンで表示します。 False の場合、選択肢の上に押せないボタンとして表示します。"
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu(クイックメニュー)スクリーン"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## クイックメニューはゲーム中つねに表示されるスクリーンで、ゲーム外の機能に素早くアクセスすることができます。"
+
+    # screens.rpy:251
+    old "## Ensure this appears on top of other screens."
+    new "## 他のスクリーンの上に表示する。"
+
+    # screens.rpy:261
+    old "Back"
+    new "ロールバック"
+
+    # screens.rpy:262
+    old "History"
+    new "ヒストリー"
+
+    # screens.rpy:263
+    old "Skip"
+    new "スキップ"
+
+    # screens.rpy:264
+    old "Auto"
+    new "オート"
+
+    # screens.rpy:265
+    old "Save"
+    new "セーブ"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.セーブ"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.ロード"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "設定"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## 次のコードは、プレイヤーが明示的にインターフェースを隠さない限り quick_menu スクリーンが常にゲーム中に表示されるようにしています。"
+
+    old "## Main and Game Menu Screens"
+    new "## メインメニュースクリーンとゲームメニュースクリーン"
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation(ナビゲーション)スクリーン"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## このスクリーンはメインメニューとゲームメニューに表示され、各メニュー間を移動したり、ゲームをスタートしたりする機能を提供しています。"
+
+    # screens.rpy:308
+    old "Start"
+    new "スタート"
+
+    # screens.rpy:316
+    old "Load"
+    new "ロード"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "環境設定"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "リプレイ終了"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "メインメニュー"
+
+    # screens.rpy:328
+    old "About"
+    new "バージョン情報"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## モバイルデバイスにはヘルプは不要であるか不適切です。"
+
+    # screens.rpy:333
+    old "Help"
+    new "ヘルプ"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## 終了ボタンは iOS では使えず Android では不要です。"
+
+    # screens.rpy:336
+    old "Quit"
+    new "終了"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu(メインメニュー)スクリーン"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Ren'py が起動した時に表示されるメインメニューを表示するスクリーンです。"
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:357
+    old "## This ensures that any other menu screen is replaced."
+    new "## 次のコードは、同じタグを持つ他のメニュースクリーンが表示された時にスクリーンを置換します。"
+
+    # screens.rpy:364
+    old "## This empty frame darkens the main menu."
+    new "## 次の空のフレームは gui/overlay/main_menu.png を表示してメインメニューを暗くしています。"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## use 文は、他のスクリーンを現在のスクリーンの内に表示するのに使います。メインメニューの実際のコンテンツは navigation(ナビゲーション)スクリーンです。"
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu(ゲームメニュー)スクリーン"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## このスクリーンは、様々なゲームメニューの基本的な共通構造をレイアウトします。各ゲームメニュースクリーンによって呼び出され、背景・現在のスクリーンタイトル・ナビゲーションを表示します。"
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## scroll パラメーターは None 、\"viewport\" 、\"vpgrid\" のいずれかをとります。呼び出し親のスクリーンのコンテンツは、このスクリーンの中の transclude の部分に配置されます。"
+
+    # screens.rpy:435
+    old "## Reserve space for the navigation section."
+    new "## 次のフレームはナビゲーションを表示するスペースを空けています。"
+
+    # screens.rpy:476
+    old "Return"
+    new "戻る"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About(バージョン情報)スクリーン"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## このスクリーンは、本ゲームと Ren'Py に関するコピーライトとクレジットを表示します。"
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## このスクリーンは特別なことをしていません。そのためカスタムスクリーン作成の例として利用していきます。"
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## 次の use 文は game_menu(ゲームメニュー)スクリーンをこのスクリーンの内に表示しています。use 文の子(内包されたオブジェクト)の vbox は game_menu スクリーンの中の viewport に配置されます。"
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about は、通常 options.rpy で設定します。"
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## 次の変数は about スクリーンにテキストを表示します。この変数は options.rpy で再定義されるため、options.rpy の同じコードを消去しないと反映されません。"
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save(セーブ・ロード)スクリーン"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## 以下のスクリーンは、プレイヤーがゲームデータをセーブ・ロードできるようにします。どちらも構造はほとんど等しいため、第三の file_slots(ファイルスロット)スクリーンで実装しています。"
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "ページ {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "オートセーブ"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "クイックセーブ"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## 次の文は、ページ名の input のイベントがより後に定義したボタンよりも優先されるように、重なり順を反転しています。"
+
+    # screens.rpy:615
+    old "## The page name, which can be edited by clicking on a button."
+    new "## ページ名。クリックすると編集できるように、ボタンとして表示しています。"
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## ファイルスロットを配置するグリッド。"
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%Y年%m月%d日(%a) %H時%M分"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "空のスロット"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## 他のページにアクセスするボタン。"
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:670
+    old "## range(1, 10) gives the numbers from 1 to 9."
+    new "## range(1, 10) は1から9までの数字を生成します。"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences(環境設定)スクリーン"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## Preferences スクリーンは、各プレイヤーがゲームを自分に合う環境にカスタマイズできるようにします。"
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "ディスプレイ"
+
+    # screens.rpy:739
+    old "Window"
+    new "ウィンドウ"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "フルスクリーン"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "ロールバック\nサイド"
+
+    # screens.rpy:745
+    old "Disable"
+    new "無効"
+
+    # screens.rpy:746
+    old "Left"
+    new "レフト"
+
+    # screens.rpy:747
+    old "Right"
+    new "ライト"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "未読テキスト"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "選択肢の後"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "トランジション"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## この場所に \"radio_pref\" または \"check_pref\" をスタイルに持つ vbox を追加して、開発者が定義した環境設定を増やすことができます。"
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "文字表示速度"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "オート待ち時間"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "音楽の音量"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "効果音の音量"
+
+    # screens.rpy:791
+    old "Test"
+    new "テスト"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "ボイスの音量"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "全てミュート"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History(履歴)スクリーン"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## このスクリーンは、ダイアローグヒストリー(台詞の履歴)を表示します。このスクリーンに特別なものはありませんが、_history_list に保存されたダイアローグヒストリーにアクセスする必要があります。"
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## データが大きくなりすぎる可能性があるため、このスクリーンを予測しないようにしています。"
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## 次の文は history_height が None の場合でもレイアウトが正しくなるようにしています。"
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## キャラクター名のカラーが設定されている場合、その情報を獲得して色付けします。"
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "ヒストリーはありません。"
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help(ヘルプ)スクリーン"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## キーやマウスの割り当てに関する情報を表示するスクリーン。実際のヘルプは他のスクリーン(keyboard_help、mouse_help、gamepad_help)を使います。"
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "キーボード"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "マウス"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "ゲームパッド"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "台詞を読み進める。またはボタンを選択する。"
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "台詞を読み進める。ただしボタンは選択しない。"
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "方向キー"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "インターフェースを移動する。"
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "ゲームメニューを開く。"
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "押し続けている間スキップする。"
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "スキップモードに切り替える。"
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "前の台詞に戻る。"
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "ロールバック中、次の台詞に進む。"
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "インターフェースを隠す。"
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "スクリーンショットを撮る。"
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "{a=https://www.renpy.org/l/voicing}セルフボイシング{/a}を有効化する。"
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "左クリック"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "中クリック"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "右クリック"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "マウスホイール上回転\n画面サイドをタッチ"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "マウスホイール下回転"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Rトリガー\nA/下ボタン"
+
+    old "Left Trigger\nLeft Shoulder"
+    new "Lトリガー\nLボタン"
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Rボタン"
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "方向パッド\n左右スティック"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "スタート、ガイド"
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/上ボタン"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "キャリブレート"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## 追加スクリーン"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm(確認)スクリーン"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## Confirm スクリーンは、 Ren'Py がプレイヤーに「はい・いいえ」で答える質問をする時に使います。"
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## 次の文は、このスクリーンが表示されている間、他のスクリーンの反応を無視するようにしています。"
+
+    # screens.rpy:1161
+    old "Yes"
+    new "はい"
+
+    # screens.rpy:1162
+    old "No"
+    new "いいえ"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## 右クリックで「いいえ」と答える。"
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator(スキップ表示)スクリーン"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## Skip_indicator スクリーンは、スキップ中であることを表示するスクリーンです。"
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "スキップ中"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## 矢印を次から次へと点滅させる transform(変換)。"
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify(通知)スクリーン"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## Notify スクリーンは、プレイヤーに短いメッセージを表示するのに使います。(例えばクイックセーブをしたり、スクリーンショットを撮った時。)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL(ノベル)スクリーン"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## このスクリーンは NVL モード(全画面方式)の台詞と選択肢を表示します。"
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## gui.nvl_height が設定されていれば vpgrid で等間隔に表示、そうでなければ vbox で可変的に表示します。"
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## 選択肢があれば表示。config.narrator_menu が初期設定である True のままの場合、正しく表示されないことがあります。"
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## 次の文は一度に表示される NVL モードのエントリー(1台詞)の最大数を制御します。"
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## モバイル用の別設定"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## マウスが無いので、ボタンが大きくて数が少ないクイックメニューに置き換えてタッチしやすいようにしています。"
+
+    # screens.rpy:1429
+    old "Menu"
+    new "メニュー"
+
diff --git a/launcher/game/tl/japanese/script.rpym b/launcher/game/tl/japanese/script.rpym
new file mode 100644
index 0000000..68bab03
--- /dev/null
+++ b/launcher/game/tl/japanese/script.rpym
@@ -0,0 +1,62 @@
+# このファイルにはゲームのスクリプトを記述します。
+
+# Ren'Py のスクリプトは、インデント(行頭の空白)によってブロック分けされています。
+# インデントは Tab や Shift + Tab によって調整することができます。
+
+
+# まず最初に、ゲームに使うキャラクター(台詞を表示するオブジェクト)を定義します。
+# 最初のパラメーターは、テキストウィンドウに表示されるキャラクターの名前です。
+# color のパラメーターを追加すると、キャラクターの名前を色付けできます。
+
+define e = Character('Eileen', color="#c8ffc8")
+
+
+# label ステートメント(命令文)はゲームの処理をまとめてラベル付けします。
+# ラベル間の移動は jump ステートメントか call ステートメントを使います。
+
+# ゲームは start ラベルからスタートします。
+
+label start:
+
+    # 背景を表示します。デフォルトではプレースホルダー(仮画像)を使用しますが、
+    # images ディレクトリーにファイル(ファイル名は "bg room.png" や "bg room.jpg")
+    # を追加すると表示することができます。
+
+    scene bg room
+
+    # スプライト(立ち絵)を表示します。ここではプレースホルダーを使用していますが、
+    # images ディレクトリーに "eileen happy.png" と命名したファイルを追加すると
+    # 表示することができます。
+    
+    # at ステートメントは画像の表示する位置を調整します。
+    # at center は中央に下揃えで表示します。これは省略しても同じ結果になります。
+    # その他に at right、at left などがデフォルトで定義されています。
+
+    show eileen happy at center
+
+    # トランジション(画面遷移効果)を使って表示を画面に反映させます。
+    # 台詞を表示するか with None を使うと、トランジション無しで直ちに表示します。
+    
+    with dissolve
+    
+    # 音楽を再生します。ここではタグを利用して無音を再生していますが、
+    # game ディレクトリーに "music.ogg" と命名したファイルを追加すると
+    # play music "music.ogg" の形で再生することができます。
+    
+    # 効果音を再生する時は play audio "filename" を使用します。
+    # play music とは違って複数の効果音を同時に再生することができます。
+    
+    play music "<silence .5>" 
+    
+    # 以下は台詞を表示します。
+
+    "Hello, world."
+
+    e "Ren'Py の新しいゲームを作成しました。"
+
+    e "ストーリー、画像、音楽を追加すれば、世界にリリースすることができます!"
+
+    # return でゲームを終了します。
+
+    return
+    
diff --git a/launcher/game/tl/japanese/style.rpy b/launcher/game/tl/japanese/style.rpy
index eca846f..460d084 100644
--- a/launcher/game/tl/japanese/style.rpy
+++ b/launcher/game/tl/japanese/style.rpy
@@ -1,32 +1,6 @@
-translate japanese python:
-    MTLC = "tl/japanese/MTLc3m.ttf"
+init python:
+    translate_font("japanese", "MTLc3m.ttf")
+    translate_define("japanese", "gui.language", "'japanese-normal'")
 
-translate japanese style l_default:
-    font MTLC
-    size 16
-
-translate japanese style l_button_text:
-    selected_font MTLC
-    selected_bold True
-
-translate japanese style l_link_text:
-    font MTLC
-
-translate japanese style l_alternate_text:
-    font MTLC
-
-translate japanese style l_navigation_button_text:
-    font MTLC
-
-translate japanese style l_navigation_text:
-    font MTLC
-    bold True
-
-translate japanese style l_checkbox_text:
-    selected_font MTLC
-
-translate japanese style l_nonbox_text:
-    selected_font MTLC
-
-translate japanese style hyperlink_text:
-    font MTLC
+translate japanese python:
+    gui.FONT_SCALE = .9
diff --git a/launcher/game/tl/japanese/translations.rpy b/launcher/game/tl/japanese/translations.rpy
deleted file mode 100644
index 3a4c3a6..0000000
--- a/launcher/game/tl/japanese/translations.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate japanese strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "翻訳の作成または更新"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "翻訳を作成または更新したい言語名を入力してください。"
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "言語名は空の文字列であってはなりません。"
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Pyは翻訳を生成しています…"
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Pyは [language] の翻訳ファイルを生成しました。"
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "どのフォーマットで台詞を抽出しますか?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Pyは台詞を抽出しています…"
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Pyは台詞を抽出し終えました。抽出した台詞はベースディレクトリーの dialogue.[format] にあります。"
-
diff --git a/launcher/game/tl/japanese/updater.rpy b/launcher/game/tl/japanese/updater.rpy
deleted file mode 100644
index ddeeeaa..0000000
--- a/launcher/game/tl/japanese/updater.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-
-translate japanese strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "アップデートチャンネルを選択してください"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "アップデートチャンネルはアップデーターがダウンロードするRen'Pyのバージョンを制御します。アップデートチャンネルを選択してください。"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Release"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}推奨{/b} 全ての新しく配布されるゲームで使用されるべきRen'Pyのバージョンです。"
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Prerelease"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "テストや新機能利用のために使用されるRen'Pyの次期バージョンのプレビューですが、\nゲームの最終リリースには向きません。"
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Experimental"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Ren'Pyの試験的なバージョンです。開発者に頼まれない限りこのバージョンを使用するべきではありません。"
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "エラーが発生しました:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "アップデートをチェックしています。"
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren'Pyは最新です。"
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] が利用可能です。インストールしますか?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "アップデートのダウンロード準備をしています。"
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "アップデートをダウンロードしています。"
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "アップデートを解凍しています。"
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "完了しました。"
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "アップデートはインストールされました。Ren'Pyは再起動します。"
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "アップデートはインストールされました。"
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "アップデートはキャンセルされました。"
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Ren'Py アップデート"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "続行"
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Ren'Pyの開発版で、極めて不安定です。これには最新の機能が含まれていますが、すべては動かないかもしれません。"
-
diff --git a/launcher/game/tl/korean/about.rpy b/launcher/game/tl/korean/about.rpy
deleted file mode 100644
index 1ce7bf7..0000000
--- a/launcher/game/tl/korean/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate korean strings:
-
-    # game/about.rpy:39
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:43
-    old "View license"
-    new "라이선스 보기"
-
-    # game/about.rpy:45
-    old "Back"
-    new "뒤로"
-
diff --git a/launcher/game/tl/korean/add_file.rpy b/launcher/game/tl/korean/add_file.rpy
deleted file mode 100644
index 186c292..0000000
--- a/launcher/game/tl/korean/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate korean strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "파일이름"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "새로 만들 스크립트 파일 이름을 입력하세요."
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "파일 이름에는 반드시 .rpy 확장자가 적혀있어야 합니다."
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "이 파일 이름은 이미 존재합니다."
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# 렌파이는 자동으로 파일 이름이 .rpy 로 끝나는 스크립트 파일을 불러옵니다. \n# 파일을 사용하려면, 레이블을 정의하여 다른 파일에서 해당 레이블로 점프하세요.\n"
-
diff --git a/launcher/game/tl/korean/android.rpy b/launcher/game/tl/korean/android.rpy
deleted file mode 100644
index 9334803..0000000
--- a/launcher/game/tl/korean/android.rpy
+++ /dev/null
@@ -1,173 +0,0 @@
-
-translate korean strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "안드로이드 패키지를 만드려면, RAPT 파일을 내려받은 뒤에 렌파이 디렉토리에 압축 해제하세요. 그 다음 렌파이 런처를 재시작하세요."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "윈도우에서 안드로이드 패키지를 만드려면 32비트 JDK가 필요합니다. JDK는 JRE와 다르므로 PC에 JDK가 없는 자바가 설치되어 있을 수 있습니다.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}JDK를 내려받아 설치한 뒤{/a}, 렌파이 런처를 재시작해주세요."
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT는 설치되었으나 안드로이드 패키지를 만드려면 안드로이드 SDK를 설치해야 합니다. SDK 설치하기 버튼을 눌러 설치하세요."
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT가 설치되었으나 키가 설정되지 않았습니다. 새 키를 만들거나 android.keystore 파일을 복구하세요."
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "현재 선택된 프로젝트의 환경 설정이 이루어지지 않았습니다. \"설정하기\" 버튼으로 패키지를 만들기 전에 설정하세요."
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "\"패키지 만들기\"로 현재 선택된 프로젝트의 패키지를 만들거나, 안드로이드 기기를 연결하고 \"패키지 만들기 & 설치하기\"로 연결된 기기에 패키지를 설치하세요."
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "안드로이드 폰 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스 버튼이 눌린 때에만 마우스로 대신합니다. 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "안드로이드 태블릿 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스 버튼이 눌린 때에만 마우스로 대신합니다. 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "OUYA나 Fire TV 같은 TV기반 안드로이드 콘솔 환경을 모방하여 게임을 실행합니다. 컨트롤러 입력은 화살표 키, 선택 버튼은 Enter 키, 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "안드로이드 SDK 파일과 기타 패키지를 내려받고 설치합니다. 추가적으로 패키지에 사인할 때에 필요한 키를 생성합니다."
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "이 프로젝트의 패키지 이름과 버전, 기타 정보를 설정합니다."
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "구글 플레이 키가 적힌 파일을 에디터로 엽니다.\n\n어플리케이션이 APK 확장자일 때에만 필요합니다. 자세한 내용은 문서를 참조해주세요."
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "안드로이드 패키지를 만듭니다."
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "안드로이드 패키지를 만들고, 현재 컴퓨터에 연결된 안드로이드 기기에 패키지를 설치합니다."
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "TCP/IP 모드로 실행 중인 ADB를 안드로이드 기기에 연결합니다."
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "TCP/IP 모드로 실행 중인 ADB를 안드로이드 기기에서 연결 해제합니다."
-
-    # game/android.rpy:164
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:176
-    old "QUESTION"
-    new "확인"
-
-    # game/android.rpy:437
-    old "Android: [project.current.name!q]"
-    new "안드로이드: [project.current.name!q]"
-
-    # game/android.rpy:457
-    old "Emulation:"
-    new "에뮬레이션:"
-
-    # game/android.rpy:465
-    old "Phone"
-    new "스마트폰"
-
-    # game/android.rpy:469
-    old "Tablet"
-    new "태블릿"
-
-    # game/android.rpy:473
-    old "Television / OUYA"
-    new "TV / OUYA"
-
-    # game/android.rpy:485
-    old "Build:"
-    new "만들기:"
-
-    # game/android.rpy:493
-    old "Install SDK & Create Keys"
-    new "SDK 설치 & 키 생성하기"
-
-    # game/android.rpy:497
-    old "Configure"
-    new "설정하기"
-
-    # game/android.rpy:501
-    old "Build Package"
-    new "패키지 만들기"
-
-    # game/android.rpy:505
-    old "Build & Install"
-    new "패키지 만들기 & 설치"
-
-    # game/android.rpy:516
-    old "Other:"
-    new "기타:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "ADB 연결"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "원격 ADB 연결 해제"
-
-    # game/android.rpy:561
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "안드로이드 앱을 만들기 전에, 렌파이 안드로이드 패키징 도구(RAPT)를 내려받아야합니다. RAPT를 내려받으시겠습니까?"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "원격 ADB 주소"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "\"192.168.1.143:5555\" 형식으로 연결할 기기의 IP주소와 포트를 입력하세요.  문서를 참고하여 기기가 원격 ADB를 지원하는지 확인한 다음, 사용할 주소와 포트를 입력하세요."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "사용할 수 없는 원격 ADB 주소"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "주소에는 ':' 한 개가 포함되어야 합니다."
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "호스트 주소에는 공백이 없어야 합니다."
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "포트는 반드시 숫자이어야 합니다."
-
-translate korean strings:
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "안드로이드 패키지를 만들어 컴퓨터와 연결된 안드로이드 기기에 설치한 뒤 기기에서 설치한 앱을 실행합니다."
-
-    # game/android.rpy:239
-    old "Copying Android files to distributions directory."
-    new "안드로이드 파일을 패키지 경로에 복사하는 중."
-
-    # game/android.rpy:340
-    old "Television"
-    new "TV"
-
-    # game/android.rpy:376
-    old "Build, Install & Launch"
-    new "패키지를 만들어 설치하고 실행하기"
-
diff --git a/launcher/game/tl/korean/choose_directory.rpy b/launcher/game/tl/korean/choose_directory.rpy
deleted file mode 100644
index f91e5fa..0000000
--- a/launcher/game/tl/korean/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate korean strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "프로젝트 경로를 선택하는 tkinter를 구동하지 못했습니다. python-tk나 tkinter 패키지를 설치하세요."
-
diff --git a/launcher/game/tl/korean/choose_theme.rpy b/launcher/game/tl/korean/choose_theme.rpy
deleted file mode 100644
index 976279e..0000000
--- a/launcher/game/tl/korean/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate korean strings:
-
-    # game/choose_theme.rpy:292
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "테마를 바꿀 수 없습니다. options.rpy의 내용이 크게 변경되었을 가능성이 있습니다."
-
-    # game/choose_theme.rpy:357
-    old "Display"
-    new "Display"
-
-    # game/choose_theme.rpy:358
-    old "Window"
-    new "Window"
-
-    # game/choose_theme.rpy:359
-    old "Fullscreen"
-    new "Fullscreen"
-
-    # game/choose_theme.rpy:360
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:367
-    old "Sound Volume"
-    new "Sound Volume"
-
-    # game/choose_theme.rpy:401
-    old "Choose Theme"
-    new "테마 선택하기"
-
-    # game/choose_theme.rpy:414
-    old "Theme"
-    new "테마"
-
-    # game/choose_theme.rpy:438
-    old "Color Scheme"
-    new "색상 배색"
-
-    # game/choose_theme.rpy:469
-    old "Continue"
-    new "계속하기"
-
diff --git a/launcher/game/tl/korean/common.rpy b/launcher/game/tl/korean/common.rpy
index 3d6bc15..94ebdae 100644
--- a/launcher/game/tl/korean/common.rpy
+++ b/launcher/game/tl/korean/common.rpy
@@ -1,557 +1,335 @@
 
 translate korean strings:
 
-    # renpy/common/00action_file.rpy:142
-    old "%b %d, %H:%M"
-    new "%b %d %H:%M"
-
-    # renpy/common/00action_file.rpy:605
-    old "Quick save complete."
-    new "퀵세이브했습니다."
-
-translate korean strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)s 콘솔,  원본 작성자 Shiz, C, delta.\n"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "콘솔을 종료하려면 <esc>키를 누르세요. help를 입력하면 도움말이 나타납니다.\n"
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "렌파이 스크립트 입력 활성화."
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "렌파이 스크립트 입력 비활성화."
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: 도움말을 표시한다"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "commands:\n"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new "<렌파이 스크립트 명령문>: 명령문을 실행한다\n"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new "<파이썬 표현식 또는 명령문>: 표현식이나 명령문을 실행한다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: 콘솔을 비운다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: 콘솔을 종료한다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: slot에서 게임을 불러온다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: slot에 게임을 저장한다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: 최신 스크립트를 불러와 게임을 재시작한다"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <expression>: 파이썬 표현식 expression을 주시한다"
-
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwathch <expression>: expression 표현식의 주시를 중단한다"
-
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: 모든 표현식의 주시를 중단한다"
-
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: label로 점프한다"
-
-
-translate korean strings:
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gallery.rpy:539
-    old "Image [index] of [count] locked."
-    new "[count]의 [index]번째 그림은 잠겨있습니다."
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gallery.rpy:557
-    old "prev"
-    new "뒤로"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gallery.rpy:558
-    old "next"
-    new "앞으로"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gallery.rpy:559
-    old "slideshow"
-    new "슬라이드쇼"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gallery.rpy:560
-    old "return"
-    new "돌아가기"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-translate korean strings:
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:68
-    old "Graphics Acceleration"
-    new "그래픽 가속"
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:72
-    old "Automatically Choose"
-    new "자동으로 선택한다"
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:77
-    old "Force Angle/DirectX Renderer"
-    new "앵글/다이렉트X 렌더러를 강제한다"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:81
-    old "Force OpenGL Renderer"
-    new "오픈GL 렌더러를 강제한다"
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-    # renpy/common/00gltest.rpy:85
-    old "Force Software Renderer"
-    new "소프트웨어 렌더러를 강제한다"
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-    # renpy/common/00gltest.rpy:91
-    old "Changes will take effect the next time this program is run."
-    new "변경사항은 프로그램을 재시작하면 적용됩니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00gltest.rpy:95
-    old "Quit"
-    new "종료"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-    # renpy/common/00gltest.rpy:100
-    old "Return"
-    new "돌아가기"
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00gltest.rpy:130
-    old "Performance Warning"
-    new "성능 경고"
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
 
-    # renpy/common/00gltest.rpy:135
-    old "This computer is using software rendering."
-    new "이 컴퓨터에서는 소프트웨어 렌더링을 사용하고 있습니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
 
-    # renpy/common/00gltest.rpy:137
-    old "This computer is not using shaders."
-    new "이 컴퓨터에서는 쉐이더를 사용하지 않습니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-    # renpy/common/00gltest.rpy:139
-    old "This computer is displaying graphics slowly."
-    new "이 컴퓨터에서는 그래픽을 느리게 표시합니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
 
-    # renpy/common/00gltest.rpy:141
-    old "This computer has a problem displaying graphics: [problem]."
-    new "이 컴퓨터에는 그래픽 표시에 문제가 있습니다. [problem]."
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
 
-    # renpy/common/00gltest.rpy:146
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "컴퓨터의 그래픽 드라비어가 구버전이거나 제대로 작동하지 않습니다. 그래픽을 느리게 표시하거나 제대로 표시하지 못할 수 있습니다. 다이렉트X를 업데이트하면 이 문제를 해결할 수 있습니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
 
-    # renpy/common/00gltest.rpy:148
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "컴퓨터의 그래픽 드라비어가 구버전이거나 제대로 작동하지 않습니다. 그래픽을 느리게 표시하거나 제대로 표시하지 못할 수 있습니다."
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
-    # renpy/common/00gltest.rpy:153
-    old "Update DirectX"
-    new "다이렉트X 업데이트하기"
-
-    # renpy/common/00gltest.rpy:159
-    old "Continue, Show this warning again"
-    new "계속한다. 이 경고를 다시 표시한다."
-
-    # renpy/common/00gltest.rpy:163
-    old "Continue, Don't show warning again"
-    new "계속한다. 이 경고를 다시 표시하지 않는다."
-
-    # renpy/common/00gltest.rpy:189
-    old "Updating DirectX."
-    new "다이렉트X를 업데이트하고 있습니다."
-
-    # renpy/common/00gltest.rpy:193
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "다이렉트X 웹 설치를 시작했습니다. 작업표시줄에 최소화 상태로 시작되었을 수도 있습니다. 설치 안내창에 따라 다이렉트X를 설치하세요."
-
-    # renpy/common/00gltest.rpy:197
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}* 주의{/b}/n 마이크로소프트의 다이렉트X 웹 설치 프로그램은 기본적으로 Bing 툴바를 설치합니다. 이 툴바를 설치하고 싶지 않다면 체크 박스의 체크 표시를 해제하세요."
-
-    # renpy/common/00gltest.rpy:201
-    old "When setup finishes, please click below to restart this program."
-    new "설치가 완료되면 아래 버튼을 눌러 프로그램을 다시 시작하세요."
-
-    # renpy/common/00gltest.rpy:203
-    old "Restart"
-    new "다시 시작"
-
-
-translate korean strings:
-
-    # renpy/common/00keymap.rpy:193
-    old "Saved screenshot as %s."
-    new "스크린샷을 %s 에 저장했습니다."
-
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "자동 다시 불러오기"
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d %H:%M"
 
-translate korean strings:
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "퀵세이브 완료."
 
-    # renpy/common/00layout.rpy:439
+    # 00gui.rpy:227
     old "Are you sure?"
     new "정말입니까?"
 
-    # renpy/common/00layout.rpy:440
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "이 세이브 파일을 지우겠습니까?"
 
-    # renpy/common/00layout.rpy:441
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "이 세이브 파일에 덮어쓰겠습니까?"
 
-    # renpy/common/00layout.rpy:442
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "불러오기를 하면 저장하지 않은 데이터를 잃게 됩니다.\n파일을 불러올까요?"
 
-    # renpy/common/00layout.rpy:443
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "종료하겠습니까?"
 
-    # renpy/common/00layout.rpy:444
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "메인 메뉴로 돌아가겠습니까?\n저장하지 않은 데이터는 잃게 됩니다."
 
-    # renpy/common/00layout.rpy:445
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "스킵을 시작하겠습니까?"
 
-    # renpy/common/00layout.rpy:446
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "다음 선택지가 나타날 때까지 스킵하겠습니까?"
 
-    # renpy/common/00layout.rpy:447
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "읽지 않은 대사나 다음 선택지가 나타날 때까지 스킵하겠습니까?"
-
-
-translate korean strings:
-
-    # renpy/common/00library.rpy:95
-    old "Skip Mode"
-    new "스킵 모드"
-
-    # renpy/common/00library.rpy:98
-    old "Fast Skip Mode"
-    new "고속 스킵 모드"
-
-
-translate korean strings:
-
-    # renpy/common/00updater.rpy:1276
-    old "Updater"
-    new "업데이터"
-
-    # renpy/common/00updater.rpy:1285
-    old "This program is up to date."
-    new "이 프로그램은 최신 버전입니다"
-
-    # renpy/common/00updater.rpy:1287
-    old "[u.version] is available. Do you want to install it?"
-    new "[u.version]을 업데이트할 수 있습니다. 설치하겠습니까?"
-
-    # renpy/common/00updater.rpy:1289
-    old "Preparing to download the updates."
-    new "업데이트 파일 다운로드 준비 중."
-
-    # renpy/common/00updater.rpy:1291
-    old "Downloading the updates."
-    new "업데이트 파일 다운로드 중."
-
-    # renpy/common/00updater.rpy:1293
-    old "Unpacking the updates."
-    new "업데이트 파일 압축해제 중."
-
-    # renpy/common/00updater.rpy:1297
-    old "The updates have been installed. The program will restart."
-    new "업데이트를 설치했습니다. 프로그램을 재시작합니다."
-
-    # renpy/common/00updater.rpy:1299
-    old "The updates have been installed."
-    new "업데이트를 설치했습니다."
-
-    # renpy/common/00updater.rpy:1301
-    old "The updates were cancelled."
-    new "업데이트가 취소되었습니다."
-
-
-translate korean strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "빈 슬롯"
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
-    new "뒤로"
-
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
-    new "앞으로"
-
-
-translate korean strings:
-
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "조이스틱 설정"
-
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-translate korean strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "개발자 메뉴"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "게임 재시작 (Shift + R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "콘솔 (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "변수 확인"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "테마 테스트"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "이미지 위치 확인"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "파일이름 목록"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "이미지 불러오기 목록을 표시하기"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "이미지 불러오기 목록을 숨기기"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "게임이 시작한 이후로 변경된 변수가 없습니다."
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "개발자 메뉴로 돌아가기"
-
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}없는 이미지{/b}"
-
-    # renpy/common/_developer/developer.rpym:424
-    old "Rectangle: %r"
-    new "사각 영역 좌표: %r"
-
-    # renpy/common/_developer/developer.rpym:429
-    old "Mouse position: %r"
-    new "마우스 포인터 좌료: %r"
-
-    # renpy/common/_developer/developer.rpym:431
-    old "Right-click or escape to quit."
-    new "우클릭 및 Esc 키로 종료하기."
-
-    # renpy/common/_developer/developer.rpym:482
-    old "Done"
-    new "완료"
-
-
-translate korean strings:
-
-    # renpy/common/_developer/inspector.rpym:43
-    old "Displayable Inspector"
-    new "디스플레이어블 조사기"
-
-    # renpy/common/_developer/inspector.rpym:49
-    old "Nothing to inspect."
-    new "조사할 것이 없습니다."
-
-    # renpy/common/_developer/inspector.rpym:58
-    old "Size"
-    new "크기"
-
-    # renpy/common/_developer/inspector.rpym:63
-    old "Style"
-    new "스타일"
-
-    # renpy/common/_developer/inspector.rpym:123
-    old "Inspecting Styles of [displayable_name!q]"
-    new "[displayable_name!q]의 스타일 조사 중"
-
-    # renpy/common/_developer/inspector.rpym:135
-    old "displayable:"
-    new "디스플레이어블:"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "        (no properties affect the displayable)"
-    new "(디스플레이어블에 적용되는 속성이 없습니다)"
-
-    # renpy/common/_developer/inspector.rpym:144
-    old "        (default properties omitted)"
-    new "        (기본 속성이 빠져있습니다)"
-
-    # renpy/common/_developer/inspector.rpym:174
-    old "<repr() failed>"
-    new "<repr() 실패>"
-
-
-translate korean strings:
-
-    # renpy/common/_errorhandling.rpym:449
-    old "An exception has occurred."
-    new "예외가 발생했습니다."
-
-    # renpy/common/_errorhandling.rpym:475
-    old "Rollback"
-    new "롤백"
-
-    # renpy/common/_errorhandling.rpym:477
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "게임을 저장하거나 다른 선택지를 선택할 수 있도록 이전으로 롤백합니다."
-
-    # renpy/common/_errorhandling.rpym:480
-    old "Ignore"
-    new "무시"
-
-    # renpy/common/_errorhandling.rpym:482
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "예외를 무시하고 게임을 계속합니다. 간혹 오류가 추가 발생할 수 있습니다."
-
-    # renpy/common/_errorhandling.rpym:485
-    old "Reload"
-    new "다시 불러오기"
-
-    # renpy/common/_errorhandling.rpym:487
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "현재 상태를 저장한 뒤 복원하여 게임을 디스크에서 다시 불러옵니다."
-
-    # renpy/common/_errorhandling.rpym:489
-    old "Open Traceback"
-    new "Traceback.txt 파일 열기"
-
-    # renpy/common/_errorhandling.rpym:491
-    old "Opens the traceback.txt file in a text editor."
-    new "traceback.txt 파일을 스크립트 에디터로 엽니다."
-
-    # renpy/common/_errorhandling.rpym:497
-    old "Quits the game."
-    new "게임을 종료합니다."
-
-    # renpy/common/_errorhandling.rpym:524
-    old "Parsing the script failed."
-    new "스크립트 해석 실패."
-
-    # renpy/common/_errorhandling.rpym:551
-    old "Open Parse Errors"
-    new "Error.txt 파일 열기"
-
-    # renpy/common/_errorhandling.rpym:553
-    old "Opens the errors.txt file in a text editor."
-    new "errors.txt 파일을 스크립트 에디터로 엽니다."
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "스크린샷을 %s 에 저장했습니다."
 
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-translate korean strings:
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/_layout/classic_load_save.rpym:170
-    old "a"
-    new "a"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
-    # renpy/common/_layout/classic_load_save.rpym:179
-    old "q"
-    new "q"
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "스킵 모드"
 
-translate korean strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:387
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "대사 복사하기 기능을 실행했습니다. 'Shift+C'로 종료합니다."
 
-    # renpy/common/00preferences.rpy:389
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "대사 읽기 기능을 실행했습니다. 'v' 키를 눌러 종료합니다."
 
-translate korean strings:
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "렌파이 업데이터는 모바일 기기에서 작동하지 않습니다."
 
-    # renpy/common/00updater.rpy:481
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "오류가 발생했습니다."
 
-    # renpy/common/00updater.rpy:657
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "이 프로젝트는 업데이트 기능을 지원하지 않거나, 이 프로젝트의 업데이트 상태 파일이 제거되었습니다."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "이 계정은 업데이트를 실행할 권한이 없습니다."
 
-    # renpy/common/00updater.rpy:674
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "이 계정은 업데이트 로그를 작성할 권한이 없습니다."
 
-    # renpy/common/00updater.rpy:699
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "업데이트 서명을 확인할 수 없습니다."
 
-    # renpy/common/00updater.rpy:970
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "업데이트 파일이 다운로드되지 않았습니다."
 
-    # renpy/common/00updater.rpy:988
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "업데이트 파일에 올바른 개요가 없습니다. 파일이 손상되었을 수 있습니다."
 
-    # renpy/common/00updater.rpy:1044
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "{} 압축 해제 중, {}는 알 수 없는 타입입니다."
 
-translate korean strings:
+    # 00updater.rpy:1393
+    old "Updater"
+    new "업데이터"
 
-    # renpy/common/_developer/developer.rpym:425
-    old "Rectangle copied to clipboard."
-    new "선택 영역 좌표가 복사되었습니다."
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "이 프로그램은 최신 버전입니다"
 
-    # renpy/common/_developer/developer.rpym:428
-    old "Position copied to clipboard."
-    new "좌표가 복사되었습니다."
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version]을 업데이트할 수 있습니다. 설치하겠습니까?"
 
-translate korean strings:
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "업데이트 파일 다운로드 준비 중."
+
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "업데이트 파일 다운로드 중."
+
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "업데이트 파일 압축해제 중."
 
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "위치"
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "업데이트를 설치했습니다. 프로그램을 재시작합니다."
+
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "업데이트를 설치했습니다."
+
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "업데이트가 취소되었습니다."
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "[count]의 [index]번째 그림은 잠겨있습니다."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "뒤로"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "앞으로"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "슬라이드쇼"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "돌아가기"
 
diff --git a/launcher/game/tl/korean/developer.rpy b/launcher/game/tl/korean/developer.rpy
new file mode 100644
index 0000000..771b7c4
--- /dev/null
+++ b/launcher/game/tl/korean/developer.rpy
@@ -0,0 +1,179 @@
+
+translate korean strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "개발자 메뉴"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "게임 재시작 (Shift + R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "콘솔 (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "변수 확인"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "테마 테스트"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "이미지 위치 확인"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "파일이름 목록"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "이미지 불러오기 목록을 표시하기"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "이미지 불러오기 목록을 숨기기"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "조사할 것이 없습니다."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "개발자 메뉴로 돌아가기"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "사각 영역 좌표: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "마우스 포인터 좌료: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "우클릭 및 Esc 키로 종료하기."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "선택 영역 좌표가 복사되었습니다."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "좌표가 복사되었습니다."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "디스플레이어블 조사기"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "크기"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "스타일"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "위치"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "[displayable_name!q]의 스타일 조사 중"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "디스플레이어블:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "(디스플레이어블에 적용되는 속성이 없습니다)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (기본 속성이 빠져있습니다)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() 실패>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "콘솔을 종료하려면 <esc>키를 누르세요. help를 입력하면 도움말이 나타납니다.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "렌파이 스크립트 입력 활성화."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "렌파이 스크립트 입력 비활성화."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: 도움말을 표시한다"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "commands:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new "<렌파이 스크립트 명령문>: 명령문을 실행한다\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new "<파이썬 표현식 또는 명령문>: 표현식이나 명령문을 실행한다"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: 콘솔을 비운다"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: 콘솔을 종료한다"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: slot에서 게임을 불러온다"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: slot에 게임을 저장한다"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: 최신 스크립트를 불러와 게임을 재시작한다"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: 파이썬 표현식 expression을 주시한다"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwathch <expression>: expression 표현식의 주시를 중단한다"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: 모든 표현식의 주시를 중단한다"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: label로 점프한다"
+
diff --git a/launcher/game/tl/korean/distribute.rpy b/launcher/game/tl/korean/distribute.rpy
deleted file mode 100644
index 70cef81..0000000
--- a/launcher/game/tl/korean/distribute.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate korean strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "배포판 만들기에 실패했습니다.\n\n build.directory_name 변수에는 공백이나 콜론, 세미 콜론 문자를 입력할 수 없습니다."
-
-    # game/distribute.rpy:381
-    old "No packages are selected, so there's nothing to do."
-    new "선택된 패키지가 없으므로 할 수 있는 작업이 없습니다."
-
-    # game/distribute.rpy:386
-    old "Scanning project files..."
-    new "프로젝트 파일 살펴보는 중..."
-
-    # game/distribute.rpy:396
-    old "Scanning Ren'Py files..."
-    new "렌파이 파일 살펴보는 중..."
-
-    # game/distribute.rpy:444
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "패키지를 전부 작성했습니다.\n\n 권한 정보로 인해 리눅스와 매킨토시 배포판을 윈도우에서 압축해제하거나 재압축하는 것은 지원하지 않습니다."
-
-    # game/distribute.rpy:568
-    old "Archiving files..."
-    new "파일 압축 중..."
-
-    # game/distribute.rpy:831
-    old "Writing the [variant] [format] package."
-    new "[variant] [format] 패키지 작성 중."
-
-    # game/distribute.rpy:844
-    old "Making the [variant] update zsync file."
-    new "[variant] 업데이트 zsync 파일 생성 중."
-
-    # game/distribute.rpy:940
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "총 {b}[total]{/b}개의 파일 중에서 {b}[complete]{/b} 파일 완료."
-
diff --git a/launcher/game/tl/korean/distribute_gui.rpy b/launcher/game/tl/korean/distribute_gui.rpy
deleted file mode 100644
index 7f3e07f..0000000
--- a/launcher/game/tl/korean/distribute_gui.rpy
+++ /dev/null
@@ -1,65 +0,0 @@
-
-translate korean strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "[project.current.name!q] 배포판 만들기"
-
-    # game/distribute_gui.rpy:172
-    old "Directory Name:"
-    new "디렉토리 이름:"
-
-    # game/distribute_gui.rpy:176
-    old "Executable Name:"
-    new "실행 파일 이름:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "작업:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "options.rpy 수정하기"
-
-    # game/distribute_gui.rpy:194
-    old "Refresh"
-    new "새로고침"
-
-    # game/distribute_gui.rpy:211
-    old "Build Packages:"
-    new "만들 패키지:"
-
-    # game/distribute_gui.rpy:225
-    old "Build Updates"
-    new "업데이트 파일 만들기"
-
-    # game/distribute_gui.rpy:229
-    old "Build"
-    new "만들기"
-
-    # game/distribute_gui.rpy:236
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "프로젝트를 실행하던 도중 오류를 발견했습니다. 배포판을 작성하기 전에 프로젝트가 오류 없이 실행되는지 확인하세요."
-
-    # game/distribute_gui.rpy:253
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "프로젝트에 배포판 정보가 없습니다. options.rpy 끝부분에 배포판 정보를 추가하겠습니까?"
-
-translate korean strings:
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "from 절을 call 문에 추가하기(1회)"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "설정:"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "from 절을 call 문에 추가하기"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "from 절이 없는 call 문에 from 절을 추가합니다."
-
diff --git a/launcher/game/tl/korean/editor.rpy b/launcher/game/tl/korean/editor.rpy
deleted file mode 100644
index 61dd1b4..0000000
--- a/launcher/game/tl/korean/editor.rpy
+++ /dev/null
@@ -1,55 +0,0 @@
-
-translate korean strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}추천.{/b} 인터페이스를 사용하기 쉬우며 맞춤법 검사 등 개발을 편리하게 해주는 기능이 있는 에디터입니다. 에디트라는 현재 중국어, 일본어, 한국어 텍스트를 입력할 때 필요한 IME를 지원하지 않습니다."
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}추천.{/b} 인터페이스를 사용하기 쉬우며 맞춤법 검사 등 개발을 편리하게 해주는 기능이 있는 에디터입니다. 에디트라는 현재 중국어, 일본어, 한국어 텍스트를 입력할 때 필요한 IME를 지원하지 않습니다. 에디트라를 리눅스에서 실행하려면 wxPython이 필요합니다."
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "wxPython이 설치되지 않아 문제가 발생했을 가능성이 있습니다."
-
-    # game/editor.rpy:174
-    old "Up to 22 MB download required."
-    new "22MB 내려받기 필요."
-
-    # game/editor.rpy:185
-    old "A mature editor that requires Java."
-    new "Java를 사용하는 완성도 높은 에디터."
-
-    # game/editor.rpy:187
-    old "1.8 MB download required."
-    new "1.8MB 내려받기 필요."
-
-    # game/editor.rpy:188
-    old "This may have occured because Java is not installed on this system."
-    new "Java가 설치되지 않아 문제가 발생했을 수도 있습니다."
-
-    # game/editor.rpy:194
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "OS에서 .rpy 파일을 열 때 사용하는 에디터를 실행합니다."
-
-    # game/editor.rpy:210
-    old "Prevents Ren'Py from opening a text editor."
-    new "렌파이가 스크립트 에디터를 실행하지 못하도록 합니다."
-
-    # game/editor.rpy:357
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "스크립트 에디터를 실행하던 도중 예외가 발생했습니다:\n[exception!q]"
-
-    # game/editor.rpy:453
-    old "Select Editor"
-    new "에디터 선택하기"
-
-    # game/editor.rpy:468
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "스크립트 에디터란 렌파이 스크립트 파일을 수정할 때 사용하는 프로그램입니다. 이곳에서는 렌파이가 실행시킬 에디터를 선택할 수 있습니다. 에디터가 없다면 에디터를 자동으로 다운로드해 설치합니다."
-
-    # game/editor.rpy:490
-    old "Cancel"
-    new "취소"
-
diff --git a/launcher/game/tl/korean/error.rpy b/launcher/game/tl/korean/error.rpy
new file mode 100644
index 0000000..2d60649
--- /dev/null
+++ b/launcher/game/tl/korean/error.rpy
@@ -0,0 +1,179 @@
+
+translate korean strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "그래픽 가속"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "자동으로 선택한다"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "앵글/다이렉트X 렌더러를 강제한다"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "오픈GL 렌더러를 강제한다"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "소프트웨어 렌더러를 강제한다"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "변경사항은 프로그램을 재시작하면 적용됩니다."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "성능 경고"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "이 컴퓨터에서는 소프트웨어 렌더링을 사용하고 있습니다."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "이 컴퓨터에서는 쉐이더를 사용하지 않습니다."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "이 컴퓨터에서는 그래픽을 느리게 표시합니다."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "이 컴퓨터에는 그래픽 표시에 문제가 있습니다. [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "컴퓨터의 그래픽 드라비어가 구버전이거나 제대로 작동하지 않습니다. 그래픽을 느리게 표시하거나 제대로 표시하지 못할 수 있습니다. 다이렉트X를 업데이트하면 이 문제를 해결할 수 있습니다."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "컴퓨터의 그래픽 드라비어가 구버전이거나 제대로 작동하지 않습니다. 그래픽을 느리게 표시하거나 제대로 표시하지 못할 수 있습니다."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "다이렉트X 업데이트하기"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "계속한다. 이 경고를 다시 표시한다."
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "계속한다. 이 경고를 다시 표시하지 않는다."
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "다이렉트X를 업데이트하고 있습니다."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "다이렉트X 웹 설치를 시작했습니다. 작업표시줄에 최소화 상태로 시작되었을 수도 있습니다. 설치 안내창에 따라 다이렉트X를 설치하세요."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}* 주의{/b}/n 마이크로소프트의 다이렉트X 웹 설치 프로그램은 기본적으로 Bing 툴바를 설치합니다. 이 툴바를 설치하고 싶지 않다면 체크 박스의 체크 표시를 해제하세요."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "설치가 완료되면 아래 버튼을 눌러 프로그램을 다시 시작하세요."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "다시 시작"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Traceback.txt 파일 열기"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "traceback.txt 파일을 스크립트 에디터로 엽니다."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "예외가 발생했습니다."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "롤백"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "게임을 저장하거나 다른 선택지를 선택할 수 있도록 이전으로 롤백합니다."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "무시"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "예외를 무시하고 게임을 계속합니다. 간혹 오류가 추가 발생할 수 있습니다."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "다시 불러오기"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "현재 상태를 저장한 뒤 복원하여 게임을 디스크에서 다시 불러옵니다."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "게임을 종료합니다."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "스크립트 해석 실패."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Error.txt 파일 열기"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "errors.txt 파일을 스크립트 에디터로 엽니다."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/korean/front_page.rpy b/launcher/game/tl/korean/front_page.rpy
deleted file mode 100644
index f02a6c5..0000000
--- a/launcher/game/tl/korean/front_page.rpy
+++ /dev/null
@@ -1,117 +0,0 @@
-
-translate korean strings:
-
-    # game/front_page.rpy:89
-    old "refresh"
-    new "새로고침"
-
-    # game/front_page.rpy:116
-    old "+ Create New Project"
-    new "+ 새 프로젝트 만들기"
-
-    # game/front_page.rpy:128
-    old "Launch Project"
-    new "프로젝트 실행"
-
-    # game/front_page.rpy:144
-    old "[p.name!q] (template)"
-    new "[p.name!q] (서식)"
-
-    # game/front_page.rpy:160
-    old "Tutorial"
-    new "길라잡이"
-
-    # game/front_page.rpy:161
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:177
-    old "Active Project"
-    new "진행 중인 프로젝트"
-
-    # game/front_page.rpy:185
-    old "Open Directory"
-    new "폴더 열기"
-
-    # game/front_page.rpy:190
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:191
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:197
-    old "Edit File"
-    new "파일 수정하기"
-
-    # game/front_page.rpy:205
-    old "All script files"
-    new "모든 스크립트 파일"
-
-    # game/front_page.rpy:214
-    old "Navigate Script"
-    new "스크립트 살펴보기"
-
-    # game/front_page.rpy:225
-    old "Check Script (Lint)"
-    new "스크립트 확인 (오류 검사)"
-
-    # game/front_page.rpy:226
-    old "Change Theme"
-    new "테마 바꾸기"
-
-    # game/front_page.rpy:227
-    old "Delete Persistent"
-    new "지속 데이터 삭제하기"
-
-    # game/front_page.rpy:235
-    old "Build Distributions"
-    new "배포판 만들기"
-
-    # game/front_page.rpy:237
-    old "Android"
-    new "안드로이드"
-
-    # game/front_page.rpy:238
-    old "Generate Translations"
-    new "번역 파일 만들기"
-
-    # game/front_page.rpy:239
-    old "Extract Dialogue"
-    new "대사 추출하기"
-
-    # game/front_page.rpy:255
-    old "Checking script for potential problems..."
-    new "스크립트에서 문제가 발생할 수 있는지를 확인하고 있습니다..."
-
-    # game/front_page.rpy:270
-    old "Deleting persistent data..."
-    new "지속 데이터를 삭제하고 있습니다... "
-
-translate korean strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "[text] 경로를 엽니다."
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "[text] 프로젝트를 선택합니다."
-
-    # game/front_page.rpy:198
-    old "images"
-    new "images"
-
-    # game/front_page.rpy:235
-    old "Force Recompile"
-    new "강제 재컴파일"
-
-    # game/front_page.rpy:246
-    old "iOS"
-    new "iOS"
-
-    # game/front_page.rpy:287
-    old "Recompiling all rpy files into rpyc files..."
-    new "모든 rpy 파일을 rpyc 파일로 재컴파일하는 중..."
-
diff --git a/launcher/game/tl/korean/gui.rpy b/launcher/game/tl/korean/gui.rpy
new file mode 100644
index 0000000..5cc4f78
--- /dev/null
+++ b/launcher/game/tl/korean/gui.rpy
@@ -0,0 +1,411 @@
+
+translate korean strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/korean/interface.rpy b/launcher/game/tl/korean/interface.rpy
deleted file mode 100644
index 51e9b31..0000000
--- a/launcher/game/tl/korean/interface.rpy
+++ /dev/null
@@ -1,79 +0,0 @@
-
-translate korean strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "매뉴얼"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "렌파이 공식 홈페이지"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "렌파이 게임 목록"
-
-    # game/interface.rpy:110
-    old "About"
-    new "렌파이란"
-
-    # game/interface.rpy:117
-    old "update"
-    new "업데이트"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "환경설정"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "종료"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "네"
-
-    # game/interface.rpy:194
-    old "No"
-    new "아니오"
-
-    # game/interface.rpy:229
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "패키지 형식에 제한이 있으므로 ASCII가 아닌 문자가 입력된 파일 이름이나 디렉토리 이름은 사용할 수 없습니다."
-
-    # game/interface.rpy:321
-    old "ERROR"
-    new "오류"
-
-    # game/interface.rpy:350
-    old "While [what!q], an error occured:"
-    new "[what!q] 도중, 에러가 발생했습니다:"
-
-    # game/interface.rpy:351
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:369
-    old "Text input may not contain the {{ or [[ characters."
-    new "글자를 입력할 때는 {{나 [[ 문자는 없어야 합니다."
-
-    # game/interface.rpy:374
-    old "File and directory names may not contain / or \\."
-    new "파일 및 디렉토리 이름에는 / 나 \\가 없어야 합니다."
-
-    # game/interface.rpy:380
-    old "File and directory names must consist of ASCII characters."
-    new "파일이나 디렉토리 이름은 ASCII 문자로 지어야 합니다."
-
-    # game/interface.rpy:401
-    old "INFORMATION"
-    new "알림"
-
-    # game/interface.rpy:448
-    old "PROCESSING"
-    new "처리 중"
-
-    # game/interface.rpy:478
-    old "CHOICE"
-    new "선택"
-
diff --git a/launcher/game/tl/korean/ios.rpy b/launcher/game/tl/korean/ios.rpy
deleted file mode 100644
index 2e3b77d..0000000
--- a/launcher/game/tl/korean/ios.rpy
+++ /dev/null
@@ -1,97 +0,0 @@
-translate korean strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "iOS 배포판을 만드려면 renios 패키지를 다운받은 후, 렌'파이 디렉터리에 압축을 해제하세요. 그 다음, 렌'파이를 재시작하세요."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Xcode 프로젝트가 생성될 폴더가 지정되지 않았습니다. '경로 선택' 버튼을 눌러 경로를 선택하세요."
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "현재 렌'파이 프로젝트에 대응하는 Xcode 프로젝트가 없습니다. 'Xcode 프로젝트 만들기'를 눌러 프로젝트를 만드세요."
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "이미 Xcode 프로젝트가 존재합니다. 'Xcode 프로젝트 업데이트'를 눌러 프로젝트를 최신 파일로 업데이트하거나, Xcode를 이용해 프로젝트를 빌드하세요."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "iPhone 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스로 대체합니다. 그러나 마우스를 클릭할 때만 활성화됩니다."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "iPhone 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스로 대체합니다. 그러나 마우스를 클릭할 때만 활성화됩니다."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Xcode 프로젝트가 위치할 경로를 선택합니다."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "현재 프로젝트에 대응하는 Xcode 프로젝트를 만듭니다."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Xcode 프로젝트 파일을 최신 게임 파일으로 업데이트합니다. 이 작업은 프로젝트에 변경 사항이 생길 때마다 행해져야 합니다."
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Xcode에서 Xcode 프로젝트를 엽니다."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Xcode 프로젝트가 있는 경로를 엽니다."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Xcode 프로젝트가 이미 존재합니다. 이전 프로젝트의 이름을 바꾸고 새 프로젝트 파일로 교체하겠습니까?"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:229
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:233
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "경로 선택하기"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "Xcode 프로젝트 만들기"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "Xcode 프로젝트 업데이트하기"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "Xcode 실행하기"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "Xcode 프로젝트 경로 열기"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "iOS 앱을 패키징하기 전, 렌파이 iOS 서포트(renios)를 다운로드할 필요가 있습니다. 지금 다운로드하겠습니까?"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "Xcode 프로젝트 경로"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "경로 선택창을 이용하여 Xcode 프로젝트 경로를 선택하세요.\n{b}경로 선택 창이 이 창의 뒤에 열렸을 수도 있습니다."
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "렌'파이가 Xcode 프로젝트 경로를 다음과 같이 설정했습니다:"
diff --git a/launcher/game/tl/korean/launcher.rpy b/launcher/game/tl/korean/launcher.rpy
new file mode 100644
index 0000000..17e9f47
--- /dev/null
+++ b/launcher/game/tl/korean/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate korean strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "라이선스 보기"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "파일이름"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "새로 만들 스크립트 파일 이름을 입력하세요."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "파일 이름에는 반드시 .rpy 확장자가 적혀있어야 합니다."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "이 파일 이름은 이미 존재합니다."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# 렌파이는 자동으로 파일 이름이 .rpy 로 끝나는 스크립트 파일을 불러옵니다. \n# 파일을 사용하려면, 레이블을 정의하여 다른 파일에서 해당 레이블로 점프하세요.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "안드로이드 패키지를 만드려면, RAPT 파일을 내려받은 뒤에 렌파이 디렉토리에 압축 해제하세요. 그 다음 렌파이 런처를 재시작하세요."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "윈도우에서 안드로이드 패키지를 만드려면 32비트 JDK가 필요합니다. JDK는 JRE와 다르므로 PC에 JDK가 없는 자바가 설치되어 있을 수 있습니다.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}JDK를 내려받아 설치한 뒤{/a}, 렌파이 런처를 재시작해주세요."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT는 설치되었으나 안드로이드 패키지를 만드려면 안드로이드 SDK를 설치해야 합니다. SDK 설치하기 버튼을 눌러 설치하세요."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT가 설치되었으나 키가 설정되지 않았습니다. 새 키를 만들거나 android.keystore 파일을 복구하세요."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "현재 선택된 프로젝트의 환경 설정이 이루어지지 않았습니다. \"설정하기\" 버튼으로 패키지를 만들기 전에 설정하세요."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "\"패키지 만들기\"로 현재 선택된 프로젝트의 패키지를 만들거나, 안드로이드 기기를 연결하고 \"패키지 만들기 & 설치하기\"로 연결된 기기에 패키지를 설치하세요."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "안드로이드 폰 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스 버튼이 눌린 때에만 마우스로 대신합니다. 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "안드로이드 태블릿 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스 버튼이 눌린 때에만 마우스로 대신합니다. 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "OUYA나 Fire TV 같은 TV기반 안드로이드 콘솔 환경을 모방하여 게임을 실행합니다. 컨트롤러 입력은 화살표 키, 선택 버튼은 Enter 키, 메뉴 버튼은 Esc 키, 뒤로 버튼은 PageUp 키가 대신합니다."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "안드로이드 SDK 파일과 기타 패키지를 내려받고 설치합니다. 추가적으로 패키지에 사인할 때에 필요한 키를 생성합니다."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "이 프로젝트의 패키지 이름과 버전, 기타 정보를 설정합니다."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "구글 플레이 키가 적힌 파일을 에디터로 엽니다.\n\n어플리케이션이 APK 확장자일 때에만 필요합니다. 자세한 내용은 문서를 참조해주세요."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "안드로이드 패키지를 만듭니다."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "안드로이드 패키지를 만들고, 현재 컴퓨터에 연결된 안드로이드 기기에 패키지를 설치합니다."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "안드로이드 패키지를 만들어 컴퓨터와 연결된 안드로이드 기기에 설치한 뒤 기기에서 설치한 앱을 실행합니다."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "TCP/IP 모드로 실행 중인 ADB를 안드로이드 기기에 연결합니다."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "TCP/IP 모드로 실행 중인 ADB를 안드로이드 기기에서 연결 해제합니다."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "안드로이드 파일을 패키지 경로에 복사하는 중."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "안드로이드: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "에뮬레이션:"
+
+    # android.rpy:333
+    old "Phone"
+    new "스마트폰"
+
+    # android.rpy:337
+    old "Tablet"
+    new "태블릿"
+
+    # android.rpy:341
+    old "Television"
+    new "TV"
+
+    # android.rpy:353
+    old "Build:"
+    new "만들기:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "SDK 설치 & 키 생성하기"
+
+    # android.rpy:365
+    old "Configure"
+    new "설정하기"
+
+    # android.rpy:369
+    old "Build Package"
+    new "패키지 만들기"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "패키지 만들기 & 설치"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "패키지를 만들어 설치하고 실행하기"
+
+    # android.rpy:388
+    old "Other:"
+    new "기타:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "ADB 연결"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "원격 ADB 연결 해제"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "안드로이드 앱을 만들기 전에, 렌파이 안드로이드 패키징 도구(RAPT)를 내려받아야합니다. RAPT를 내려받으시겠습니까?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "원격 ADB 주소"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "\"192.168.1.143:5555\" 형식으로 연결할 기기의 IP주소와 포트를 입력하세요.  문서를 참고하여 기기가 원격 ADB를 지원하는지 확인한 다음, 사용할 주소와 포트를 입력하세요."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "사용할 수 없는 원격 ADB 주소"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "주소에는 ':' 한 개가 포함되어야 합니다."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "호스트 주소에는 공백이 없어야 합니다."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "포트는 반드시 숫자이어야 합니다."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "프로젝트 경로를 선택하는 tkinter를 구동하지 못했습니다. python-tk나 tkinter 패키지를 설치하세요."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "테마를 바꿀 수 없습니다. options.rpy의 내용이 크게 변경되었을 가능성이 있습니다."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "테마 선택하기"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "테마"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "색상 배색"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "계속하기"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "알림"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "프로젝트 파일 살펴보는 중..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "배포판 만들기에 실패했습니다.\n\n build.directory_name 변수에는 공백이나 콜론, 세미 콜론 문자를 입력할 수 없습니다."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "선택된 패키지가 없으므로 할 수 있는 작업이 없습니다."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "렌파이 파일 살펴보는 중..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "패키지를 전부 작성했습니다.\n\n 권한 정보로 인해 리눅스와 매킨토시 배포판을 윈도우에서 압축해제하거나 재압축하는 것은 지원하지 않습니다."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "파일 압축 중..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "[variant] [format] 패키지 작성 중."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "[variant] 업데이트 zsync 파일 생성 중."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "총 {b}[total]{/b}개의 파일 중에서 {b}[complete]{/b} 파일 완료."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "[project.current.name!q] 배포판 만들기"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "디렉토리 이름:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "실행 파일 이름:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "작업:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "options.rpy 수정하기"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "from 절을 call 문에 추가하기(1회)"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "새로고침"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "만들 패키지:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "설정:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "업데이트 파일 만들기"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "from 절을 call 문에 추가하기"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "강제 재컴파일"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "만들기"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "from 절이 없는 call 문에 from 절을 추가합니다."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "프로젝트를 실행하던 도중 오류를 발견했습니다. 배포판을 작성하기 전에 프로젝트가 오류 없이 실행되는지 확인하세요."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "프로젝트에 배포판 정보가 없습니다. options.rpy 끝부분에 배포판 정보를 추가하겠습니까?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}추천.{/b} 인터페이스를 사용하기 쉬우며 맞춤법 검사 등 개발을 편리하게 해주는 기능이 있는 에디터입니다. 에디트라는 현재 중국어, 일본어, 한국어 텍스트를 입력할 때 필요한 IME를 지원하지 않습니다."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}추천.{/b} 인터페이스를 사용하기 쉬우며 맞춤법 검사 등 개발을 편리하게 해주는 기능이 있는 에디터입니다. 에디트라는 현재 중국어, 일본어, 한국어 텍스트를 입력할 때 필요한 IME를 지원하지 않습니다. 에디트라를 리눅스에서 실행하려면 wxPython이 필요합니다."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "wxPython이 설치되지 않아 문제가 발생했을 가능성이 있습니다."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "22MB 내려받기 필요."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Java를 사용하는 완성도 높은 에디터."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8MB 내려받기 필요."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Java가 설치되지 않아 문제가 발생했을 수도 있습니다."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "OS에서 .rpy 파일을 열 때 사용하는 에디터를 실행합니다."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "렌파이가 스크립트 에디터를 실행하지 못하도록 합니다."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "스크립트 에디터를 실행하던 도중 예외가 발생했습니다:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "에디터 선택하기"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "스크립트 에디터란 렌파이 스크립트 파일을 수정할 때 사용하는 프로그램입니다. 이곳에서는 렌파이가 실행시킬 에디터를 선택할 수 있습니다. 에디터가 없다면 에디터를 자동으로 다운로드해 설치합니다."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "취소"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "[text] 경로를 엽니다."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "새로고침"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ 새 프로젝트 만들기"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "프로젝트 실행"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (서식)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "[text] 프로젝트를 선택합니다."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "길라잡이"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "진행 중인 프로젝트"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "폴더 열기"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "파일 수정하기"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "모든 스크립트 파일"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "스크립트 살펴보기"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "스크립트 확인 (오류 검사)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "테마 바꾸기"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "지속 데이터 삭제하기"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "배포판 만들기"
+
+    # front_page.rpy:253
+    old "Android"
+    new "안드로이드"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "번역 파일 만들기"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "대사 추출하기"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "스크립트에서 문제가 발생할 수 있는지를 확인하고 있습니다..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "지속 데이터를 삭제하고 있습니다... "
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "모든 rpy 파일을 rpyc 파일로 재컴파일하는 중..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "프로젝트 이름"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "프로젝트 이름을 입력하세요:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "프로젝트 이름을 입력하지 않았습니다."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q]는 이미 존재합니다. 다른 프로젝트 이름을 선택하세요."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q]는 이미 존재합니다. 다른 프로젝트 이름을 선택하세요."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "매뉴얼"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "렌파이 공식 홈페이지"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "렌파이 게임 목록"
+
+    # interface.rpy:117
+    old "update"
+    new "업데이트"
+
+    # interface.rpy:119
+    old "preferences"
+    new "환경설정"
+
+    # interface.rpy:120
+    old "quit"
+    new "종료"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "패키지 형식에 제한이 있으므로 ASCII가 아닌 문자가 입력된 파일 이름이나 디렉토리 이름은 사용할 수 없습니다."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "오류"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "[what!q] 도중, 에러가 발생했습니다:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "글자를 입력할 때는 {{나 [[ 문자는 없어야 합니다."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "파일 및 디렉토리 이름에는 / 나 \\가 없어야 합니다."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "파일이나 디렉토리 이름은 ASCII 문자로 지어야 합니다."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "처리 중"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "확인"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "선택"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "iOS 배포판을 만드려면 renios 패키지를 다운받은 후, 렌'파이 디렉터리에 압축을 해제하세요. 그 다음, 렌'파이를 재시작하세요."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Xcode 프로젝트가 생성될 폴더가 지정되지 않았습니다. '경로 선택' 버튼을 눌러 경로를 선택하세요."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "현재 렌'파이 프로젝트에 대응하는 Xcode 프로젝트가 없습니다. 'Xcode 프로젝트 만들기'를 눌러 프로젝트를 만드세요."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "이미 Xcode 프로젝트가 존재합니다. 'Xcode 프로젝트 업데이트'를 눌러 프로젝트를 최신 파일로 업데이트하거나, Xcode를 이용해 프로젝트를 빌드하세요."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "iPhone 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스로 대체합니다. 그러나 마우스를 클릭할 때만 활성화됩니다."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "iPhone 환경을 모방하여 프로젝트를 실행합니다.\n\n터치 입력은 마우스로 대체합니다. 그러나 마우스를 클릭할 때만 활성화됩니다."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Xcode 프로젝트가 위치할 경로를 선택합니다."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "현재 프로젝트에 대응하는 Xcode 프로젝트를 만듭니다."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Xcode 프로젝트 파일을 최신 게임 파일으로 업데이트합니다. 이 작업은 프로젝트에 변경 사항이 생길 때마다 행해져야 합니다."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Xcode에서 Xcode 프로젝트를 엽니다."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Xcode 프로젝트가 있는 경로를 엽니다."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Xcode 프로젝트가 이미 존재합니다. 이전 프로젝트의 이름을 바꾸고 새 프로젝트 파일로 교체하겠습니까?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "경로 선택하기"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Xcode 프로젝트 만들기"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Xcode 프로젝트 업데이트하기"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Xcode 실행하기"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Xcode 프로젝트 경로 열기"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "iOS 앱을 패키징하기 전, 렌파이 iOS 서포트(renios)를 다운로드할 필요가 있습니다. 지금 다운로드하겠습니까?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "Xcode 프로젝트 경로"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "경로 선택창을 이용하여 Xcode 프로젝트 경로를 선택하세요.\n{b}경로 선택 창이 이 창의 뒤에 열렸을 수도 있습니다."
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "렌'파이가 Xcode 프로젝트 경로를 다음과 같이 설정했습니다:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "[project.current.name] 살펴보기"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "순서: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "알파벳 순서로"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "파일 별로"
+
+    # navigation.rpy:182
+    old "natural"
+    new "생성된 순서대로"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "종류:"
+
+    # navigation.rpy:196
+    old "files"
+    new "파일"
+
+    # navigation.rpy:197
+    old "labels"
+    new "레이블"
+
+    # navigation.rpy:198
+    old "defines"
+    new "정의"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "트랜스폼"
+
+    # navigation.rpy:200
+    old "screens"
+    new "스크린"
+
+    # navigation.rpy:201
+    old "callables"
+    new "콜러블"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "해야할 작업"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ 새 스크립트 파일 추가하기"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "TODO 주석을 발견하지 못했습니다.\n\nTODO 주석을 만드려면 스크립트 파일에 \"# TODO\" 를 적으세요."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "이름 목록이 비었습니다."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "프로젝트 경로를 설정할 수 없습니다. 취소 중."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "프로젝트의 서식을 선택하세요"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "새 프로젝트에서 사용할 서식을 선택하세요. 서식은 기본 사용 폰트와 UI 언어를 설정합니다. 본인이 사용하는 언어가 지원되지 않는다면, 'english' 를 선택하세요."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "런처 환경설정"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "프로젝트 경로:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "프로젝트 경로: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "설정되지 않음"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "스크립트 에디터:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "텍스트 에디터: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "업데이트 경로:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "스크립트 살펴보기 옵션:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "개인 이름을 포함한다"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "라이브러리 이름을 포함한다"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "런처 옵션:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "하드웨어 렌더링"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "서식 표시하기"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "파일 수정하기 영역 표시하기"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "글자 크게 표시하기"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "콘솔 출력"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "런처 프로젝트 열기"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "언어:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "스크립트를 변경한 다음에는 Shift+R를 눌러 게임을 다시 불러오세요."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Shift+O로 콘솔을 엽니다."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Shift+D로 개발자 메뉴를 엽니다."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "프로젝트는 자주 백업합시다!"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "프로젝트를 실행하지 못했습니다."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "이 명령을 실행하기 전에 프로젝트를 정상적으로 실행했는지 확인하세요."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "프로젝트를 살펴보고 있습니다..."
+
+    # project.rpy:568
+    old "Launching"
+    new "실행 중"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "프로젝트 경로"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "경로 선택창을 이용하여 프로젝트가 저장된 경로를 선택하세요.\n{b}경로 선택창이 런처 창 뒤에서 열렸을 수도 있습니다."
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "런처가 이 경로를 살펴보고 이 경로에서 새 프로젝트를 생성하며 프로젝트 배포판을 만듭니다."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "렌파이가 프로젝트 경로를 다음과 같이 설정했습니다."
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "번역 파일 생성 시 빈 문자열 만들기"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "번역 파일을 만들고 있습니다..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "[language] 번역 파일을 만들었습니다."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "대사를 추출하고 있습니다..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "업데이트 경로 선택"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "업데이트 경로는 업데이터가 다운로드할 렌파이 버전을 제어합니다. 업데이트 경로를 선택해주세요:"
+
+    # updater.rpy:91
+    old "Release"
+    new "배포판"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}추천.{/b} 새로 배포되는 게임에서 사용할 렌파이 버전."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "선배포판"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "렌파이의 다음 버전을 테스트하거나 새로운 기능을 미리 이용할 수 있으나 게임을 최종적으로 배포하기에는 적합하지 않은 선배포 버전. "
+
+    # updater.rpy:114
+    old "Experimental"
+    new "실험용"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "렌파이 실험용 버전. 렌파이 개발자에게 요구받은 것이 아니라면 이 경로를 선택하지 마십시오."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "야간용"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "검증되지 않은 렌파이 최신 버전. 최신 기능이 포함되어 있거나 전혀 실행되지 않을 수도 있습니다."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "오류가 발생했습니다:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "업데이트 확인 중."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "렌파이가 최신 버전입니다."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] 버전을 내려받을 수 있습니다. 설치할까요?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "업데이트 파일 내려받기 준비."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "업데이트 파일 내려받는 중."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "업데이트 파일 압축해제 중."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "마무리 중."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "업데이트를 설치했습니다. 렌파이를 재시작합니다."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "업데이트를 설치했습니다."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "업데이트가 취소되었습니다."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "렌파이 업데이트"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "다음으로"
+
diff --git a/launcher/game/tl/korean/navigation.rpy b/launcher/game/tl/korean/navigation.rpy
deleted file mode 100644
index 10a63cc..0000000
--- a/launcher/game/tl/korean/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate korean strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "[project.current.name] 살펴보기"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "순서: "
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "알파벳 순서로"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "파일 별로"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "생성된 순서대로"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "종류:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "파일"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "레이블"
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "정의"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "트랜스폼"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "스크린"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "콜러블"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "해야할 작업"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ 새 스크립트 파일 추가하기"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "TODO 주석을 발견하지 못했습니다.\n\nTODO 주석을 만드려면 스크립트 파일에 \"# TODO\" 를 적으세요."
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "이름 목록이 비었습니다."
-
diff --git a/launcher/game/tl/korean/new_project.rpy b/launcher/game/tl/korean/new_project.rpy
deleted file mode 100644
index c982223..0000000
--- a/launcher/game/tl/korean/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate korean strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "프로젝트의 서식을 선택하세요"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "새 프로젝트에서 사용할 서식을 선택하세요. 서식은 기본 사용 폰트와 UI 언어를 설정합니다. 본인이 사용하는 언어가 지원되지 않는다면, 'english' 를 선택하세요."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "프로젝트 경로를 설정할 수 없습니다. 취소 중."
-
-    # game/new_project.rpy:76
-    old "PROJECT NAME"
-    new "프로젝트 이름"
-
-    # game/new_project.rpy:77
-    old "Please enter the name of your project:"
-    new "프로젝트 이름을 입력하세요:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "프로젝트 이름을 입력하지 않았습니다."
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q]는 이미 존재합니다. 다른 프로젝트 이름을 선택하세요."
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q]는 이미 존재합니다. 다른 프로젝트 이름을 선택하세요."
-
diff --git a/launcher/game/tl/korean/obsolete.rpy b/launcher/game/tl/korean/obsolete.rpy
new file mode 100644
index 0000000..76c5453
--- /dev/null
+++ b/launcher/game/tl/korean/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate korean strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "조이스틱 설정"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "빈 슬롯."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "뒤로"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "앞으로"
+
diff --git a/launcher/game/tl/korean/options.rpy b/launcher/game/tl/korean/options.rpy
new file mode 100644
index 0000000..16a6761
--- /dev/null
+++ b/launcher/game/tl/korean/options.rpy
@@ -0,0 +1,195 @@
+
+translate korean strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/korean/preferences.rpy b/launcher/game/tl/korean/preferences.rpy
deleted file mode 100644
index 25f0715..0000000
--- a/launcher/game/tl/korean/preferences.rpy
+++ /dev/null
@@ -1,85 +0,0 @@
-
-translate korean strings:
-
-    # game/preferences.rpy:58
-    old "Launcher Preferences"
-    new "런처 환경설정"
-
-    # game/preferences.rpy:79
-    old "Projects Directory:"
-    new "프로젝트 경로:"
-
-    # game/preferences.rpy:86
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:88
-    old "Not Set"
-    new "설정되지 않음"
-
-    # game/preferences.rpy:102
-    old "Text Editor:"
-    new "스크립트 에디터:"
-
-    # game/preferences.rpy:124
-    old "Update Channel:"
-    new "업데이트 경로:"
-
-    # game/preferences.rpy:144
-    old "Navigation Options:"
-    new "스크립트 살펴보기 옵션:"
-
-    # game/preferences.rpy:148
-    old "Include private names"
-    new "개인 이름을 포함한다"
-
-    # game/preferences.rpy:149
-    old "Include library names"
-    new "라이브러리 이름을 포함한다"
-
-    # game/preferences.rpy:159
-    old "Launcher Options:"
-    new "런처 옵션:"
-
-    # game/preferences.rpy:163
-    old "Hardware rendering"
-    new "하드웨어 렌더링"
-
-    # game/preferences.rpy:164
-    old "Show templates"
-    new "서식 표시하기"
-
-    # game/preferences.rpy:167
-    old "Console output"
-    new "콘솔 출력"
-
-    # game/preferences.rpy:188
-    old "Open launcher project"
-    new "런처 프로젝트 열기"
-
-    # game/preferences.rpy:202
-    old "Language:"
-    new "언어:"
-
-translate korean strings:
-
-    # game/preferences.rpy:94
-    old "Projects directory: [text]"
-    new "프로젝트 경로: [text]"
-
-    # game/preferences.rpy:117
-    old "Text editor: [text]"
-    new "텍스트 에디터: [text]"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "파일 수정하기 영역 표시하기"
-
-    # game/preferences.rpy:175
-    old "Large fonts"
-    new "글자 크게 표시하기"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "번역 파일 생성 시 빈 문자열 만들기"
-
diff --git a/launcher/game/tl/korean/project.rpy b/launcher/game/tl/korean/project.rpy
deleted file mode 100644
index 70dc643..0000000
--- a/launcher/game/tl/korean/project.rpy
+++ /dev/null
@@ -1,54 +0,0 @@
-
-translate korean strings:
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "프로젝트는 자주 백업합시다!"
-
-    # game/project.rpy:48
-    old "After making changes to the script, press shift+R to reload your game."
-    new "스크립트를 변경한 다음에는 Shift+R를 눌러 게임을 다시 불러오세요."
-
-    # game/project.rpy:49
-    old "Press shift+O (the letter) to access the console."
-    new "Shift+O로 콘솔을 엽니다."
-
-    # game/project.rpy:50
-    old "Press shift+D to access the developer menu."
-    new "Shift+D로 개발자 메뉴를 엽니다."
-
-    # game/project.rpy:219
-    old "Launching the project failed."
-    new "프로젝트를 실행하지 못했습니다."
-
-    # game/project.rpy:219
-    old "Please ensure that your project launches normally before running this command."
-    new "이 명령을 실행하기 전에 프로젝트를 정상적으로 실행했는지 확인하세요."
-
-    # game/project.rpy:232
-    old "Ren'Py is scanning the project..."
-    new "프로젝트를 살펴보고 있습니다..."
-
-    # game/project.rpy:516
-    old "Launching"
-    new "실행 중"
-
-    # game/project.rpy:545
-    old "PROJECTS DIRECTORY"
-    new "프로젝트 경로"
-
-    # game/project.rpy:545
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "경로 선택창을 이용하여 프로젝트가 저장된 경로를 선택하세요.\n{b}경로 선택창이 런처 창 뒤에서 열렸을 수도 있습니다."
-
-    # game/project.rpy:545
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "런처가 이 경로를 살펴보고 이 경로에서 새 프로젝트를 생성하며 프로젝트 배포판을 만듭니다."
-
-    # game/project.rpy:585
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "프로젝트 경로를 선택하는 tkinter를 구동하지 못했습니다. python-tk나 tkinter 패키지를 설치하세요."
-
-    # game/project.rpy:595
-    old "Ren'Py has set the projects directory to:"
-    new "렌파이가 프로젝트 경로를 다음과 같이 설정했습니다."
diff --git a/launcher/game/tl/korean/screens.rpy b/launcher/game/tl/korean/screens.rpy
new file mode 100644
index 0000000..d6b249c
--- /dev/null
+++ b/launcher/game/tl/korean/screens.rpy
@@ -0,0 +1,643 @@
+
+translate korean strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "뒤로"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "스킵"
+
+    # screens.rpy:264
+    old "Auto"
+    new "자동저장"
+
+    # screens.rpy:265
+    old "Save"
+    new "저장하기"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "퀵세이브"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "퀵로드"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "설정"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "환경 설정"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "메인 메뉴"
+
+    # screens.rpy:328
+    old "About"
+    new "렌파이란"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "도움말"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "끝내기"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "돌아가기"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "화면 모드"
+
+    # screens.rpy:739
+    old "Window"
+    new "창 모드"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "전체 화면 모드"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "선택지 이후 스킵"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "화면 전환 효과"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "텍스트 속도"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "자동 진행 시간"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "배경음 크기"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "효과음 크기"
+
+    # screens.rpy:791
+    old "Test"
+    new "테스트"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "음성 크기"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "네"
+
+    # screens.rpy:1162
+    old "No"
+    new "아니오"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/korean/script.rpym b/launcher/game/tl/korean/script.rpym
new file mode 100644
index 0000000..20eec09
--- /dev/null
+++ b/launcher/game/tl/korean/script.rpym
@@ -0,0 +1,17 @@
+# 이 파일에 게임 스크립트를 입력합니다.
+
+# image 문을 사용해 이미지를 정의합니다.
+# image eileen happy = "eileen_happy.png"
+
+# 게임에서 사용할 캐릭터를 정의합니다.
+define e = Character('아이린', color="#c8ffc8")
+
+
+# 여기에서부터 게임이 시작합니다.
+label start:
+
+    e "새로운 렌파이 게임을 만들었군요."
+
+    e "이야기와 그림, 음악을 더하면 여러분의 게임을 세상에 배포할 수 있어요!"
+
+    return
diff --git a/launcher/game/tl/korean/style.rpy b/launcher/game/tl/korean/style.rpy
index b6b73fd..352178d 100644
--- a/launcher/game/tl/korean/style.rpy
+++ b/launcher/game/tl/korean/style.rpy
@@ -1,27 +1,7 @@
-translate korean python:
+init python:
+    translate_font("korean", "NanumGothic.ttf")
 
-    NANUM = "tl/korean/NanumGothic.ttf"
-
-    style.l_default.language = "korean-with-spaces"
-    style.l_default.font = NANUM
-    style.l_default.size = 16
-    style.l_default.selected_font = NANUM
-    style.l_default.selected_bold = 1
-
-    style.l_button_text.font = NANUM
-    style.l_checkbox_text.font = NANUM
-    style.l_link_text.font = NANUM
-
-    style.l_button_text.selected_font = NANUM
-    style.l_button_text.selected_bold = 1
-
-    style.l_checkbox_text.selected_font = NANUM
-    style.l_checkbox_text.selected_bold = 1
-
-    style.l_link_text.selected_font = NANUM
-    style.l_link_text.selected_bold = 1
-
-    style.l_alternate_text.font = NANUM
-    style.l_nonbox_text.font = NANUM
+translate korean python:
+    gui.REGULAR_BOLD = True
 
 
diff --git a/launcher/game/tl/korean/translations.rpy b/launcher/game/tl/korean/translations.rpy
deleted file mode 100644
index 065d217..0000000
--- a/launcher/game/tl/korean/translations.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate korean strings:
-
-    # game/translations.rpy:31
-    old "Create or Update Translations"
-    new "번역 파일 생성 및 수정하기"
-
-    # game/translations.rpy:31
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "만들거나 수정하려는 번역 파일의 언어 이름을 입력하세요."
-
-    # game/translations.rpy:36
-    old "The language name can not be the empty string."
-    new "언어 이름에는 빈 문자열을 입력할 수 없습니다."
-
-    # game/translations.rpy:47
-    old "Ren'Py is generating translations...."
-    new "번역 파일을 만들고 있습니다..."
-
-    # game/translations.rpy:51
-    old "Ren'Py has finished generating [language] translations."
-    new "[language] 번역 파일을 만들었습니다."
-
-    # game/translations.rpy:65
-    old "What format would you like for the extracted dialogue?"
-    new "대사를 어떤 파일 형식으로 추출하겠습니까?"
-
-    # game/translations.rpy:77
-    old "Ren'Py is extracting dialogue...."
-    new "대사를 추출하고 있습니다..."
-
-    # game/translations.rpy:81
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "대사를 모두 추출했습니다. 추출한 대사는 프로젝트 폴더에 있는 dialogue.[format] 파일에서 찾을 수 있습니다."
-
diff --git a/launcher/game/tl/korean/updater.rpy b/launcher/game/tl/korean/updater.rpy
deleted file mode 100644
index ca62a58..0000000
--- a/launcher/game/tl/korean/updater.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-
-translate korean strings:
-
-    # game/updater.rpy:78
-    old "Select Update Channel"
-    new "업데이트 경로 선택"
-
-    # game/updater.rpy:89
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "업데이트 경로는 업데이터가 다운로드할 렌파이 버전을 제어합니다. 업데이트 경로를 선택해주세요:"
-
-    # game/updater.rpy:94
-    old "Release"
-    new "배포판"
-
-    # game/updater.rpy:100
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}추천.{/b} 새로 배포되는 게임에서 사용할 렌파이 버전."
-
-    # game/updater.rpy:105
-    old "Prerelease"
-    new "선배포판"
-
-    # game/updater.rpy:111
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "렌파이의 다음 버전을 테스트하거나 새로운 기능을 미리 이용할 수 있으나 게임을 최종적으로 배포하기에는 적합하지 않은 선배포 버전. "
-
-    # game/updater.rpy:117
-    old "Experimental"
-    new "실험용"
-
-    # game/updater.rpy:123
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "렌파이 실험용 버전. 렌파이 개발자에게 요구받은 것이 아니라면 이 경로를 선택하지 마십시오."
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "야간용"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "검증되지 않은 렌파이 최신 버전. 최신 기능이 포함되어 있거나 전혀 실행되지 않을 수도 있습니다."
-
-    # game/updater.rpy:155
-    old "An error has occured:"
-    new "오류가 발생했습니다:"
-
-    # game/updater.rpy:157
-    old "Checking for updates."
-    new "업데이트 확인 중."
-
-    # game/updater.rpy:159
-    old "Ren'Py is up to date."
-    new "렌파이가 최신 버전입니다."
-
-    # game/updater.rpy:161
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] 버전을 내려받을 수 있습니다. 설치할까요?"
-
-    # game/updater.rpy:163
-    old "Preparing to download the update."
-    new "업데이트 파일 내려받기 준비."
-
-    # game/updater.rpy:165
-    old "Downloading the update."
-    new "업데이트 파일 내려받는 중."
-
-    # game/updater.rpy:167
-    old "Unpacking the update."
-    new "업데이트 파일 압축해제 중."
-
-    # game/updater.rpy:169
-    old "Finishing up."
-    new "마무리 중."
-
-    # game/updater.rpy:171
-    old "The update has been installed. Ren'Py will restart."
-    new "업데이트를 설치했습니다. 렌파이를 재시작합니다."
-
-    # game/updater.rpy:173
-    old "The update has been installed."
-    new "업데이트를 설치했습니다."
-
-    # game/updater.rpy:175
-    old "The update was cancelled."
-    new "업데이트가 취소되었습니다."
-
-    # game/updater.rpy:192
-    old "Ren'Py Update"
-    new "렌파이 업데이트"
-
-    # game/updater.rpy:198
-    old "Proceed"
-    new "다음"
-
diff --git a/launcher/game/tl/piglatin/common.rpy b/launcher/game/tl/piglatin/common.rpy
new file mode 100644
index 0000000..954829f
--- /dev/null
+++ b/launcher/game/tl/piglatin/common.rpy
@@ -0,0 +1,334 @@
+translate piglatin strings:
+
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Ondaymay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Uesdaytay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Ednesdayway"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Hursdaytay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Ridayfay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Aturdaysay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Undaysay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Onmay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Uetay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Edway"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Hutay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Rifay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Atsay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Unsay"
+
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}Anuaryjay"
+
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}Ebruaryfay"
+
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}Archmay"
+
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}Prilaay"
+
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}Aymay"
+
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}Unejay"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}Ulyjay"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}Ugustaay"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}Eptembersay"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}Ctoberoay"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}Ovembernay"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}Ecemberday"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Anjay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Ebfay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Armay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Praay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}Aymay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Unjay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Uljay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Ugaay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Epsay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Ctoay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Ovnay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Ecday"
+
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%bay %day, %Hay:%May"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Uickqay avesay ompletecay."
+
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "Reaay ouyay uresay?"
+
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "Reaay ouyay uresay ouyay antway otay eleteday histay avesay?"
+
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "Reaay ouyay uresay ouyay antway otay overwriteay ouryay avesay?"
+
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "Oadinglay illway oselay unsaveday rogresspay.\nReaay ouyay uresay ouyay antway otay oday histay?"
+
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "Reaay ouyay uresay ouyay antway otay uitqay?"
+
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "Reaay ouyay uresay ouyay antway otay eturnray otay hetay ainmay enumay?\nHistay illway oselay unsaveday rogresspay."
+
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Reaay ouyay uresay ouyay antway otay enday hetay eplayray?"
+
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "Reaay ouyay uresay ouyay antway otay eginbay kippingsay?"
+
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "Reaay ouyay uresay ouyay antway otay kipsay otay hetay extnay oicechay?"
+
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Reaay ouyay uresay ouyay antway otay kipsay unseenay ialogueday otay hetay extnay oicechay?"
+
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Avedsay creenshotsay asay %say."
+
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Elfsay-oicingvay isabledday."
+
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Lipboardcay oicingvay enableday. "
+
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Elfsay-oicingvay enableday. "
+
+    # 00library.rpy:178
+    old "Skip Mode"
+    new "Kipsay Odemay"
+
+    # 00library.rpy:261
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "Histay rogrampay ontainscay eefray oftwaresay underay aay umbernay ofay icenseslay, includingay hetay Itmay Icenselay anday Nugay Esserlay Eneralgay Ublicpay Icenselay. Aay ompletecay istlay ofay oftwaresay, includingay inkslay otay ullfay ourcesay odecay, ancay ebay oundfay {a=https://www.renpy.org/l/license}erehay{/a}."
+
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Lipboardcay oicingvay enableday. Resspay 'iftshay+Cay' otay isableday."
+
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Elfsay-oicingvay ouldway aysay \"[renpy.display.tts.last]\". Resspay 'altay+iftshay+Vay' otay isableday."
+
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Elfsay-oicingvay enableday. Resspay 'vay' otay isableday."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Ontactingcay Ppaay Toresay\nLeasepay Aitway..."
+
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "Hetay Enray'Ypay Pdateruay isay otnay upportedsay onay obilemay evicesday."
+
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "Naay erroray isay eingbay imulatedsay."
+
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Ithereay histay rojectpay oesday otnay upportsay updatingay, oray hetay updateay atusstay ilefay asway eletedday."
+
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "Histay accountay oesday otnay avehay ermissionpay otay erformpay anay updateay."
+
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "Histay accountay oesday otnay avehay ermissionpay otay riteway hetay updateay oglay."
+
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "Ouldcay otnay erifyvay updateay ignaturesay."
+
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "Hetay updateay ilefay asway otnay ownloadedday."
+
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "Hetay updateay ilefay oesday otnay avehay hetay orrectcay igestday - itay aymay avehay eenbay orruptedcay."
+
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "Hileway unpackingay {}, unknownay ypetay {}."
+
+    # 00updater.rpy:1393
+    old "Updater"
+    new "Pdateruay"
+
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "Histay rogrampay isay upay otay ateday."
+
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] isay availableay. Oday ouyay antway otay installay itay?"
+
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "Reparingpay otay ownloadday hetay updatesay."
+
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "Ownloadingday hetay updatesay."
+
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "Npackinguay hetay updatesay."
+
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "Hetay updatesay avehay eenbay installeday. Hetay rogrampay illway estartray."
+
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "Hetay updatesay avehay eenbay installeday."
+
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "Hetay updatesay ereway ancelledcay."
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Mageiay [index] ofay [count] ockedlay."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "revpay"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "extnay"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "ideshowslay"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "eturnray"
+
diff --git a/launcher/game/tl/piglatin/developer.rpy b/launcher/game/tl/piglatin/developer.rpy
new file mode 100644
index 0000000..da464af
--- /dev/null
+++ b/launcher/game/tl/piglatin/developer.rpy
@@ -0,0 +1,178 @@
+translate piglatin strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Eveloperday Enumay"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Eloadray Amegay (Hiftsay+Ray)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Onsolecay (Hiftsay+Oay)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Ariablevay Iewervay"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Hemetay Esttay"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Mageiay Ocationlay Ickerpay"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Ilenamefay Istlay"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Howsay Mageiay Oadlay Oglay"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Idehay Mageiay Oadlay Oglay"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Othingnay otay inspectay."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Eturnray otay hetay eveloperday enumay"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Ectangleray: %ray"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Ousemay ositionpay: %ray"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Ightray-ickclay oray escapeay otay uitqay."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Ectangleray opiedcay otay ipboardclay."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Ositionpay opiedcay otay ipboardclay."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ redictedpay imageay (oodgay){/color}\n{color=#fcc}✘ unpredicteday imageay (adbay){/color}\n{color=#fff}Ragday otay ovemay.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Isplayableday Nspectoriay"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Izesay"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Tylesay"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Ocationlay"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Nspectingiay Tylessay ofay [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "isplayableday:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (onay ropertiespay affectay hetay isplayableday)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (efaultday ropertiespay omitteday)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<eprray() ailedfay>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Resspay <escay> otay exitay onsolecay. Ypetay elphay orfay elphay.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Enray'Ypay criptsay enableday."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Enray'Ypay criptsay isabledday."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "elphay: owshay histay elphay"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "ommandscay:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <enpyray criptsay atementstay>: unray hetay atementstay\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <ythonpay expressionay oray atementstay>: unray hetay expressionay oray atementstay"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "earclay: earclay hetay onsolecay istoryhay"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exitay: exitay hetay onsolecay"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "oadlay <otslay>: oadslay hetay amegay omfray otslay"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "avesay <otslay>: avessay hetay amegay inay otslay"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "eloadray: eloadsray hetay amegay, efreshingray hetay criptssay"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "atchway <expressionay>: atchway aay ythonpay expressionay"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatchay <expressionay>: opstay atchingway anay expressionay"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchallay: opstay atchingway allay expressionsay"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "umpjay <abellay>: umpsjay otay abellay"
+
diff --git a/launcher/game/tl/piglatin/error.rpy b/launcher/game/tl/piglatin/error.rpy
new file mode 100644
index 0000000..f74674d
--- /dev/null
+++ b/launcher/game/tl/piglatin/error.rpy
@@ -0,0 +1,178 @@
+translate piglatin strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Raphicsgay Ccelerationaay"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Utomaticallyaay Hoosecay"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Orcefay Ngleaay/Irectxday Endererray"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Orcefay Pengloay Endererray"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Orcefay Oftwaresay Endererray"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Nableeay"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Hangescay illway aketay effectay hetay extnay imetay histay rogrampay isay unray."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Erformancepay Arningway"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Histay omputercay isay usingay oftwaresay enderingray."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Histay omputercay isay otnay usingay adersshay."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Histay omputercay isay isplayingday aphicsgray owlyslay."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Histay omputercay ashay aay roblempay isplayingday aphicsgray: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Tsiay aphicsgray riversday aymay ebay outay ofay ateday oray otnay operatingay orrectlycay. Histay ancay eadlay otay owslay oray incorrectay aphicsgray isplayday. Pdatinguay Irectxday ouldcay ixfay histay roblempay."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Tsiay aphicsgray riversday aymay ebay outay ofay ateday oray otnay operatingay orrectlycay. Histay ancay eadlay otay owslay oray incorrectay aphicsgray isplayday."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Pdateuay Irectxday"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Ontinuecay, Howsay histay arningway againay"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Ontinuecay, Onday'tay owshay arningway againay"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Pdatinguay Irectxday."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Irectxday ebway etupsay ashay eenbay artedstay. Tiay aymay artstay inimizedmay inay hetay askbartay. Leasepay ollowfay hetay romptspay otay installay Irectxday."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Otenay:{/b} Icrosoftmay'say Irectxday ebway etupsay rogrampay illway, ybay efaultday, installay hetay Ingbay oolbartay. Fiay ouyay oday otnay antway histay oolbartay, uncheckay hetay appropriateay oxbay."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Henway etupsay inishesfay, easeplay ickclay elowbay otay estartray histay rogrampay."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Estartray"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Electsay Amepadgay otay Alibratecay"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "Onay Amepadsgay Vailableaay"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Alibratingcay [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Resspay oray ovemay hetay [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Kipsay (Aay)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Ackbay (Bay)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Penoay Racebacktay"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Pensoay hetay acebacktray.xttay ilefay inay aay exttay editoray."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Opycay otay Lipboardcay"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Opiescay hetay acebacktray.xttay ilefay otay hetay ipboardclay."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Naay exceptionay ashay occurreday."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Ollbackray"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Ttemptsaay aay ollray ackbay otay aay riorpay imetay, allowingay ouyay otay avesay oray oosechay aay ifferentday oicechay."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Gnoreiay"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Gnoresiay hetay exceptionay, allowingay ouyay otay ontinuecay. Histay oftenay eadslay otay additionalay errorsay."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Eloadray"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Eloadsray hetay amegay omfray iskday, avingsay anday estoringray amegay atestay ifay ossiblepay."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Uitsqay hetay amegay."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Arsingpay hetay criptsay ailedfay."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Penoay Arsepay Rrorseay"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Pensoay hetay errorsay.xttay ilefay inay aay exttay editoray."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Opiescay hetay errorsay.xttay ilefay otay hetay ipboardclay."
+
diff --git a/launcher/game/tl/piglatin/gui.rpy b/launcher/game/tl/piglatin/gui.rpy
new file mode 100644
index 0000000..f599554
--- /dev/null
+++ b/launcher/game/tl/piglatin/gui.rpy
@@ -0,0 +1,429 @@
+translate piglatin strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Nitializationiay"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## Hetay initay offsetay atementstay ausescay hetay initay odecay inay histay ilefay otay unray eforebay initay odecay inay anyay otheray ilefay."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Allingcay uigay.initay esetsray hetay ylesstay otay ensiblesay efaultday aluesvay, anday etssay hetay idthway anday eighthay ofay hetay amegay."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Olorscay"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## Hetay olorscay ofay exttay inay hetay interfaceay."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## Naay accentay olorcay useday hroughouttay hetay interfaceay otay abellay anday ighlighthay exttay."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## Hetay olorcay useday orfay aay exttay uttonbay henway itay isay eithernay electedsay ornay overedhay."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## Hetay mallsay olorcay isay useday orfay mallsay exttay, hichway eedsnay otay ebay ighterbray/arkerday otay achieveay hetay amesay effectay."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## Hetay olorcay hattay isay useday orfay uttonsbay anday arsbay hattay areay overedhay."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## Hetay olorcay useday orfay aay exttay uttonbay henway itay isay electedsay utbay otnay ocusedfay. Aay uttonbay isay electedsay ifay itay isay hetay urrentcay creensay oray referencepay aluevay."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## Hetay olorcay useday orfay aay exttay uttonbay henway itay annotcay ebay electedsay."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Olorscay useday orfay hetay ortionspay ofay arsbay hattay areay otnay illedfay inay. Hesetay areay otnay useday irectlyday, utbay areay useday henway eray-eneratinggay arbay imageay ilesfay."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## Hetay olorscay useday orfay ialogueday anday enumay oicechay exttay."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Ontsfay anday Ontfay Izessay"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## Hetay ontfay useday orfay inay-amegay exttay."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## Hetay ontfay useday orfay aracterchay amesnay."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## Hetay ontfay useday orfay outay-ofay-amegay exttay."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## Hetay izesay ofay ormalnay ialogueday exttay."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## Hetay izesay ofay aracterchay amesnay."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## Hetay izesay ofay exttay inay hetay amegay'say useray interfaceay."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## Hetay izesay ofay abelslay inay hetay amegay'say useray interfaceay."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## Hetay izesay ofay exttay onay hetay otifynay creensay."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## Hetay izesay ofay hetay amegay'say itletay."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Ainmay anday Amegay Enusmay"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## Hetay imagesay useday orfay hetay ainmay anday amegay enusmay."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Houldsay eway owshay hetay amenay anday ersionvay ofay hetay amegay?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Ialogueday"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## Hesetay ariablesvay ontrolcay owhay ialogueday isay isplayedday onay hetay creensay oneay inelay atay aay imetay."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## Hetay eighthay ofay hetay extboxtay ontainingcay ialogueday."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## Hetay acementplay ofay hetay extboxtay erticallyvay onay hetay creensay. 0ay.0ay isay hetay optay, 0ay.5ay isay entercay, anday 1ay.0ay isay hetay ottombay."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## Hetay acementplay ofay hetay peakingsay aracterchay'say amenay, elativeray otay hetay extboxtay. Hesetay ancay ebay aay holeway umbernay ofay ixelspay omfray hetay eftlay oray optay, oray 0ay.5ay otay entercay."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## Hetay orizontalhay alignmentay ofay hetay aracterchay'say amenay. Histay ancay ebay 0ay.0ay orfay eftlay-aligneday, 0ay.5ay orfay enteredcay, anday 1ay.0ay orfay ightray-aligneday."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## Hetay idthway, eighthay, anday ordersbay ofay hetay oxbay ontainingcay hetay aracterchay'say amenay, oray Onenay otay automaticallyay izesay itay."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## Hetay ordersbay ofay hetay oxbay ontainingcay hetay aracterchay'say amenay, inay eftlay, optay, ightray, ottombay orderay."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## Fiay Ruetay, hetay ackgroundbay ofay hetay ameboxnay illway ebay iledtay, ifay Alsefay, hetay ackgroundbay ifay hetay ameboxnay illway ebay caledsay."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## Hetay acementplay ofay ialogueday elativeray otay hetay extboxtay. Hesetay ancay ebay aay holeway umbernay ofay ixelspay elativeray otay hetay eftlay oray optay idesay ofay hetay extboxtay, oray 0ay.5ay otay entercay."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## Hetay aximummay idthway ofay ialogueday exttay, inay ixelspay."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## Hetay orizontalhay alignmentay ofay hetay ialogueday exttay. Histay ancay ebay 0ay.0ay orfay eftlay-aligneday, 0ay.5ay orfay enteredcay, anday 1ay.0ay orfay ightray-aligneday."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Uttonsbay"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## Hesetay ariablesvay, alongay ithway hetay imageay ilesfay inay uigay/uttonbay, ontrolcay aspectsay ofay owhay uttonsbay areay isplayedday."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## Hetay idthway anday eighthay ofay aay uttonbay, inay ixelspay. Fiay Onenay, Enray'Ypay omputescay aay izesay."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## Hetay ordersbay onay eachay idesay ofay hetay uttonbay, inay eftlay, optay, ightray, ottombay orderay."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## Fiay Ruetay, hetay ackgroundbay imageay illway ebay iledtay. Fiay Alsefay, hetay ackgroundbay imageay illway ebay inearlylay caledsay."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## Hetay ontfay useday ybay hetay uttonbay."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## Hetay izesay ofay hetay exttay useday ybay hetay uttonbay."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## Hesetay ariablesvay overrideay ettingssay orfay ifferentday indskay ofay uttonsbay. Leasepay eesay hetay uigay ocumentationday orfay hetay indskay ofay uttonsbay availableay, anday hatway eachay isay useday orfay."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## Hesetay ustomizationscay areay useday ybay hetay efaultday interfaceay:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## Ouyay ancay alsoay adday ouryay ownay ustomizationscay, ybay addingay roperlypay-amednay ariablesvay. Orfay exampleay, ouyay ancay uncommentay hetay ollowingfay inelay otay etsay hetay idthway ofay aay avigationnay uttonbay."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Hoicecay Uttonsbay"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Hoicecay uttonsbay areay useday inay hetay inay-amegay enusmay."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## Ilefay Lotsay Uttonsbay"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## Aay ilefay otslay uttonbay isay aay pecialsay indkay ofay uttonbay. Tiay ontainscay aay humbnailtay imageay, anday exttay escribingday hetay ontentscay ofay hetay avesay otslay. Aay avesay otslay usesay imageay ilesfay inay uigay/uttonbay, ikelay hetay otheray indskay ofay uttonsbay."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## Hetay avesay otslay uttonbay."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## Hetay idthway anday eighthay ofay humbnailstay useday ybay hetay avesay otsslay."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## Hetay umbernay ofay olumnscay anday owsray inay hetay idgray ofay avesay otsslay."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Ositioningpay anday Pacingsay"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## Hesetay ariablesvay ontrolcay hetay ositioningpay anday pacingsay ofay ariousvay useray interfaceay elementsay."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## Hetay ositionpay ofay hetay eftlay idesay ofay hetay avigationnay uttonsbay, elativeray otay hetay eftlay idesay ofay hetay creensay."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## Hetay erticalvay ositionpay ofay hetay kipsay indicatoray."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## Hetay erticalvay ositionpay ofay hetay otifynay creensay."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## Hetay pacingsay etweenbay enumay oiceschay."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Uttonsbay inay hetay avigationnay ectionsay ofay hetay ainmay anday amegay enusmay."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Ontrolscay hetay amountay ofay pacingsay etweenbay referencespay."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Ontrolscay hetay amountay ofay pacingsay etweenbay referencepay uttonsbay."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## Hetay pacingsay etweenbay ilefay agepay uttonsbay."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## Hetay pacingsay etweenbay ilefay otsslay."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Ramesfay"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## Hesetay ariablesvay ontrolcay hetay ooklay ofay amesfray hattay ancay ontaincay useray interfaceay omponentscay henway anay overlayay oray indowway isay otnay resentpay."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Enericgay amesfray hattay areay introduceday ybay ayerplay odecay."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## Hetay amefray hattay isay useday asay artpay ofay hetay onfirmcay creensay."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## Hetay amefray hattay isay useday asay artpay ofay hetay kipsay creensay."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## Hetay amefray hattay isay useday asay artpay ofay hetay otifynay creensay."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Houldsay amefray ackgroundsbay ebay iledtay?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Arsbay, Crollbarssay, anday Liderssay"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## Hesetay ontrolcay hetay ooklay anday izesay ofay arsbay, crollbarssay, anday idersslay."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## Hetay efaultday Uigay onlyay usesay idersslay anday erticalvay crollbarssay. Llaay ofay hetay otheray arsbay areay onlyay useday inay reatorcay-rittenway odecay."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## Hetay eighthay ofay orizontalhay arsbay, crollbarssay, anday idersslay. Hetay idthway ofay erticalvay arsbay, crollbarssay, anday idersslay."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## Ruetay ifay arbay imagesay ouldshay ebay iledtay. Alsefay ifay heytay ouldshay ebay inearlylay caledsay."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Orizontalhay ordersbay."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Erticalvay ordersbay."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## Hatway otay oday ithway unscrollableay crollbarssay inay hetay uigay. \"idehay\" ideshay hemtay, hileway Onenay owsshay hemtay."
+
+    # gui.rpy:331
+    old "## History"
+    new "## Istoryhay"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## Hetay istoryhay creensay isplaysday ialogueday hattay hetay ayerplay ashay alreadyay ismissedday."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## Hetay umbernay ofay ocksblay ofay ialogueday istoryhay Enray'Ypay illway eepkay."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## Hetay eighthay ofay aay istoryhay creensay entryay, oray Onenay otay akemay hetay eighthay ariablevay atay hetay ostcay ofay erformancepay."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## Hetay ositionpay, idthway, anday alignmentay ofay hetay abellay ivinggay hetay amenay ofay hetay peakingsay aracterchay."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## Hetay ositionpay, idthway, anday alignmentay ofay hetay ialogueday exttay."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## Vlnay-Odemay"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## Hetay Vlnay-odemay creensay isplaysday hetay ialogueday pokensay ybay Vlnay-odemay aracterschay."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## Hetay ordersbay ofay hetay ackgroundbay ofay hetay Vlnay-odemay ackgroundbay indowway."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## Hetay eighthay ofay anay Vlnay-odemay entryay. Etsay histay otay Onenay otay avehay hetay entriesay ynamicallyday adjustay eighthay."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## Hetay pacingsay etweenbay Vlnay-odemay entriesay henway uigay.vl_heightnay isay Onenay, anday etweenbay Vlnay-odemay entriesay anday anay Vlnay-odemay enumay."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## Hetay ositionpay, idthway, anday alignmentay ofay vl_thoughtnay exttay (hetay exttay aidsay ybay hetay vl_narratornay aracterchay.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## Hetay ositionpay ofay vlnay enu_buttonsmay."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## Histay increasesay hetay izesay ofay hetay uickqay uttonsbay otay akemay hemtay easieray otay ouchtay onay abletstay anday onesphay."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## Histay angeschay hetay izesay anday pacingsay ofay ariousvay Uigay elementsay otay ensureay heytay areay easilyay isiblevay onay onesphay."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Ontfay izessay."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Djustaay hetay ocationlay ofay hetay extboxtay."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Hangecay hetay izesay anday pacingsay ofay itemsay inay hetay amegay enumay."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## Ilefay uttonbay ayoutlay."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## Vlnay-odemay."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Uickqay uttonsbay."
+
+
+translate piglatin strings:
+
+    # gui.rpy:17
+    old "## GUI Configuration Variables"
+    new "## Uigay Onfigurationcay Ariablesvay"
+
+    # gui.rpy:168
+    old "## The color of button text in various states."
+    new "## Hetay olorcay ofay uttonbay exttay inay ariousvay atesstay."
+
+    # gui.rpy:174
+    old "## The horizontal alignment of the button text. (0.0 is left, 0.5 is center, 1.0 is right)."
+    new "## Hetay orizontalhay alignmentay ofay hetay uttonbay exttay. (0ay.0ay isay eftlay, 0ay.5ay isay entercay, 1ay.0ay isay ightray)."
+
+    # gui.rpy:398
+    old "## Mobile devices"
+    new "## Obilemay evicesday"
+
diff --git a/launcher/game/tl/piglatin/launcher.rpy b/launcher/game/tl/piglatin/launcher.rpy
new file mode 100644
index 0000000..ff308f3
--- /dev/null
+++ b/launcher/game/tl/piglatin/launcher.rpy
@@ -0,0 +1,1201 @@
+translate piglatin strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Iewvay icenselay"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "Ilenamefay"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Ntereay hetay amenay ofay hetay criptsay ilefay otay reatecay."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Hetay ilenamefay ustmay avehay hetay .pyray extensionay."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Hetay ilefay alreadyay existsay."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Enray'Ypay automaticallyay oadslay allay criptsay ilesfay endingay ithway .pyray. Otay useay histay\n# ilefay, efineday aay abellay anday umpjay otay itay omfray anotheray ilefay.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Otay uildbay Ndroidaay ackagespay, easeplay ownloadday Aptray, unzipay itay, anday aceplay itay intoay hetay Enray'Ypay irectoryday. Hentay estartray hetay Enray'Ypay auncherlay."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Aay 23ay-itbay Avajay Evelopmentday Itkay isay equiredray otay uildbay Ndroidaay ackagespay onay Indowsway. Hetay Dkjay isay ifferentday omfray hetay Rejay, osay itay'say ossiblepay ouyay avehay Avajay ithoutway avinghay hetay Dkjay.\n\nLeasepay {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}ownloadday anday installay hetay Dkjay{/a}, hentay estartray hetay Enray'Ypay auncherlay."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "Aptray ashay eenbay installeday, utbay ouyay'llay eednay otay installay hetay Ndroidaay Dksay eforebay ouyay ancay uildbay Ndroidaay ackagespay. Hoosecay Nstalliay Dksay otay oday histay."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "Aptray ashay eenbay installeday, utbay aay eykay asnhay'tay eenbay onfiguredcay. Leasepay reatecay aay ewnay eykay, oray estoreray androiday.eystorekay."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Hetay urrentcay rojectpay ashay otnay eenbay onfiguredcay. Seuay \"Onfigurecay\" otay onfigurecay itay eforebay uildingbay."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Hoosecay \"Uildbay\" otay uildbay hetay urrentcay rojectpay, oray attachay anay Ndroidaay eviceday anday oosechay \"Uildbay & Nstalliay\" otay uildbay anday installay itay onay hetay eviceday."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ttemptsaay otay emulateay anay Ndroidaay onephay.\n\nOuchtay inputay isay emulateday hroughtay hetay ousemay, utbay onlyay henway hetay uttonbay isay eldhay ownday. Scapeeay isay appedmay otay hetay enumay uttonbay, anday Ageuppay isay appedmay otay hetay ackbay uttonbay."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ttemptsaay otay emulateay anay Ndroidaay ablettay.\n\nOuchtay inputay isay emulateday hroughtay hetay ousemay, utbay onlyay henway hetay uttonbay isay eldhay ownday. Scapeeay isay appedmay otay hetay enumay uttonbay, anday Ageuppay isay appedmay otay hetay ackbay uttonbay."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Ttemptsaay otay emulateay aay elevisontay-asedbay Ndroidaay onsolecay, ikelay hetay Uyaoay oray Irefay Vtay.\n\nOntrollercay inputay isay appedmay otay hetay arroway eyskay, Ntereay isay appedmay otay hetay electsay uttonbay, Scapeeay isay appedmay otay hetay enumay uttonbay, anday Ageuppay isay appedmay otay hetay ackbay uttonbay."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Ownloadsday anday installsay hetay Ndroidaay Dksay anday upportingsay ackagespay. Ptionallyoay, eneratesgay hetay eyskay equiredray otay ignsay hetay ackagepay."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Onfigurescay hetay ackagepay amenay, ersionvay, anday otheray informationay aboutay histay rojectpay."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Pensoay hetay ilefay ontainingcay hetay Ooglegay Laypay eyskay inay hetay editoray.\n\nHistay isay onlyay eedednay ifay hetay applicationay isay usingay anay expansionay Pkaay. Eadray hetay ocumentationday orfay oremay etailsday."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Uildsbay hetay Ndroidaay ackagepay."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Uildsbay hetay Ndroidaay ackagepay, anday installsay itay onay anay Ndroidaay eviceday onnectedcay otay ouryay omputercay."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Uildsbay hetay Ndroidaay ackagepay, installsay itay onay anay Ndroidaay eviceday onnectedcay otay ouryay omputercay, hentay auncheslay hetay appay onay ouryay eviceday."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Onnectscay otay anay Ndroidaay eviceday unningray Dbaay inay Cptay/Piay odemay."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Isconnectsday omfray anay Ndroidaay eviceday unningray Dbaay inay Cptay/Piay odemay."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Etrievesray hetay oglay omfray hetay Ndroidaay eviceday anday ritesway itay otay aay ilefay."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Opyingcay Ndroidaay ilesfay otay istributionsday irectoryday."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Ndroidaay: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Mulationeay:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Honepay"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Ablettay"
+
+    # android.rpy:341
+    old "Television"
+    new "Elevisiontay"
+
+    # android.rpy:353
+    old "Build:"
+    new "Uildbay:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Nstalliay Dksay & Reatecay Eyskay"
+
+    # android.rpy:365
+    old "Configure"
+    new "Onfigurecay"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Uildbay Ackagepay"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Uildbay & Nstalliay"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Uildbay, Nstalliay & Aunchlay"
+
+    # android.rpy:388
+    old "Other:"
+    new "Theroay:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Emoteray Dbaay Onnectcay"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Emoteray Dbaay Isconnectday"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Ogcatlay"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Eforebay ackagingpay Ndroidaay appsay, ouyay'llay eednay otay ownloadday Aptray, hetay Enray'Ypay Ndroidaay Ackagingpay Ooltay. Ouldway ouyay ikelay otay ownloadday Aptray ownay?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Emoteray Dbaay Ddressaay"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Leasepay enteray hetay Piay addressay anday ortpay umbernay otay onnectcay otay, inay hetay ormfay \"921ay.681ay.1ay.431ay:5555ay\". Onsultcay ouryay eviceday'say ocumentationday otay etermineday ifay itay upportssay emoteray Dbaay, anday ifay osay, hetay addressay anday ortpay otay useay."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Nvalidiay emoteray Dbaay addressay"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Hetay addressay ustmay ontaincay oneay exactlyay oneay ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "Hetay osthay aymay otnay ontaincay hitespaceway."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Hetay ortpay ustmay ebay aay umbernay."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Etrievingray ogcatlay informationay omfray eviceday."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Enray'Ypay asway unableay otay unray ythonpay ithway kintertay otay oosechay hetay irectoryday. Leasepay installay hetay ythonpay-ktay oray kintertay ackagepay."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Ouldcay otnay angechay hetay hemetay. Erhapspay optionsay.pyray asway angedchay ootay uchmay."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Lanetariumpay"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Hoosecay Hemetay"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Hemetay"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Olorcay Chemesay"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Ontinuecay"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "Nformationiay"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "Hetay ommandcay isay eingbay unray inay aay ewnay operatingay ystemsay onsolecay indowway."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Canningsay rojectpay ilesfay..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Uildingbay istributionsday ailedfay:\n\nHetay uildbay.irectory_nameday ariablevay aymay otnay includeay hetay pacesay, oloncay, oray emicolonsay aracterschay."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Onay ackagespay areay electedsay, osay heretay'say othingnay otay oday."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Canningsay Enray'Ypay ilesfay..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Llaay ackagespay avehay eenbay uiltbay.\n\nUeday otay hetay resencepay ofay ermissionpay informationay, unpackingay anday epackingray hetay Inuxlay anday Acintoshmay istributionsday onay Indowsway isay otnay upportedsay."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Rchivingaay ilesfay..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Npackinguay hetay Acintoshmay applicationay orfay igningsay..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Igningsay hetay Acintoshmay applicationay..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Reatingcay hetay Acintoshmay Mgday..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Igningsay hetay Acintoshmay Mgday..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Ritingway hetay [variant] [format] ackagepay."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Akingmay hetay [variant] updateay synczay ilefay."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Rocessedpay {b}[complete]{/b} ofay {b}[total]{/b} ilesfay."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Uildbay Istributionsday: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Irectoryday Amenay:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Xecutableeay Amenay:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Ctionsaay:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Diteay optionsay.pyray"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Ddaay omfray ausesclay otay allscay, onceay"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Efreshray"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Ploaduay otay itchay.ioay"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Uildbay Ackagespay:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Ptionsoay:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Uildbay Pdatesuay"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Ddaay omfray ausesclay otay allscay"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Orcefay Ecompileray"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Uildbay"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Ddingaay omfray ausesclay otay allcay atementsstay hattay oday otnay avehay hemtay."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Rrorseay ereway etectedday henway unningray hetay rojectpay. Leasepay ensureay hetay rojectpay unsray ithoutway errorsay eforebay uildingbay istributionsday."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Ouryay rojectpay oesday otnay ontaincay uildbay informationay. Ouldway ouyay ikelay otay adday uildbay informationay otay hetay enday ofay optionsay.pyray?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Ecommendedray.{/b} Aay etabay editoray ithway anay easyay otay useay interfaceay anday eaturesfay hattay aiday inay evelopmentday, uchsay asay pellsay-eckingchay. Ditraeay urrentlycay ackslay hetay Meiay upportsay equiredray orfay Hinesecay, Apanesejay, anday Oreankay exttay inputay."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Ecommendedray.{/b} Aay etabay editoray ithway anay easyay otay useay interfaceay anday eaturesfay hattay aiday inay evelopmentday, uchsay asay pellsay-eckingchay. Ditraeay urrentlycay ackslay hetay Meiay upportsay equiredray orfay Hinesecay, Apanesejay, anday Oreankay exttay inputay. Noay Inuxlay, Ditraeay equiresray xPythonway."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Histay aymay avehay occureday ecausebay xPythonway isay otnay installeday onay histay ystemsay."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Puay otay 22ay Bmay ownloadday equiredray."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Aay aturemay editoray hattay equiresray Avajay."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1ay.8ay Bmay ownloadday equiredray."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Histay aymay avehay occureday ecausebay Avajay isay otnay installeday onay histay ystemsay."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Nvokesiay hetay editoray ouryay operatingay ystemsay ashay associateday ithway .pyray ilesfay."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Reventspay Enray'Ypay omfray openingay aay exttay editoray."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Naay exceptionay occureday hileway aunchinglay hetay exttay editoray:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Electsay Ditoreay"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Aay exttay editoray isay hetay rogrampay ouyay'llay useay otay editay Enray'Ypay criptsay ilesfay. Erehay, ouyay ancay electsay hetay editoray Enray'Ypay illway useay. Fiay otnay alreadyay resentpay, hetay editoray illway ebay automaticallyay ownloadedday anday installeday."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Ancelcay"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Penoay [text] irectoryday."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "efreshray"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Reatecay Ewnay Rojectpay"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Aunchlay Rojectpay"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (emplatetay)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Electsay rojectpay [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Utorialtay"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "Hetay Uestionqay"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Ctiveaay Rojectpay"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Penoay Irectoryday"
+
+    # front_page.rpy:195
+    old "game"
+    new "amegay"
+
+    # front_page.rpy:196
+    old "base"
+    new "asebay"
+
+    # front_page.rpy:197
+    old "images"
+    new "imagesay"
+
+    # front_page.rpy:198
+    old "gui"
+    new "uigay"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Diteay Ilefay"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Llaay criptsay ilesfay"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Avigatenay Criptsay"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Heckcay Criptsay (Intlay)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Hangecay/Pdateuay Uigay"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Hangecay Hemetay"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Eleteday Ersistentpay"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Uildbay Istributionsday"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Ndroidaay"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOSay"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Enerategay Ranslationstay"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Xtracteay Ialogueday"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Heckingcay criptsay orfay otentialpay roblemspay..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Eletingday ersistentpay ataday..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Ecompilingray allay pyray ilesfay intoay pycray ilesfay..."
+
+    # gui7.rpy:202
+    old "Select Accent and Background Colors"
+    new "Electsay Ccentaay anday Ackgroundbay Olorscay"
+
+    # gui7.rpy:216
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Leasepay ickclay onay hetay olorcay chemesay ouyay ishway otay useay, hentay ickclay Ontinuecay. Hesetay olorscay ancay ebay angedchay anday ustomizedcay aterlay."
+
+    # gui7.rpy:260
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Arningway{/b}\nOntinuingcay illway overwriteay ustomizedcay arbay, uttonbay, avesay otslay, crollbarsay, anday iderslay imagesay.\n\nHatway ouldway ouyay ikelay otay oday?"
+
+    # gui7.rpy:260
+    old "Choose new colors, then regenerate image files."
+    new "Hoosecay ewnay olorscay, hentay egenerateray imageay ilesfay."
+
+    # gui7.rpy:260
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Egenerateray hetay imageay ilesfay usingay hetay olorscay inay uigay.pyray."
+
+    # gui7.rpy:280
+    old "PROJECT NAME"
+    new "Rojectpay Amenay"
+
+    # gui7.rpy:280
+    old "Please enter the name of your project:"
+    new "Leasepay enteray hetay amenay ofay ouryay rojectpay:"
+
+    # gui7.rpy:288
+    old "The project name may not be empty."
+    new "Hetay rojectpay amenay aymay otnay ebay emptyay."
+
+    # gui7.rpy:293
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] alreadyay existsay. Leasepay oosechay aay ifferentday rojectpay amenay."
+
+    # gui7.rpy:296
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] alreadyay existsay. Leasepay oosechay aay ifferentday rojectpay amenay."
+
+    # gui7.rpy:307
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "Hatway esolutionray ouldshay hetay rojectpay useay? Lthoughaay Enray'Ypay ancay calesay hetay indowway upay anday ownday, histay isay hetay initialay izesay ofay hetay indowway, hetay izesay atay hichway assetsay ouldshay ebay rawnday, anday hetay izesay atay hichway hetay assetsay illway ebay atay heirtay arpestshay.\n\nHetay efaultday ofay 280x7201ay isay aay easonableray ompromisecay."
+
+    # gui7.rpy:355
+    old "Creating the new project..."
+    new "Reatingcay hetay ewnay rojectpay..."
+
+    # gui7.rpy:357
+    old "Updating the project..."
+    new "Pdatinguay hetay rojectpay..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Ocumentationday"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Enray'Ypay Ebsiteway"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Enray'Ypay Amesgay Istlay"
+
+    # interface.rpy:117
+    old "update"
+    new "updateay"
+
+    # interface.rpy:119
+    old "preferences"
+    new "referencespay"
+
+    # interface.rpy:120
+    old "quit"
+    new "uitqay"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Ueday otay ackagepay ormatfay imitationslay, onnay-Sciiaay ilefay anday irectoryday amesnay areay otnay alloweday."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "Rroreay"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Hileway [what!q], anay erroray occureday:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Exttay inputay aymay otnay ontaincay hetay {{ oray [[ aracterschay."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Ilefay anday irectoryday amesnay aymay otnay ontaincay / oray \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Ilefay anday irectoryday amesnay ustmay onsistcay ofay Sciiaay aracterschay."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "Rocessingpay"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "Uestionqay"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "Hoicecay"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Otay uildbay iOSay ackagespay, easeplay ownloadday eniosray, unzipay itay, anday aceplay itay intoay hetay Enray'Ypay irectoryday. Hentay estartray hetay Enray'Ypay auncherlay."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Hetay irectoryday inay hereway Codexay rojectspay illway ebay acedplay ashay otnay eenbay electedsay. Hoosecay 'Electsay Irectoryday' otay electsay itay."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "Heretay isay onay Codexay rojectpay orrespondingcay otay hetay urrentcay Enray'Ypay rojectpay. Hoosecay 'Reatecay Codexay Rojectpay' otay reatecay oneay."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Naay Codexay rojectpay existsay. Hoosecay 'Pdateuay Codexay Rojectpay' otay updateay itay ithway hetay atestlay amegay ilesfay, oray useay Codexay otay uildbay anday installay itay."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Ttemptsaay otay emulateay anay iPhoneay.\n\nOuchtay inputay isay emulateday hroughtay hetay ousemay, utbay onlyay henway hetay uttonbay isay eldhay ownday."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Ttemptsaay otay emulateay anay iPaday.\n\nOuchtay inputay isay emulateday hroughtay hetay ousemay, utbay onlyay henway hetay uttonbay isay eldhay ownday."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Electssay hetay irectoryday hereway Codexay rojectspay illway ebay acedplay."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Reatescay anay Codexay rojectpay orrespondingcay otay hetay urrentcay Enray'Ypay rojectpay."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Pdatesuay hetay Codexay rojectpay ithway hetay atestlay amegay ilesfay. Histay ustmay ebay oneday eachay imetay hetay Enray'Ypay rojectpay angeschay."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Pensoay hetay Codexay rojectpay inay Codexay."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Pensoay hetay irectoryday ontainingcay Codexay rojectspay."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Hetay Codexay rojectpay alreadyay existsay. Ouldway ouyay ikelay otay enameray hetay olday rojectpay, anday eplaceray itay ithway aay ewnay oneay?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOSay: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhoneay"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPaday"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Electsay Codexay Rojectspay Irectoryday"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Reatecay Codexay Rojectpay"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Pdateuay Codexay Rojectpay"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Aunchlay Codexay"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Penoay Codexay Rojectspay Irectoryday"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Eforebay ackagingpay iOSay appsay, ouyay'llay eednay otay ownloadday eniosray, Enray'Ypay'say iOSay upportsay. Ouldway ouyay ikelay otay ownloadday eniosray ownay?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "Codexay Rojectspay Irectoryday"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Leasepay oosechay hetay Codexay Rojectspay Irectoryday usingay hetay irectoryday ooserchay.\n{b}Hetay irectoryday ooserchay aymay avehay openeday ehindbay histay indowway.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Enray'Ypay ashay etsay hetay Codexay Rojectspay Irectoryday otay:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "Hetay uiltbay istributionsday ouldcay otnay ebay oundfay. Leasepay oosechay 'Uildbay' anday ytray againay."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "Onay uploadableay ilesfay ereway oundfay. Leasepay oosechay 'Uildbay' anday ytray againay."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "Hetay utlerbay rogrampay asway otnay oundfay."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Leasepay installay hetay itchay.ioay appay, hichway includesay utlerbay, anday ytray againay."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "Hetay amenay ofay hetay itchay rojectpay ashay otnay eenbay etsay."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Leasepay {a=https://itch.io/game/new}reatecay ouryay rojectpay{/a}, hentay adday aay inelay ikelay \n{vspace=5}efineday uildbay.itch_projectay = \"useray-amenay/amegay-amenay\"\n{vspace=5} otay optionsay.pyray."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%say{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Avigatenay: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Rderoay: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "alphabeticalay"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "ybay-ilefay"
+
+    # navigation.rpy:182
+    old "natural"
+    new "aturalnay"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Ategorycay:"
+
+    # navigation.rpy:196
+    old "files"
+    new "ilesfay"
+
+    # navigation.rpy:197
+    old "labels"
+    new "abelslay"
+
+    # navigation.rpy:198
+    old "defines"
+    new "efinesday"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "ansformstray"
+
+    # navigation.rpy:200
+    old "screens"
+    new "creenssay"
+
+    # navigation.rpy:201
+    old "callables"
+    new "allablescay"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "Odostay"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Ddaay criptsay ilefay"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Onay Odotay ommentscay oundfay.\n\nOtay reatecay oneay, includeay \"# Odotay\" inay ouryay criptsay."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Hetay istlay ofay amesnay isay emptyay."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "Ewnay Uigay Nterfaceiay"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Othbay interfacesay avehay eenbay anslatedtray otay ouryay anguagelay."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Nlyoay hetay ewnay Uigay ashay eenbay anslatedtray otay ouryay anguagelay."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Nlyoay hetay egacylay hemetay interfaceay ashay eenbay anslatedtray otay ouryay anguagelay."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Eithernay interfaceay ashay eenbay anslatedtray otay ouryay anguagelay."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Hetay rojectspay irectoryday ouldcay otnay ebay etsay. Ivinggay upay."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Hichway interfaceay ouldway ouyay ikelay otay useay? Hetay ewnay Uigay ashay aay odernmay ooklay, upportssay ideway creenssay anday obilemay evicesday, anday isay easieray otay ustomizecay. Egacylay hemestay ightmay ebay ecessarynay otay orkway ithway olderay exampleay odecay.\n\n[language_support!t]\n\nFiay inay oubtday, oosechay hetay ewnay Uigay, hentay ickclay Ontinuecay onay hetay ottombay-ightray."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Egacylay Hemetay Nterfaceiay"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Hoosecay Rojectpay Emplatetay"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Leasepay electsay aay emplatetay otay useay orfay ouryay ewnay rojectpay. Hetay emplatetay etssay hetay efaultday ontfay anday hetay useray interfaceay anguagelay. Fiay ouryay anguagelay isay otnay upportedsay, oosechay 'englishay'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Auncherlay Referencespay"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Rojectspay Irectoryday:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Rojectspay irectoryday: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Otnay Etsay"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Exttay Ditoreay:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Exttay editoray: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Pdateuay Hannelcay:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Avigationnay Ptionsoay:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Ncludeiay rivatepay amesnay"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Ncludeiay ibrarylay amesnay"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Auncherlay Ptionsoay:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Ardwarehay enderingray"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Howsay emplatestay"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Howsay editay ilefay ectionsay"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Argelay ontsfay"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Onsolecay outputay"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Penoay auncherlay rojectpay"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Anguagelay:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Fteraay akingmay angeschay otay hetay criptsay, resspay iftshay+Ray otay eloadray ouryay amegay."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Resspay iftshay+Oay (hetay etterlay) otay accessay hetay onsolecay."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Resspay iftshay+Day otay accessay hetay eveloperday enumay."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Avehay ouyay ackedbay upay ouryay rojectspay ecentlyray?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Aunchinglay hetay rojectpay ailedfay."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Leasepay ensureay hattay ouryay rojectpay auncheslay ormallynay eforebay unningray histay ommandcay."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Enray'Ypay isay canningsay hetay rojectpay..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Aunchinglay"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "Rojectspay Irectoryday"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Leasepay oosechay hetay rojectspay irectoryday usingay hetay irectoryday ooserchay.\n{b}Hetay irectoryday ooserchay aymay avehay openeday ehindbay histay indowway.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Histay auncherlay illway cansay orfay rojectspay inay histay irectoryday, illway reatecay ewnay rojectspay inay histay irectoryday, anday illway aceplay uiltbay rojectspay intoay histay irectoryday."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Enray'Ypay ashay etsay hetay rojectspay irectoryday otay:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Ranslationstay: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "Hetay anguagelay otay orkway ithway. Histay ouldshay onlyay ontaincay owerlay-asecay Sciiaay aracterschay anday underscoresay."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Enerategay emptyay ringsstay orfay anslationstray"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Eneratesgay oray updatesay anslationtray ilesfay. Hetay ilesfay illway ebay acedplay inay amegay/ltay/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Xtracteay Tringsay Ranslationstay"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Ergemay Tringsay Ranslationstay"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Eplaceray existingay anslationstray"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Everseray anguageslay"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Pdateuay Efaultday Nterfaceiay Ranslationstay"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "Hetay extractay ommandcay allowsay ouyay otay extractay ringstay anslationstray omfray anay existingay rojectpay intoay aay emporarytay ilefay.\n\nHetay ergemay ommandcay ergesmay extracteday anslationstray intoay anotheray rojectpay."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Enray'Ypay isay eneratinggay anslationstray...."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Enray'Ypay ashay inishedfay eneratinggay [language] anslationstray."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Enray'Ypay isay extractingay ringstay anslationstray..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Enray'Ypay ashay inishedfay extractingay [language] ringstay anslationstray."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Enray'Ypay isay ergingmay ringstay anslationstray..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Enray'Ypay ashay inishedfay ergingmay [language] ringstay anslationstray."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Pdatinguay efaultday interfaceay anslationstray..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Xtracteay Ialogueday: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Ormatfay:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Abtay-elimitedday Preadsheetsay (ialogueday.abtay)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Ialogueday Exttay Nlyoay (ialogueday.xttay)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Tripsay exttay agstay omfray hetay ialogueday."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Scapeeay uotesqay anday otheray pecialsay aracterschay."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Xtracteay allay anslatabletray ringsstay, otnay ustjay ialogueday."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Enray'Ypay isay extractingay ialogueday...."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Enray'Ypay ashay inishedfay extractingay ialogueday. Hetay extracteday ialogueday ancay ebay oundfay inay ialogueday.[persistent.dialogue_format] inay hetay asebay irectoryday."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Electsay Pdateuay Hannelcay"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Hetay updateay annelchay ontrolscay hetay ersionvay ofay Enray'Ypay hetay updateray illway ownloadday. Leasepay electsay anay updateay annelchay:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Eleaseray"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Ecommendedray.{/b} Hetay ersionvay ofay Enray'Ypay hattay ouldshay ebay useday inay allay ewlynay-eleasedray amesgay."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Rereleasepay"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Aay reviewpay ofay hetay extnay ersionvay ofay Enray'Ypay hattay ancay ebay useday orfay estingtay anday akingtay advantageay ofay ewnay eaturesfay, utbay otnay orfay inalfay eleasesray ofay amesgay."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Xperimentaleay"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Xperimentaleay ersionsvay ofay Enray'Ypay. Ouyay ouldnshay'tay electsay histay annelchay unlessay askeday ybay aay Enray'Ypay eveloperday."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Ightlynay"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Hetay eedingblay edgeay ofay Enray'Ypay evelopmentday. Histay aymay avehay hetay atestlay eaturesfay, oray ightmay otnay unray atay allay."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Naay erroray ashay occureday:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Heckingcay orfay updatesay."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Enray'Ypay isay upay otay ateday."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] isay ownay availableay. Oday ouyay antway otay installay itay?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Reparingpay otay ownloadday hetay updateay."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Ownloadingday hetay updateay."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Npackinguay hetay updateay."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Inishingfay upay."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Hetay updateay ashay eenbay installeday. Enray'Ypay illway estartray."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Hetay updateay ashay eenbay installeday."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Hetay updateay asway ancelledcay."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Enray'Ypay Pdateuay"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Roceedpay"
+
+
+translate piglatin strings:
+
+    # choose_directory.rpy:104
+    old "The selected projects directory is not writable."
+    new "Hetay electedsay rojectspay irectoryday isay otnay ritableway."
+
+    # distribute.rpy:1061
+    old "Signing the Macintosh application...\n(This may take a long time.)"
+    new "Igningsay hetay Acintoshmay applicationay...\n(Histay aymay aketay aay onglay imetay.)"
+
+    # front_page.rpy:91
+    old "PROJECTS:"
+    new "Rojectspay:"
+
diff --git a/launcher/game/tl/piglatin/obsolete.rpy b/launcher/game/tl/piglatin/obsolete.rpy
new file mode 100644
index 0000000..5f4d6f1
--- /dev/null
+++ b/launcher/game/tl/piglatin/obsolete.rpy
@@ -0,0 +1,26 @@
+translate piglatin strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Oystickjay Appingmay"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Mptyeay Lotsay."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "aay"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "qay"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Reviouspay"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Extnay"
+
diff --git a/launcher/game/tl/piglatin/options.rpy b/launcher/game/tl/piglatin/options.rpy
new file mode 100644
index 0000000..2eb533c
--- /dev/null
+++ b/launcher/game/tl/piglatin/options.rpy
@@ -0,0 +1,194 @@
+translate piglatin strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## Histay ilefay ontainscay optionsay hattay ancay ebay angedchay otay ustomizecay ouryay amegay."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Ineslay eginningbay ithway wotay '#' arksmay areay ommentscay, anday ouyay ouldnshay'tay uncommentay hemtay. Ineslay eginningbay ithway aay inglesay '#' arkmay areay ommentedcay-outay odecay, anday ouyay aymay antway otay uncommentay hemtay henway appropriateay."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Asicsbay"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## Aay umanhay-eadableray amenay ofay hetay amegay. Histay isay useday otay etsay hetay efaultday indowway itletay, anday owsshay upay inay hetay interfaceay anday erroray eportsray."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## Hetay _ay() urroundingsay hetay ringstay arksmay itay asay eligibleay orfay anslationtray."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Enray'Ypay 7ay Efaultday Uigay"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Eterminesday ifay hetay itletay ivengay aboveay isay ownshay onay hetay ainmay enumay creensay. Etsay histay otay Alsefay otay idehay hetay itletay."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## Hetay ersionvay ofay hetay amegay."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Exttay hattay isay acedplay onay hetay amegay'say aboutay creensay. Otay insertay aay ankblay inelay etweenbay aragraphspay, riteway \\nay\\nay."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## Aay ortshay amenay orfay hetay amegay useday orfay executablesay anday irectoriesday inay hetay uiltbay istributionday. Histay ustmay ebay Sciiaay-onlyay, anday ustmay otnay ontaincay pacessay, olonscay, oray emicolonssay."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Oundssay anday usicmay"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## Hesetay hreetay ariablesvay ontrolcay hichway ixersmay areay ownshay otay hetay ayerplay ybay efaultday. Ettingsay oneay ofay hesetay otay Alsefay illway idehay hetay appropriateay ixermay."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## Otay alloway hetay useray otay ayplay aay esttay oundsay onay hetay oundsay oray oicevay annelchay, uncommentay aay inelay elowbay anday useay itay otay etsay aay amplesay oundsay otay ayplay."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Ncommentuay hetay ollowingfay inelay otay etsay anay audioay ilefay hattay illway ebay ayedplay hileway hetay ayerplay isay atay hetay ainmay enumay. Histay ilefay illway ontinuecay ayingplay intoay hetay amegay, untilay itay isay oppedstay oray anotheray ilefay isay ayedplay."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Ransitionstay"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## Hesetay ariablesvay etsay ansitionstray hattay areay useday henway ertaincay eventsay occuray. Acheay ariablevay ouldshay ebay etsay otay aay ansitiontray, oray Onenay otay indicateay hattay onay ansitiontray ouldshay ebay useday."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Nteringeay oray exitingay hetay amegay enumay."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## Aay ansitiontray hattay isay useday afteray aay amegay ashay eenbay oadedlay."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Seduay henway enteringay hetay ainmay enumay afteray hetay amegay ashay endeday."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## Aay ariablevay otay etsay hetay ansitiontray useday henway hetay amegay artsstay oesday otnay existay. Nsteadiay, useay aay ithway atementstay afteray owingshay hetay initialay cenesay."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Indowway anagementmay"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## Histay ontrolscay henway hetay ialogueday indowway isay isplayedday. Fiay \"owshay\", itay isay alwaysay isplayedday. Fiay \"idehay\", itay isay onlyay isplayedday henway ialogueday isay resentpay. Fiay \"autoay\", hetay indowway isay iddenhay eforebay cenesay atementsstay anday ownshay againay onceay ialogueday isay isplayedday."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## Fteraay hetay amegay ashay artedstay, histay ancay ebay angedchay ithway hetay \"indowway owshay\", \"indowway idehay\", anday \"indowway autoay\" atementsstay."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Ransitionstay useday otay owshay anday idehay hetay ialogueday indowway"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Referencepay efaultsday"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Ontrolscay hetay efaultday exttay peedsay. Hetay efaultday, 0ay, isay infiniteay, hileway anyay otheray umbernay isay hetay umbernay ofay aracterschay erpay econdsay otay ypetay outay."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## Hetay efaultday autoay-orwardfay elayday. Argerlay umbersnay eadlay otay ongerlay aitsway, ithway 0ay otay 03ay eingbay hetay alidvay angeray."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Avesay irectoryday"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Ontrolscay hetay atformplay-pecificsay aceplay Enray'Ypay illway aceplay hetay avesay ilesfay orfay histay amegay. Hetay avesay ilesfay illway ebay acedplay inay:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Indowsway: %Ppdataaay\\Enpyray\\<onfigcay.ave_directorysay>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Acintoshmay: $Omehay/Ibrarylay/Enpyray/<onfigcay.ave_directorysay>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Inuxlay: $Omehay/.enpyray/<onfigcay.ave_directorysay>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## Histay enerallygay ouldshay otnay ebay angedchay, anday ifay itay isay, ouldshay alwaysay ebay aay iterallay ringstay, otnay anay expressionay."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Coniay ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## Hetay iconay isplayedday onay hetay askbartay oray ockday."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Uildbay onfigurationcay"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## Histay ectionsay ontrolscay owhay Enray'Ypay urnstay ouryay rojectpay intoay istributionday ilesfay."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## Hetay ollowingfay unctionsfay aketay ilefay atternspay. Ilefay atternspay areay asecay- insensitiveay, anday atchedmay againstay hetay athpay elativeray otay hetay asebay irectoryday, ithway anday ithoutway aay eadinglay /. Fiay ultiplemay atternspay atchmay, hetay irstfay isay useday."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## Niay aay atternpay:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / isay hetay irectoryday eparatorsay."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * atchesmay allay aracterschay, exceptay hetay irectoryday eparatorsay."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** atchesmay allay aracterschay, includingay hetay irectoryday eparatorsay."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## Orfay exampleay, \"*.xttay\" atchesmay xttay ilesfay inay hetay asebay irectoryday, \"amegay/**.oggay\" atchesmay oggay ilesfay inay hetay amegay irectoryday oray anyay ofay itsay ubdirectoriessay, anday \"**.sdpay\" atchesmay sdpay ilesfay anywhereay inay hetay rojectpay."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Lassifycay ilesfay asay Onenay otay excludeay hemtay omfray hetay uiltbay istributionsday."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## Otay archiveay ilesfay, assifyclay hemtay asay 'archiveay'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Ilesfay atchingmay ocumentationday atternspay areay uplicatedday inay aay acmay appay uildbay, osay heytay appearay inay othbay hetay appay anday hetay ipzay ilefay."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## Aay Ooglegay Laypay icenselay eykay isay equiredray otay ownloadday expansionay ilesfay anday erformpay inay-appay urchasespay. Tiay ancay ebay oundfay onay hetay \"Ervicessay & Pisaay\" agepay ofay hetay Ooglegay Laypay eveloperday onsolecay."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## Hetay usernameay anday rojectpay amenay associateday ithway anay itchay.ioay rojectpay, eparatedsay ybay aay ashslay."
+
diff --git a/launcher/game/tl/piglatin/screens.rpy b/launcher/game/tl/piglatin/screens.rpy
new file mode 100644
index 0000000..3934e63
--- /dev/null
+++ b/launcher/game/tl/piglatin/screens.rpy
@@ -0,0 +1,673 @@
+translate piglatin strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Tylessay"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## Niay-amegay creenssay"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Aysay creensay"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## Hetay aysay creensay isay useday otay isplayday ialogueday otay hetay ayerplay. Tiay akestay wotay arameterspay, howay anday hatway, hichway areay hetay amenay ofay hetay peakingsay aracterchay anday hetay exttay otay ebay isplayedday, espectivelyray. (Hetay howay arameterpay ancay ebay Onenay ifay onay amenay isay ivengay.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## Histay creensay ustmay reatecay aay exttay isplayableday ithway iday \"hatway\", asay Enray'Ypay usesay histay otay anagemay exttay isplayday. Tiay ancay alsoay reatecay isplayablesday ithway iday \"howay\" anday iday \"indowway\" otay applyay ylestay ropertiespay."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#aysay"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Nputiay creensay"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## Histay creensay isay useday otay isplayday enpyray.inputay. Hetay romptpay arameterpay isay useday otay asspay aay exttay romptpay inay."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## Histay creensay ustmay reatecay anay inputay isplayableday ithway iday \"inputay\" otay acceptay hetay ariousvay inputay arameterspay."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## ttphay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#inputay"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Hoicecay creensay"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## Histay creensay isay useday otay isplayday hetay inay-amegay oiceschay resentedpay ybay hetay enumay atementstay. Hetay oneay arameterpay, itemsay, isay aay istlay ofay objectsay, eachay ithway aptioncay anday actionay ieldsfay."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## ttphay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#oicechay"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## Henway histay isay uetray, enumay aptionscay illway ebay pokensay ybay hetay arratornay. Henway alsefay, enumay aptionscay illway ebay isplayedday asay emptyay uttonsbay."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Uickqay Enumay creensay"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## Hetay uickqay enumay isay isplayedday inay-amegay otay rovidepay easyay accessay otay hetay outay-ofay-amegay enusmay."
+
+    # screens.rpy:261
+    old "Back"
+    new "Ackbay"
+
+    # screens.rpy:262
+    old "History"
+    new "Istoryhay"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Kipsay"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Utoaay"
+
+    # screens.rpy:265
+    old "Save"
+    new "Avesay"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Qay.Avesay"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Qay.Oadlay"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Refspay"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## Histay odecay ensuresay hattay hetay uick_menuqay creensay isay isplayedday inay-amegay, heneverway hetay ayerplay ashay otnay explicitlyay iddenhay hetay interfaceay."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Avigationnay creensay"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## Histay creensay isay includeday inay hetay ainmay anday amegay enusmay, anday rovidespay avigationnay otay otheray enusmay, anday otay artstay hetay amegay."
+
+    # screens.rpy:308
+    old "Start"
+    new "Tartsay"
+
+    # screens.rpy:316
+    old "Load"
+    new "Oadlay"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Referencespay"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "Ndeay Eplayray"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Ainmay Enumay"
+
+    # screens.rpy:328
+    old "About"
+    new "Boutaay"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Elphay isnay'tay ecessarynay oray elevantray otay obilemay evicesday."
+
+    # screens.rpy:333
+    old "Help"
+    new "Elphay"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## Hetay uitqay uttonbay isay annedbay onay iOSay anday unnecessaryay onay Ndroidaay."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Uitqay"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Ainmay Enumay creensay"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Seduay otay isplayday hetay ainmay enumay henway Enray'Ypay artsstay."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## ttphay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#ainmay-enumay"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## Hetay useay atementstay includesay anotheray creensay insideay histay oneay. Hetay actualay ontentscay ofay hetay ainmay enumay areay inay hetay avigationnay creensay."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Amegay Enumay creensay"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## Histay ayslay outay hetay asicbay ommoncay ructurestay ofay aay amegay enumay creensay. Tiay'say alledcay ithway hetay creensay itletay, anday isplaysday hetay ackgroundbay, itletay, anday avigationnay."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## Hetay crollsay arameterpay ancay ebay Onenay, oray oneay ofay \"iewportvay\" oray \"pgridvay\". Henway histay creensay isay intendeday otay ebay useday ithway oneay oray oremay ildrenchay, hichway areay anscludedtray (acedplay) insideay itay."
+
+    # screens.rpy:476
+    old "Return"
+    new "Eturnray"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## Boutaay creensay"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## Histay creensay ivesgay reditcay anday opyrightcay informationay aboutay hetay amegay anday Enray'Ypay."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## Heretay'say othingnay pecialsay aboutay histay creensay, anday encehay itay alsoay ervessay asay anay exampleay ofay owhay otay akemay aay ustomcay creensay."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## Histay useay atementstay includesay hetay ame_menugay creensay insideay histay oneay. Hetay boxvay ildchay isay hentay includeday insideay hetay iewportvay insideay hetay ame_menugay creensay."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Ersionvay [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## uigay.aboutay isay usuallyay etsay inay optionsay.pyray."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Ademay ithway {a=https://www.renpy.org/}Enray'Ypay{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## Histay isay edefinedray inay optionsay.pyray otay adday exttay otay hetay aboutay creensay."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Oadlay anday Avesay creenssay"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## Hesetay creenssay areay esponsibleray orfay ettinglay hetay ayerplay avesay hetay amegay anday oadlay itay againay. Incesay heytay areshay earlynay everythingay inay ommoncay, othbay areay implementeday inay ermstay ofay aay hirdtay creensay, ile_slotsfay."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#avesay ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#oadlay"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Agepay {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Utomaticaay avessay"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Uickqay avessay"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## Histay ensuresay hetay inputay illway etgay hetay enteray eventay eforebay anyay ofay hetay uttonsbay oday."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## Hetay idgray ofay ilefay otsslay."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%Aay, %Bay %day %Yay, %Hay:%May"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "emptyay otslay"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Uttonsbay otay accessay otheray agespay."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}Aay"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Qay"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Referencespay creensay"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## Hetay referencespay creensay allowsay hetay ayerplay otay onfigurecay hetay amegay otay etterbay uitsay hemselvestay."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#referencespay"
+
+    # screens.rpy:738
+    old "Display"
+    new "Isplayday"
+
+    # screens.rpy:739
+    old "Window"
+    new "Indowway"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Ullscreenfay"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Ollbackray Idesay"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Isableday"
+
+    # screens.rpy:746
+    old "Left"
+    new "Eftlay"
+
+    # screens.rpy:747
+    old "Right"
+    new "Ightray"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Nseenuay Exttay"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Fteraay Hoicescay"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Ransitionstay"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Dditionalaay boxesvay ofay ypetay \"adio_prefray\" oray \"eck_prefchay\" ancay ebay addeday erehay, otay adday additionalay reatorcay-efinedday referencespay."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Exttay Peedsay"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Utoaay-Orwardfay Imetay"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Usicmay Olumevay"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Oundsay Olumevay"
+
+    # screens.rpy:791
+    old "Test"
+    new "Esttay"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Oicevay Olumevay"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Utemay Llaay"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## Istoryhay creensay"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## Histay isay aay creensay hattay isplaysday hetay ialogueday istoryhay otay hetay ayerplay. Hileway heretay isnay'tay anythingay pecialsay aboutay histay creensay, itay oesday avehay otay accessay hetay ialogueday istoryhay oredstay inay history_list_ay."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/istoryhay.tmlhay"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Voidaay redictingpay histay creensay, asay itay ancay ebay eryvay argelay."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## Histay ayslay hingstay outay roperlypay ifay istory_heighthay isay Onenay."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Aketay hetay olorcay ofay hetay howay exttay omfray hetay Haractercay, ifay etsay."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "Hetay ialogueday istoryhay isay emptyay."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Elphay creensay"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## Aay creensay hattay ivesgay informationay aboutay eykay anday ousemay indingsbay. Tiay usesay otheray creenssay (eyboard_helpkay, ouse_helpmay, anday amepad_helpgay) otay isplayday hetay actualay elphay."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Eyboardkay"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Ousemay"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Amepadgay"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Ntereay"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Dvancesaay ialogueday anday activatesay hetay interfaceay."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Pacesay"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Dvancesaay ialogueday ithoutway electingsay oiceschay."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Rrowaay Eyskay"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Avigatenay hetay interfaceay."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Scapeeay"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Ccessesaay hetay amegay enumay."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Trlcay"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Kipssay ialogueday hileway eldhay ownday."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Abtay"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Ogglestay ialogueday kippingsay."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Agepay Puay"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Ollsray ackbay otay earlieray ialogueday."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Agepay Ownday"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Ollsray orwardfay otay aterlay ialogueday."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Ideshay hetay useray interfaceay."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Akestay aay creenshotsay."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Ogglestay assistiveay {a=https://www.renpy.org/l/voicing}elfsay-oicingvay{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Eftlay Lickcay"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Iddlemay Lickcay"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Ightray Lickcay"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Ousemay Heelway Puay\nLickcay Ollbackray Idesay"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Ousemay Heelway Ownday"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Ightray Riggertay\nAay/Ottombay Uttonbay"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Dvanceaay ialogueday anday activatesay hetay interfaceay."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Ollray ackbay otay earlieray ialogueday."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Ightray Houldersay"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Ollray orwardfay otay aterlay ialogueday."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "Day-Adpay, Tickssay"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Tartsay, Uidegay"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Ccessaay hetay amegay enumay."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Yay/Optay Uttonbay"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Alibratecay"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Dditionalaay creenssay"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Onfirmcay creensay"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## Hetay onfirmcay creensay isay alledcay henway Enray'Ypay antsway otay askay hetay ayerplay aay esyay oray onay uestionqay."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## ttphay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#onfirmcay"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Nsureeay otheray creenssay oday otnay etgay inputay hileway histay creensay isay isplayedday."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Esyay"
+
+    # screens.rpy:1162
+    old "No"
+    new "Onay"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Ightray-ickclay anday escapeay answeray \"onay\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Kipsay indicatoray creensay"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## Hetay kip_indicatorsay creensay isay isplayedday otay indicateay hattay kippingsay isay inay rogresspay."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#kipsay-indicatoray"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Kippingsay"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## Histay ansformtray isay useday otay inkblay hetay arrowsay oneay afteray anotheray."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Otifynay creensay"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## Hetay otifynay creensay isay useday otay owshay hetay ayerplay aay essagemay. (Orfay exampleay, henway hetay amegay isay uicksavedqay oray aay creenshotsay ashay eenbay akentay.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## ttpshay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#otifynay-creensay"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## Vlnay creensay"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## Histay creensay isay useday orfay Vlnay-odemay ialogueday anday enusmay."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## ttphay://wwway.enpyray.orgay/ocday/tmlhay/creen_specialsay.tmlhay#vlnay"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Isplaysday ialogueday inay eitheray aay pgridvay oray hetay boxvay."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Isplaysday hetay enumay, ifay ivengay. Hetay enumay aymay ebay isplayedday incorrectlyay ifay onfigcay.arrator_menunay isay etsay otay Ruetay, asay itay isay aboveay."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## Histay ontrolscay hetay aximummay umbernay ofay Vlnay-odemay entriesay hattay ancay ebay isplayedday atay onceay."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Obilemay Ariantsvay"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Incesay aay ousemay aymay otnay ebay resentpay, eway eplaceray hetay uickqay enumay ithway aay ersionvay hattay usesay ewerfay anday iggerbay uttonsbay hattay areay easieray otay ouchtay."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Enumay"
+
+
+translate piglatin strings:
+
+    # screens.rpy:119
+    old "## If there's a side image, display it above the text. Do not display on the phone variant - there's no room."
+    new "## Fiay heretay'say aay idesay imageay, isplayday itay aboveay hetay exttay. Oday otnay isplayday onay hetay onephay ariantvay - heretay'say onay oomray."
+
+    # screens.rpy:251
+    old "## Ensure this appears on top of other screens."
+    new "## Nsureeay histay appearsay onay optay ofay otheray creenssay."
+
+    # screens.rpy:360
+    old "## This ensures that any other menu screen is replaced."
+    new "## Histay ensuresay hattay anyay otheray enumay creensay isay eplacedray."
+
+    # screens.rpy:367
+    old "## This empty frame darkens the main menu."
+    new "## Histay emptyay amefray arkensday hetay ainmay enumay."
+
+    # screens.rpy:438
+    old "## Reserve space for the navigation section."
+    new "## Eserveray pacesay orfay hetay avigationnay ectionsay."
+
+    # screens.rpy:618
+    old "## The page name, which can be edited by clicking on a button."
+    new "## Hetay agepay amenay, hichway ancay ebay editeday ybay ickingclay onay aay uttonbay."
+
+    # screens.rpy:673
+    old "## range(1, 10) gives the numbers from 1 to 9."
+    new "## angeray(1ay, 01ay) ivesgay hetay umbersnay omfray 1ay otay 9ay."
+
diff --git a/launcher/game/tl/piglatin/script.rpym b/launcher/game/tl/piglatin/script.rpym
new file mode 100644
index 0000000..df6acf2
--- /dev/null
+++ b/launcher/game/tl/piglatin/script.rpym
@@ -0,0 +1,33 @@
+# Eclareday aracterschay useday ybay histay amegay. Hetay olorcay argumentay olorizescay hetay
+# amenay ofay hetay aracterchay.
+
+define e = Character("Ileeneay")
+
+
+# Hetay amegay artsstay erehay.
+
+label start:
+
+    # Howsay aay ackgroundbay. Histay usesay aay aceholderplay ybay efaultday, utbay ouyay ancay
+    # adday aay ilefay (amednay eitheray "bg oomray.png" oray "bg oomray.jpg") otay hetay
+    # imagesay irectoryday otay owshay itay.
+
+    scene bg oomray
+
+    # Histay owsshay aay aracterchay pritesay. Aay aceholderplay isay useday, utbay ouyay ancay
+    # eplaceray itay ybay addingay aay ilefay amednay "eileenay appyhay.png" otay hetay imagesay
+    # irectoryday.
+
+    show eileenay appyhay
+
+    # Hesetay isplayday ineslay ofay ialogueday.
+
+    "Ellohay, orldway."
+
+    e "Ouyay'evay reatedcay aay ewnay Enray'Ypay amegay."
+
+    e "Nceoay ouyay adday aay orystay, icturespay, anday usicmay, ouyay ancay eleaseray itay otay hetay orldway!"
+
+    # Histay endsay hetay amegay.
+
+    return
diff --git a/launcher/game/tl/piglatin/style.rpy b/launcher/game/tl/piglatin/style.rpy
new file mode 100644
index 0000000..c8b0133
--- /dev/null
+++ b/launcher/game/tl/piglatin/style.rpy
@@ -0,0 +1,5 @@
+init python:
+    translate_font("piglatin", "DroidSansFallback.ttf")
+
+translate piglatin python:
+    gui.FONT_SCALE = .9
diff --git a/launcher/game/tl/russian/about.rpy b/launcher/game/tl/russian/about.rpy
deleted file mode 100644
index e02abfc..0000000
--- a/launcher/game/tl/russian/about.rpy
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/launcher/game/tl/russian/add_file.rpy b/launcher/game/tl/russian/add_file.rpy
deleted file mode 100644
index fe40125..0000000
--- a/launcher/game/tl/russian/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate russian strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "ИМЯ ФАЙЛА"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Введите имя файла сценария, который вы хотите создать."
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "Имя должно иметь расширение .rpy."
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "Файл уже существует."
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py автоматически загружает все файлы сценариев, заканчивающиеся на .rpy\n#Чтобы использовать этот файл, определите метку и прыгните (jump) к ней из другого файла.\n"
-
diff --git a/launcher/game/tl/russian/android.rpy b/launcher/game/tl/russian/android.rpy
deleted file mode 100644
index db08684..0000000
--- a/launcher/game/tl/russian/android.rpy
+++ /dev/null
@@ -1,103 +0,0 @@
-
-translate russian strings:
-
-    # game/android.rpy:13
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "32-разрядный инструментарий разработки Java требуется, чтобы построить Android-пакеты на Windows. JDK отличен от JRE, и возможно, у вас есть Java без JDK.\n\nПожалуйста, {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}загрузите и установите JDK{/a}, и перезапустите Ren'Py Launcher."
-
-    # game/android.rpy:14
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Чтобы строить Android-пакеты, пожалуйста, загрузите RAPT ({a=http://www.renpy.org/dl/android}отсюда{/a}), распакуйте его, и поместите его в папку Ren'Py. После этого, перезапустите Ren'Py Launcher."
-
-    # game/android.rpy:15
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT установлен, но вам понадобится установить Android SDK до того, как вы сможете создавать Android-пакеты. Выберите Установить SDK, чтобы сделать это."
-
-    # game/android.rpy:16
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT установлен, но отсутствует ключ. Пожалуйста, создайте новый ключ, или восстановите android.keystore."
-
-    # game/android.rpy:17
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Текущий проект не настроен. Используйте \"Настроить\", чтобы настроить его перед сборкой."
-
-    # game/android.rpy:18
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Выберите \"Построить\", чтобы собрать текущий проект, или присоедините Android-устройство и выберите \"Построить и Установить\", чтобы собрать и установить его на устройстве."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Пытается эмулировать Android-телефон.\n\nПрикосновения иммитируются мышью при зажатой кнопке. Escape назначен на кнопку меню, а PageUp - на кнопку назад."
-
-    # game/android.rpy:21
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Пытается эмулировать Android-планшет.\n\nПрикосновения иммитируются мышью при зажатой кнопке. Escape назначен на кнопку меню, а PageUp - на кнопку назад."
-
-    # game/android.rpy:22
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Пытается эмулировать приставку OUYA.\n\nВвод контроллера назначен на клавиши со стрелками, Enter - на кнопку Select, Escape - на кнопку меню, а PageUp - на кнопку назад."
-
-    # game/android.rpy:24
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Скачивает и устанавливает Android SDK и поддерживающие пакеты. При желании, создает ключи для подписи пакета."
-
-    # game/android.rpy:25
-    old "Configures the package name, version, and other information about this project."
-    new "Настраивает имя пакета, версию, и другую информацию о проекте."
-
-    # game/android.rpy:26
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Открывает файл, содержащий ключи Google Play в редакторе.\n\nЭто необходимо лишь для случаев, если приложение использует расширяющий APK. Прочтите документацию для больших деталей."
-
-    # game/android.rpy:27
-    old "Builds the Android package."
-    new "Собирает Android-пакет."
-
-    # game/android.rpy:28
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Собирает Android-пакет, устанавливает его на Android-устройстве, подключенном к компьютеру."
-
-    # game/android.rpy:148
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:371
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:391
-    old "Emulation:"
-    new "Эмуляция:"
-
-    # game/android.rpy:399
-    old "Phone"
-    new "Телефон"
-
-    # game/android.rpy:403
-    old "Tablet"
-    new "Планшет"
-
-    # game/android.rpy:407
-    old "Television / OUYA"
-    new "Телевидение / OUYA"
-
-    # game/android.rpy:419
-    old "Build:"
-    new "Собрать:"
-
-    # game/android.rpy:427
-    old "Install SDK & Create Keys"
-    new "Установить SDK и создать ключи"
-
-    # game/android.rpy:431
-    old "Configure"
-    new "Настроить"
-
-    # game/android.rpy:435
-    old "Build Package"
-    new "Собрать пакет"
-
-    # game/android.rpy:439
-    old "Build & Install"
-    new "Собрать и установить"
-
diff --git a/launcher/game/tl/russian/choose_theme.rpy b/launcher/game/tl/russian/choose_theme.rpy
deleted file mode 100644
index d5021c6..0000000
--- a/launcher/game/tl/russian/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate russian strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Невозможно изменить тему. Возможно, options.rpy был сильно изменен."
-
-    # game/choose_theme.rpy:339
-    old "Display"
-    new "Экран"
-
-    # game/choose_theme.rpy:340
-    old "Window"
-    new "Окно"
-
-    # game/choose_theme.rpy:341
-    old "Fullscreen"
-    new "Полный экран"
-
-    # game/choose_theme.rpy:342
-    old "Planetarium"
-    new "Планетарий"
-
-    # game/choose_theme.rpy:349
-    old "Sound Volume"
-    new "Громкость звука"
-
-    # game/choose_theme.rpy:383
-    old "Choose Theme"
-    new "Выберите тему"
-
-    # game/choose_theme.rpy:396
-    old "Theme"
-    new "Тема"
-
-    # game/choose_theme.rpy:420
-    old "Color Scheme"
-    new "Цветовая схема"
-
-    # game/choose_theme.rpy:451
-    old "Continue"
-    new "Продолжить"
-
diff --git a/launcher/game/tl/russian/common.rpy b/launcher/game/tl/russian/common.rpy
index ec01c43..7ec6e95 100644
--- a/launcher/game/tl/russian/common.rpy
+++ b/launcher/game/tl/russian/common.rpy
@@ -1,313 +1,335 @@
 
 translate russian strings:
 
-    # renpy/common/_layout/classic_load_save.rpym:120
-    old "Empty Slot."
-    new "Пустой слот."
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-translate russian strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/_layout/classic_joystick_preferences.rpym:76
-    old "Joystick Mapping"
-    new "Назначение джойстика"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-translate russian strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
+
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
+
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
+
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
+
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
+
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
+
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
+
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-    # renpy/common/00action_file.rpy:124
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
+
+    # 00action_file.rpy:235
     old "%b %d, %H:%M"
     new "%b %d, %H:%M"
 
-    # renpy/common/00action_file.rpy:587
+    # 00action_file.rpy:820
     old "Quick save complete."
     new "Быстрое сохранение завершено."
 
-
-translate russian strings:
-
-    # renpy/common/00layout.rpy:421
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Вы уверены?"
 
-    # renpy/common/00layout.rpy:422
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Вы уверены, что хотите удалить это сохранение?"
 
-    # renpy/common/00layout.rpy:423
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Вы уверены, что хотите перезаписать ваше сохранение?"
 
-    # renpy/common/00layout.rpy:424
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Загрузка игры приведет к потере несохраненного прогресса.\nВы уверены, что вы хотите это сделать?"
 
-    # renpy/common/00layout.rpy:425
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Вы уверены, что вы хотите выйти?"
 
-    # renpy/common/00layout.rpy:426
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Вы уверены, что вы хотите вернуться в главное меню?\nЭто приведет к потере несохраненного прогресса."
 
-    # renpy/common/00layout.rpy:427
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Вы уверены, что хотите начать пропуск?"
 
-    # renpy/common/00layout.rpy:428
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Вы хотите пропустить все до следующего выбора?"
 
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Вы уверены, что хотите пропустить все до невиданного диалога или следующего выбора?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Скришнот сохранен как %s."
 
-translate russian strings:
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Предыдущий"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Следующий"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Режим Пропуска"
 
-translate russian strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00keymap.rpy:168
-    old "Saved screenshot as %s."
-    new "Скришнот сохранен как %s."
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Clipboard voicing enabled. Press 'shift+C' to disable."
 
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
 
-translate russian strings:
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Self-voicing enabled. Press 'v' to disable."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
+
+    # 00updater.rpy:367
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "The Ren'Py Updater is not supported on mobile devices."
+
+    # 00updater.rpy:486
+    old "An error is being simulated."
+    new "An error is being simulated."
+
+    # 00updater.rpy:662
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Either this project does not support updating, or the update status file was deleted."
+
+    # 00updater.rpy:676
+    old "This account does not have permission to perform an update."
+    new "This account does not have permission to perform an update."
+
+    # 00updater.rpy:679
+    old "This account does not have permission to write the update log."
+    new "This account does not have permission to write the update log."
+
+    # 00updater.rpy:704
+    old "Could not verify update signature."
+    new "Could not verify update signature."
+
+    # 00updater.rpy:975
+    old "The update file was not downloaded."
+    new "The update file was not downloaded."
+
+    # 00updater.rpy:993
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "The update file does not have the correct digest - it may have been corrupted."
 
-    # renpy/common/00updater.rpy:1258
+    # 00updater.rpy:1049
+    old "While unpacking {}, unknown type {}."
+    new "While unpacking {}, unknown type {}."
+
+    # 00updater.rpy:1393
     old "Updater"
     new "Обновление"
 
-    # renpy/common/00updater.rpy:1267
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Это программа обновлена."
 
-    # renpy/common/00updater.rpy:1269
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] доступна. Вы хотите её установить?"
 
-    # renpy/common/00updater.rpy:1271
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Подготовка к загрузке обновлений."
 
-    # renpy/common/00updater.rpy:1273
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Загрузка обновлений."
 
-    # renpy/common/00updater.rpy:1275
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Распаковка обновлений."
 
-    # renpy/common/00updater.rpy:1279
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "Обновления установлены. Программа будет перезапущена."
 
-    # renpy/common/00updater.rpy:1281
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "Обновления были установлены."
 
-    # renpy/common/00updater.rpy:1283
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "Обновления были отменены."
 
-
-translate russian strings:
-
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Графическое Ускорение"
-
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Выбирать Автоматически"
-
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Насильно Отображать Через Angle/DirectX"
-
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "Насильно Отображать Через OpenGL"
-
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Насильно Отображать Програмно"
-
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Изменения вступят в силу при следующем запуске программы."
-
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "Выйти"
-
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Вернуться"
-
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Предупреждение о Производительности"
-
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Этот компьютер использует програмный рендеринг."
-
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Этот компьютер не использует шейдеры."
-
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Этот компьютер медленно отображает графику."
-
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "У этого компьютера проблема с отображением графики: [problem]"
-
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Графические драйвера устарели или работают неверно. Это может привести к медленному или неверному отображению графики. Обновление DirectX может решить эту проблему."
-
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Графические драйвера устарели или работают неверно. Это может привести к медленному или неверному отображению графики."
-
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "Обновить DirectX"
-
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Продолжить, Показать это предупреждение снова"
-
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Продолжить, Не показывать это предупреждение снова."
-
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "Обновляется DirectX."
-
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "Установщик DirectX был запущен. Вероятно, он запустился в свернутом состоянии. Пожалуйста, следуйте инструкциям для установки DirectX."
-
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Предупреждение:{/b} Установщик DirectX по умолчанию попытается установить панель инструментов Bing. Если вы этого не хотите, снимите соответствующую галочку."
-
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "По завершению установки, щелкните, чтобы перезапустить программу."
-
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Перезапустить"
-
-
-translate russian strings:
-
-    # renpy/common/00gallery.rpy:521
+    # 00gallery.rpy:563
     old "Image [index] of [count] locked."
     new "Изображение [index] из [count] заблокированных."
 
-    # renpy/common/00gallery.rpy:539
+    # 00gallery.rpy:583
     old "prev"
     new "пред"
 
-    # renpy/common/00gallery.rpy:540
+    # 00gallery.rpy:584
     old "next"
     new "след"
 
-    # renpy/common/00gallery.rpy:541
+    # 00gallery.rpy:585
     old "slideshow"
     new "слайдшоу"
 
-    # renpy/common/00gallery.rpy:542
+    # 00gallery.rpy:586
     old "return"
     new "вернуться"
 
-
-translate russian strings:
-
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "Возникло исключение."
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Вернуться назад"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Пытается вернуться назад, позволяя вам сохраниться или выбрать другой выбор."
-
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "Игнорировать"
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Игнорирует это исключение, позволяя вам продолжить. Это зачастую ведет к дополнительным ошибкам."
-
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "Перезагрузить"
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Перезагружает игру с диска, сохраняя и восстанавливая состояние, если это возможно."
-
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "Открыть Журнал"
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Открывает файл traceback.txt в текстовом редакторе."
-
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "Выходит из игры."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "Обработка сценария завершилась неудачно."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Открыть Ошибки Обработки"
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Открывает файл errors.txt в текстовом редакторе."
-
-
-translate russian strings:
-
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "Режим Пропуска"
-
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Режим Быстрого Пропуска"
-
diff --git a/launcher/game/tl/russian/developer.rpy b/launcher/game/tl/russian/developer.rpy
new file mode 100644
index 0000000..a7ac055
--- /dev/null
+++ b/launcher/game/tl/russian/developer.rpy
@@ -0,0 +1,179 @@
+
+translate russian strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Developer Menu"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Reload Game (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Console (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Variable Viewer"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Theme Test"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Image Location Picker"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Filename List"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Show Image Load Log"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Hide Image Load Log"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Nothing to inspect."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Return to the developer menu"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rectangle: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Mouse position: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Right-click or escape to quit."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectangle copied to clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Position copied to clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable Inspector"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Size"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Style"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Location"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Inspecting Styles of [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (no properties affect the displayable)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (default properties omitted)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Press <esc> to exit console. Type help for help.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren'Py script enabled."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren'Py script disabled."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: show this help"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "commands:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: run the statement\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: run the expression or statement"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: clear the console history"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: exit the console"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: loads the game from slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: saves the game in slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: reloads the game, refreshing the scripts"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: watch a python expression"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: stop watching an expression"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: stop watching all expressions"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: jumps to label"
+
diff --git a/launcher/game/tl/russian/distribute.rpy b/launcher/game/tl/russian/distribute.rpy
deleted file mode 100644
index 431a716..0000000
--- a/launcher/game/tl/russian/distribute.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate russian strings:
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Пакеты не выбраны. Делать нечего."
-
-    # game/distribute.rpy:363
-    old "Scanning project files..."
-    new "Сканирую файлы проекта..."
-
-    # game/distribute.rpy:373
-    old "Scanning Ren'Py files..."
-    new "Сканирую файлы Ren'Py..."
-
-    # game/distribute.rpy:421
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Все пакеты были построены.\n\nВ связи с наличием информации о правах доступа, не распаковывайте дистрибутивы для Linux и Macintosh на Windows."
-
-    # game/distribute.rpy:545
-    old "Archiving files..."
-    new "Архивирую файлы..."
-
-    # game/distribute.rpy:808
-    old "Writing the [variant] [format] package."
-    new "Пишу пакет [variant] [format]"
-
-    # game/distribute.rpy:821
-    old "Making the [variant] update zsync file."
-    new "Создаю файл zsync для обновления [variant]"
-
-    # game/distribute.rpy:917
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Обработано {b}[complete]{/b} из {b}[total]{/b} файлов."
-
diff --git a/launcher/game/tl/russian/distribute_gui.rpy b/launcher/game/tl/russian/distribute_gui.rpy
deleted file mode 100644
index b27afbc..0000000
--- a/launcher/game/tl/russian/distribute_gui.rpy
+++ /dev/null
@@ -1,51 +0,0 @@
-
-translate russian strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Сборка Дистрибутивов: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Имя Папки:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Имя исполняемого файла:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "Действия"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "Редактировать options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Обновить"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Построить пакеты:"
-
-    # game/distribute_gui.rpy:207
-    old "Build Updates"
-    new "Построить Обновления"
-
-    # game/distribute_gui.rpy:210
-    old "Back"
-    new "Назад"
-
-    # game/distribute_gui.rpy:211
-    old "Build"
-    new "Построить"
-
-    # game/distribute_gui.rpy:218
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "При запуске проекта произошли ошибки. Пожалуйста, убедитесь в том, что проект успешно запускается, перед созданием дистрибутивов."
-
-    # game/distribute_gui.rpy:235
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Ваш проект не содержит информацию, необходимую для сборки. Добавить её к концу options.rpy?"
-
diff --git a/launcher/game/tl/russian/editor.rpy b/launcher/game/tl/russian/editor.rpy
deleted file mode 100644
index 8a3d3e1..0000000
--- a/launcher/game/tl/russian/editor.rpy
+++ /dev/null
@@ -1,55 +0,0 @@
-
-translate russian strings:
-
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Рекомендуется.{/b} Beta-редактор с простым интерфейсом и возможностями, помогающими в разработке, такими, как проверка орфографии. Editra сейчас не поддерживает IME, необходимые для ввода Китайского, Японского и Корейского текстов."
-
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Рекомендуется.{/b} Beta-редактор с простым интерфейсом и возможностями, помогающими в разработке, такими, как проверка орфографии. Editra сейчас не поддерживает IME, необходимые для ввода Китайского, Японского и Корейского текстов. На Linux, Editra требует wxPython."
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Это могло случиться из-за того, что wxPython не установлен на этой системе."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Требуется скачать 22 МБ."
-
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Проверенный временем редактор. Требует Java."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "Требуется скачать 1.8 МБ."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Это могло случиться из-за того, что Java не установлена на данной системе."
-
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Включает текстовый редактор, ассоциированный на вашей системе с файлами .rpy."
-
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Не позволяет Ren'Py запускать текстовый редактор."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Возникла ошибка при запуске текстового редактора:\n[exception!q]"
-
-    # game/editor.rpy:423
-    old "Select Editor"
-    new "Выберите редактор"
-
-    # game/editor.rpy:438
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Текстовый редактор - программа, необходимая для редактирования сценариев Ren'Py. Здесь, вы можете выбрать редактор, который Ren'Py будет использовать. Если такового нет, редактор будет автоматически загружен и установлен."
-
-    # game/editor.rpy:460
-    old "Cancel"
-    new "Отмена"
-
diff --git a/launcher/game/tl/russian/error.rpy b/launcher/game/tl/russian/error.rpy
new file mode 100644
index 0000000..7f60f28
--- /dev/null
+++ b/launcher/game/tl/russian/error.rpy
@@ -0,0 +1,179 @@
+
+translate russian strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Графическое Ускорение"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Выбирать Автоматически"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Насильно Отображать Через Angle/DirectX"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Насильно Отображать Через OpenGL"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Насильно Отображать Програмно"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Изменения вступят в силу при следующем запуске программы."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Предупреждение о Производительности"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Этот компьютер использует програмный рендеринг."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Этот компьютер не использует шейдеры."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Этот компьютер медленно отображает графику."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "У этого компьютера проблема с отображением графики: [problem]"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Графические драйвера устарели или работают неверно. Это может привести к медленному или неверному отображению графики. Обновление DirectX может решить эту проблему."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Графические драйвера устарели или работают неверно. Это может привести к медленному или неверному отображению графики."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Обновить DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Продолжить, Показать это предупреждение снова"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Продолжить, Не показывать это предупреждение снова."
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Обновляется DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Установщик DirectX был запущен. Вероятно, он запустился в свернутом состоянии. Пожалуйста, следуйте инструкциям для установки DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Предупреждение:{/b} Установщик DirectX по умолчанию попытается установить панель инструментов Bing. Если вы этого не хотите, снимите соответствующую галочку."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "По завершению установки, щелкните, чтобы перезапустить программу."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Перезапустить"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Открыть Журнал"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Открывает файл traceback.txt в текстовом редакторе."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Возникло исключение."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Вернуться назад"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Пытается вернуться назад, позволяя вам сохраниться или выбрать другой выбор."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Игнорировать"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Игнорирует это исключение, позволяя вам продолжить. Это зачастую ведет к дополнительным ошибкам."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Перезагрузить"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Перезагружает игру с диска, сохраняя и восстанавливая состояние, если это возможно."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Выходит из игры."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Обработка сценария завершилась неудачно."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Открыть Ошибки Обработки"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Открывает файл errors.txt в текстовом редакторе."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/russian/front_page.rpy b/launcher/game/tl/russian/front_page.rpy
deleted file mode 100644
index f7a46b3..0000000
--- a/launcher/game/tl/russian/front_page.rpy
+++ /dev/null
@@ -1,110 +0,0 @@
-
-translate russian strings:
-
-    # game/front_page.rpy:67
-    old "refresh"
-    new "обновить"
-
-    # game/front_page.rpy:94
-    old "+ Create New Project"
-    new "+ Добавить новый проект"
-
-    # game/front_page.rpy:106
-    old "Launch Project"
-    new "Запустить проект"
-
-    # game/front_page.rpy:122
-    old "[p.name!q] (template)"
-    new "[p.name!q] (образец)"
-
-    # game/front_page.rpy:138
-    old "Tutorial"
-    new "Обучение"
-
-    # game/front_page.rpy:139
-    old "The Question"
-    new "Вопрос"
-
-    # game/front_page.rpy:155
-    old "Active Project"
-    new "Активный Проект"
-
-    # game/front_page.rpy:163
-    old "Open Directory"
-    new "Открыть Папку"
-
-    # game/front_page.rpy:168
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:169
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:175
-    old "Edit File"
-    new "Редактировать Файл"
-
-    # game/front_page.rpy:183
-    old "All script files"
-    new "Все файлы сценариев"
-
-    # game/front_page.rpy:192
-    old "Navigate Script"
-    new "Навигация по Сценарию"
-
-    # game/front_page.rpy:203
-    old "Check Script (Lint)"
-    new "Проверить Сценарий (Lint)"
-
-    # game/front_page.rpy:204
-    old "Change Theme"
-    new "Сменить тему"
-
-    # game/front_page.rpy:205
-    old "Delete Persistent"
-    new "Очистить постоянные данные"
-
-    # game/front_page.rpy:213
-    old "Build Distributions"
-    new "Построить дистрибутивы"
-
-    # game/front_page.rpy:215
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:216
-    old "Generate Translations"
-    new "Создать переводы"
-
-    # game/front_page.rpy:217
-    old "Extract Dialogue"
-    new "Извлечь диалог"
-
-    # game/front_page.rpy:233
-    old "Checking script for potential problems..."
-    new "Проверка потенциальных проблем сценария..."
-
-    # game/front_page.rpy:248
-    old "Deleting persistent data..."
-    new "Удаление постоянных данных..."
-
-
-translate russian strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Открыть папку [text]."
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "Выбрать проект [text]."
-
-    # game/front_page.rpy:234
-    old "Force Recompile"
-    new "Перекомпилировать проект"
-
-    # game/front_page.rpy:285
-    old "Recompiling all rpy files into rpyc files..."
-    new "Перекомпиляция всех файлов rpy в файлы rpyc..."
-
diff --git a/launcher/game/tl/russian/gui.rpy b/launcher/game/tl/russian/gui.rpy
new file mode 100644
index 0000000..bfd6d4e
--- /dev/null
+++ b/launcher/game/tl/russian/gui.rpy
@@ -0,0 +1,411 @@
+
+translate russian strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/russian/interface.rpy b/launcher/game/tl/russian/interface.rpy
deleted file mode 100644
index 909f2a1..0000000
--- a/launcher/game/tl/russian/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate russian strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Документация"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Сайт Ren'Py"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Список Игр Ren'Py"
-
-    # game/interface.rpy:92
-    old "About"
-    new "О"
-
-    # game/interface.rpy:99
-    old "update"
-    new "обновить"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "настройки"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "выйти"
-
-    # game/interface.rpy:174
-    old "Yes"
-    new "Да"
-
-    # game/interface.rpy:176
-    old "No"
-    new "Нет"
-
-    # game/interface.rpy:211
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "В связи с ограничениями на форматы пакетов, не-ASCII имена файлов и папок недопустимы."
-
-    # game/interface.rpy:303
-    old "ERROR"
-    new "ОШИБКА"
-
-    # game/interface.rpy:332
-    old "While [what!q], an error occured:"
-    new "Пока [what!q], возникла ошибка:"
-
-    # game/interface.rpy:333
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:351
-    old "Text input may not contain the {{ or [[ characters."
-    new "Текст не должен содержать знаки {{ или [[."
-
-    # game/interface.rpy:356
-    old "File and directory names may not contain / or \\."
-    new "Имена файлов и папок не должны содержать / или \\."
-
-    # game/interface.rpy:362
-    old "File and directory names must consist of ASCII characters."
-    new "Имена файлов и папок должны состоять из знаков ASCII."
-
-    # game/interface.rpy:383
-    old "INFORMATION"
-    new "ИНФОРМАЦИЯ"
-
-    # game/interface.rpy:426
-    old "PROCESSING"
-    new "ОБРАБОТКА"
-
-    # game/interface.rpy:443
-    old "QUESTION"
-    new "ВОПРОС"
-
-    # game/interface.rpy:456
-    old "CHOICE"
-    new "ВЫБОР"
-
diff --git a/launcher/game/tl/russian/launcher.rpy b/launcher/game/tl/russian/launcher.rpy
new file mode 100644
index 0000000..cbfaeef
--- /dev/null
+++ b/launcher/game/tl/russian/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate russian strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "View license"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "ИМЯ ФАЙЛА"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Введите имя файла сценария, который вы хотите создать."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Имя должно иметь расширение .rpy."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Файл уже существует."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py автоматически загружает все файлы сценариев, заканчивающиеся на .rpy\n#Чтобы использовать этот файл, определите метку и прыгните (jump) к ней из другого файла.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "32-разрядный инструментарий разработки Java требуется, чтобы построить Android-пакеты на Windows. JDK отличен от JRE, и возможно, у вас есть Java без JDK.\n\nПожалуйста, {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}загрузите и установите JDK{/a}, и перезапустите Ren'Py Launcher."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT установлен, но вам понадобится установить Android SDK до того, как вы сможете создавать Android-пакеты. Выберите Установить SDK, чтобы сделать это."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT установлен, но отсутствует ключ. Пожалуйста, создайте новый ключ, или восстановите android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Текущий проект не настроен. Используйте \"Настроить\", чтобы настроить его перед сборкой."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Выберите \"Построить\", чтобы собрать текущий проект, или присоедините Android-устройство и выберите \"Построить и Установить\", чтобы собрать и установить его на устройстве."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Пытается эмулировать Android-телефон.\n\nПрикосновения иммитируются мышью при зажатой кнопке. Escape назначен на кнопку меню, а PageUp - на кнопку назад."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Пытается эмулировать Android-планшет.\n\nПрикосновения иммитируются мышью при зажатой кнопке. Escape назначен на кнопку меню, а PageUp - на кнопку назад."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Скачивает и устанавливает Android SDK и поддерживающие пакеты. При желании, создает ключи для подписи пакета."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Настраивает имя пакета, версию, и другую информацию о проекте."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Открывает файл, содержащий ключи Google Play в редакторе.\n\nЭто необходимо лишь для случаев, если приложение использует расширяющий APK. Прочтите документацию для больших деталей."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Собирает Android-пакет."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Собирает Android-пакет, устанавливает его на Android-устройстве, подключенном к компьютеру."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Connects to an Android device running ADB in TCP/IP mode."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Disconnects from an Android device running ADB in TCP/IP mode."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Эмуляция:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Телефон"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Планшет"
+
+    # android.rpy:341
+    old "Television"
+    new "Television"
+
+    # android.rpy:353
+    old "Build:"
+    new "Собрать:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Установить SDK и создать ключи"
+
+    # android.rpy:365
+    old "Configure"
+    new "Настроить"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Собрать пакет"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Собрать и установить"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Build, Install & Launch"
+
+    # android.rpy:388
+    old "Other:"
+    new "Other:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Remote ADB Connect"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Remote ADB Disconnect"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Remote ADB Address"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Invalid remote ADB address"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "The address must contain one exactly one ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "The host may not contain whitespace."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "The port must be a number."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Невозможно изменить тему. Возможно, options.rpy был сильно изменен."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Планетарий"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Выберите тему"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Тема"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Цветовая схема"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Продолжить"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "ИНФОРМАЦИЯ"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Сканирую файлы проекта..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Пакеты не выбраны. Делать нечего."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Сканирую файлы Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Все пакеты были построены.\n\nВ связи с наличием информации о правах доступа, не распаковывайте дистрибутивы для Linux и Macintosh на Windows."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Архивирую файлы..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Пишу пакет [variant] [format]"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Создаю файл zsync для обновления [variant]"
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Обработано {b}[complete]{/b} из {b}[total]{/b} файлов."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Сборка Дистрибутивов: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Имя Папки:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Имя исполняемого файла:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Действия"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Редактировать options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Add from clauses to calls, once"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Обновить"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Построить пакеты:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Options:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Построить Обновления"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Add from clauses to calls"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Перекомпилировать проект"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Построить"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Adding from clauses to call statements that do not have them."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "При запуске проекта произошли ошибки. Пожалуйста, убедитесь в том, что проект успешно запускается, перед созданием дистрибутивов."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Ваш проект не содержит информацию, необходимую для сборки. Добавить её к концу options.rpy?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Рекомендуется.{/b} Beta-редактор с простым интерфейсом и возможностями, помогающими в разработке, такими, как проверка орфографии. Editra сейчас не поддерживает IME, необходимые для ввода Китайского, Японского и Корейского текстов."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Рекомендуется.{/b} Beta-редактор с простым интерфейсом и возможностями, помогающими в разработке, такими, как проверка орфографии. Editra сейчас не поддерживает IME, необходимые для ввода Китайского, Японского и Корейского текстов. На Linux, Editra требует wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Это могло случиться из-за того, что wxPython не установлен на этой системе."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Требуется скачать 22 МБ."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Проверенный временем редактор. Требует Java."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "Требуется скачать 1.8 МБ."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Это могло случиться из-за того, что Java не установлена на данной системе."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Включает текстовый редактор, ассоциированный на вашей системе с файлами .rpy."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Не позволяет Ren'Py запускать текстовый редактор."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Возникла ошибка при запуске текстового редактора:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Выберите редактор"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Текстовый редактор - программа, необходимая для редактирования сценариев Ren'Py. Здесь, вы можете выбрать редактор, который Ren'Py будет использовать. Если такового нет, редактор будет автоматически загружен и установлен."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Отмена"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Открыть папку [text]."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "обновить"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Добавить новый проект"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Запустить проект"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (образец)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Выбрать проект [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Обучение"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "Вопрос"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Активный Проект"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Открыть Папку"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Редактировать Файл"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Все файлы сценариев"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Навигация по Сценарию"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Проверить Сценарий (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Сменить тему"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Очистить постоянные данные"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Построить дистрибутивы"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Создать переводы"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Извлечь диалог"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Проверка потенциальных проблем сценария..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Удаление постоянных данных..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Перекомпиляция всех файлов rpy в файлы rpyc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "ИМЯ ПРОЕКТА"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Пожалуйтса, введите имя проекта:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Имя проекта не должно быть пустым."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] уже существует. Выберите другое имя проекта."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] уже существует. Выберите другое имя проекта."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Документация"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Сайт Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Список Игр Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "обновить"
+
+    # interface.rpy:119
+    old "preferences"
+    new "настройки"
+
+    # interface.rpy:120
+    old "quit"
+    new "выйти"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "В связи с ограничениями на форматы пакетов, не-ASCII имена файлов и папок недопустимы."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ОШИБКА"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Пока [what!q], возникла ошибка:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Текст не должен содержать знаки {{ или [[."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Имена файлов и папок не должны содержать / или \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Имена файлов и папок должны состоять из знаков ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "ОБРАБОТКА"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "ВОПРОС"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "ВЫБОР"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Selects the directory where Xcode projects will be placed."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Creates an Xcode project corresponding to the current Ren'Py project."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Opens the Xcode project in Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Opens the directory containing Xcode projects."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Select Xcode Projects Directory"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Create Xcode Project"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Update Xcode Project"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Launch Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Open Xcode Projects Directory"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py has set the Xcode Projects Directory to:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Навигация: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Порядок: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "алфавитный"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "по-файлу"
+
+    # navigation.rpy:182
+    old "natural"
+    new "натуральный"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Категория:"
+
+    # navigation.rpy:196
+    old "files"
+    new "файлы"
+
+    # navigation.rpy:197
+    old "labels"
+    new "метки"
+
+    # navigation.rpy:198
+    old "defines"
+    new "определения"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "трансформации"
+
+    # navigation.rpy:200
+    old "screens"
+    new "экраны"
+
+    # navigation.rpy:201
+    old "callables"
+    new "вызываемые"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODO"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Добавить файл сценария"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Не найдено комментариев TODO.\n\nЧтобы создать такой, включите \"#TODO\" в вашем сценарии"
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Список имен пуст."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "The projects directory could not be set. Giving up."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Выберите Образец Проекта"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Пожалуйста, выберите образец, на котором основывать ваш проект. Образец задает шрифт и язык по умолчанию для интерфейса. Если ваш язык не поддерживается, выберите 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Настройки Launcher"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Папка проектов:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Папка проектов: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Не задано"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Текстовый редактор:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Текстовый редактор: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Канал обновлений:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Опции навигации:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Включать приватные имена"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Включать имена библиотек"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Опции Launcher:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Аппаратный рендеринг"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Показывать образцы"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Show edit file section"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Большие шрифты"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Вывод на консоль"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Открыть проект launcher"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Язык:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "After making changes to the script, press shift+R to reload your game."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Press shift+O (the letter) to access the console."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Press shift+D to access the developer menu."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Have you backed up your projects recently?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Launching the project failed."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Please ensure that your project launches normally before running this command."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py сканирует проект..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Launching"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "ДИРЕКТОРИЯ ПРОЕКТОВ"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Пожалуйста, выберите директорию проектов, используя выбиратель директорий.\n{b}Он мог появится сзади этого окна.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Launcher будет искать проекты в этой директории, создавать новые проекты в этой директории, и размещать построенные проекты в этой директории."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py установила директорию проектов на:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Generate empty strings for translations"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py создает переводы..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py закончил создавать переводы для [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py извлекает диалог..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Выберите Канал Обновлений"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Канал Обновлений выбирает, какую версию Ren'Py скачает программа для обновления. Выберите канал обновлений:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Релиз"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Рекомендуется.{/b} Эта версия Ren'Py должна использоваться для всех новых игр."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Пререлиз"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Взгляд на следующую версию Ren'Py, которую можно использовать для тестирования и использования новых возможностей, но не для финальных релизов игр."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Экспериментальная"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Экспериментальные версии Ren'Py. Не выбирайте этот канал, если вас не просил об этом разработчик Ren'Py."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Возникла ошибка:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Проверка обновлений."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py обновлен."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] доступна. Вы хотите её установить?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Подготовка к обновлению."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Загрузка обновления."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Распаковка обновления."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Завершение."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Обновление было установлено. Ren'Py будет перезапущен."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Обновление было установлено."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Обновление было отменено."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Обновление Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Продолжить"
+
diff --git a/launcher/game/tl/russian/navigation.rpy b/launcher/game/tl/russian/navigation.rpy
deleted file mode 100644
index d23a6c9..0000000
--- a/launcher/game/tl/russian/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate russian strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Навигация: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Порядок: "
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "алфавитный"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "по-файлу"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "натуральный"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Категория:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "файлы"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "метки"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "определения"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "трансформации"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "экраны"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "вызываемые"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODO"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Добавить файл сценария"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Не найдено комментариев TODO.\n\nЧтобы создать такой, включите \"#TODO\" в вашем сценарии"
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "Список имен пуст."
-
diff --git a/launcher/game/tl/russian/new_project.rpy b/launcher/game/tl/russian/new_project.rpy
deleted file mode 100644
index 5c345ae..0000000
--- a/launcher/game/tl/russian/new_project.rpy
+++ /dev/null
@@ -1,31 +0,0 @@
-
-translate russian strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Выберите Образец Проекта"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Пожалуйста, выберите образец, на котором основывать ваш проект. Образец задает шрифт и язык по умолчанию для интерфейса. Если ваш язык не поддерживается, выберите 'english'."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "ИМЯ ПРОЕКТА"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Пожалуйтса, введите имя проекта:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "Имя проекта не должно быть пустым."
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] уже существует. Выберите другое имя проекта."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] уже существует. Выберите другое имя проекта."
-
diff --git a/launcher/game/tl/russian/obsolete.rpy b/launcher/game/tl/russian/obsolete.rpy
new file mode 100644
index 0000000..11fff40
--- /dev/null
+++ b/launcher/game/tl/russian/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate russian strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Назначение джойстика"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Пустой слот."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Предыдущий"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Следующий"
+
diff --git a/launcher/game/tl/russian/options.rpy b/launcher/game/tl/russian/options.rpy
new file mode 100644
index 0000000..058fbb4
--- /dev/null
+++ b/launcher/game/tl/russian/options.rpy
@@ -0,0 +1,195 @@
+
+translate russian strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/russian/preferences.rpy b/launcher/game/tl/russian/preferences.rpy
deleted file mode 100644
index 188d3d3..0000000
--- a/launcher/game/tl/russian/preferences.rpy
+++ /dev/null
@@ -1,78 +0,0 @@
-
-translate russian strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Настройки Launcher"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Папка проектов:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "Не задано"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Текстовый редактор:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Канал обновлений:"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Опции навигации:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Включать приватные имена"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Включать имена библиотек"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Опции Launcher:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Аппаратный рендеринг"
-
-    # game/preferences.rpy:146
-    old "Show templates"
-    new "Показывать образцы"
-
-    # game/preferences.rpy:149
-    old "Console output"
-    new "Вывод на консоль"
-
-    # game/preferences.rpy:170
-    old "Open launcher project"
-    new "Открыть проект launcher"
-
-    # game/preferences.rpy:184
-    old "Language:"
-    new "Язык:"
-
-
-translate russian strings:
-
-    # game/preferences.rpy:91
-    old "Projects directory: [text]"
-    new "Папка проектов: [text]"
-
-    # game/preferences.rpy:114
-    old "Text editor: [text]"
-    new "Текстовый редактор: [text]"
-
-    # game/preferences.rpy:171
-    old "Large fonts"
-    new "Большие шрифты"
-
diff --git a/launcher/game/tl/russian/project.rpy b/launcher/game/tl/russian/project.rpy
deleted file mode 100644
index 9ed14ee..0000000
--- a/launcher/game/tl/russian/project.rpy
+++ /dev/null
@@ -1,27 +0,0 @@
-
-translate russian strings:
-
-    # game/project.rpy:204
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py сканирует проект..."
-
-    # game/project.rpy:508
-    old "PROJECTS DIRECTORY"
-    new "ДИРЕКТОРИЯ ПРОЕКТОВ"
-
-    # game/project.rpy:508
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Пожалуйста, выберите директорию проектов, используя выбиратель директорий.\n{b}Он мог появится сзади этого окна.{/b}"
-
-    # game/project.rpy:508
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Launcher будет искать проекты в этой директории, создавать новые проекты в этой директории, и размещать построенные проекты в этой директории."
-
-    # game/project.rpy:548
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py не смогла запустить python с tkinter для выбора директории проектов."
-
-    # game/project.rpy:552
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py установила директорию проектов на:"
-
diff --git a/launcher/game/tl/russian/screens.rpy b/launcher/game/tl/russian/screens.rpy
new file mode 100644
index 0000000..88151c0
--- /dev/null
+++ b/launcher/game/tl/russian/screens.rpy
@@ -0,0 +1,643 @@
+
+translate russian strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Назад"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Skip"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Save"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.Save"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.Load"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Preferences"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Main Menu"
+
+    # screens.rpy:328
+    old "About"
+    new "О"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Help"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Выйти"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Вернуться"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Экран"
+
+    # screens.rpy:739
+    old "Window"
+    new "Окно"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Полный экран"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "After Choices"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transitions"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Text Speed"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Auto-Forward Time"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Music Volume"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Громкость звука"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Voice Volume"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Да"
+
+    # screens.rpy:1162
+    old "No"
+    new "Нет"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/russian/script.rpym b/launcher/game/tl/russian/script.rpym
new file mode 100644
index 0000000..9aa7be2
--- /dev/null
+++ b/launcher/game/tl/russian/script.rpym
@@ -0,0 +1,17 @@
+# Вы можете расположить сценарий своей игры в этом файле.
+
+# Объявляйте изображения здесь, используя оператор image.
+# например, image eileen happy = "eileen_happy.png"
+
+# Определение персонажей игры.
+define e = Character('Эйлин', color="#c8ffc8")
+
+
+# Игра начинается здесь.
+label start:
+
+    e "Вы создали новую игру Ren'Py."
+
+    e "Добавьте сюжет, изображения и музыку и отправьте её в мир!"
+
+    return
diff --git a/launcher/game/tl/russian/translations.rpy b/launcher/game/tl/russian/translations.rpy
deleted file mode 100644
index 37f8990..0000000
--- a/launcher/game/tl/russian/translations.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate russian strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Создать или Обновить Переводы"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Пожалуйста, введите имя языка, для которого вы хотите создать или обновить переводы."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "Имя языка не должно быть пустой строкой."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Py создает переводы..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py закончил создавать переводы для [language]."
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "Какой формат вы желаете для извлеченного диалога?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py извлекает диалог..."
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py закончила извлечение диалога. Извлеченный диалог может быть найден в папке base, в подпапке dialogue.[format]."
-
diff --git a/launcher/game/tl/russian/updater.rpy b/launcher/game/tl/russian/updater.rpy
deleted file mode 100644
index d3f6ebf..0000000
--- a/launcher/game/tl/russian/updater.rpy
+++ /dev/null
@@ -1,87 +0,0 @@
-
-translate russian strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Выберите Канал Обновлений"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Канал Обновлений выбирает, какую версию Ren'Py скачает программа для обновления. Выберите канал обновлений:"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Релиз"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Рекомендуется.{/b} Эта версия Ren'Py должна использоваться для всех новых игр."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Пререлиз"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Взгляд на следующую версию Ren'Py, которую можно использовать для тестирования и использования новых возможностей, но не для финальных релизов игр."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Экспериментальная"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Экспериментальные версии Ren'Py. Не выбирайте этот канал, если вас не просил об этом разработчик Ren'Py."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Возникла ошибка:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Проверка обновлений."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren'Py обновлен."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] доступна. Вы хотите её установить?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Подготовка к обновлению."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Загрузка обновления."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Распаковка обновления."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Завершение."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "Обновление было установлено. Ren'Py будет перезапущен."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "Обновление было установлено."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "Обновление было отменено."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Обновление Ren'Py"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Продолжить"
-
diff --git a/launcher/game/tl/simplified_chinese/about.rpy b/launcher/game/tl/simplified_chinese/about.rpy
deleted file mode 100644
index ba205c2..0000000
--- a/launcher/game/tl/simplified_chinese/about.rpy
+++ /dev/null
@@ -1,11 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/about.rpy:43
-    old "View license"
-    new "查看许可证"
-
-    # game/about.rpy:45
-    old "Back"
-    new "返回"
-
diff --git a/launcher/game/tl/simplified_chinese/add_file.rpy b/launcher/game/tl/simplified_chinese/add_file.rpy
deleted file mode 100644
index fcc0982..0000000
--- a/launcher/game/tl/simplified_chinese/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "文件名"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "请输入文件名来创建脚本文件。"
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "文件必须以 .rpy 为扩展名。"
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "文件已存在。"
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py 自动加载所有以 .rpy 为后缀的脚本。要使用此 \n# 文件,请先从其他文件中定义一个标签并跳转过来。\n"
-
diff --git a/launcher/game/tl/simplified_chinese/android.rpy b/launcher/game/tl/simplified_chinese/android.rpy
deleted file mode 100644
index ebe8185..0000000
--- a/launcher/game/tl/simplified_chinese/android.rpy
+++ /dev/null
@@ -1,155 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "要生成安卓应用包,请下载 RAPT,并解压到 Ren'Py 目录中。之后重启 Ren'Py。"
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "要在 Windows 中创建安卓应用包,您需要一个 32 位的 Java 开发套件(JDK)。JDK 不同于 JRE,所以您可能已安装过 Java 但尚未安装 JDK。\n\n请{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}下载并安装 JDK{/a},然后重启 Ren'Py。"
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT 已安装,但您还需要安装安卓 SDK 才可以生成安卓应用包。点击安装 SDK 来继续。"
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT 已完成安装,但密钥尚未进行过配置。请创建一个新密钥,或将参数 android.keystore 恢复。"
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "当前工程尚未配置过。请在生成前使用“配置”来进行配置。"
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "选择“生成”来生成当前工程,或者在添加安卓设备之后,选择“生成并安装”来生成并安装到设备中。"
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "尝试模拟为安卓手机。\n\n鼠标将仅在按键按下时模拟为触屏输入。Esc 和 PageUp 键将分别重映射为手机的菜单键和返回键。"
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "尝试模拟为安卓平板。\n\nEsc 和 PageUp 键将分别重映射为平板的菜单键和返回键。"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "尝试模拟为基于电视的安卓平台,例如 OUYA 或 Fire TV。\n\n键盘方向键将重映射为手柄方向键,Enter、Esc 和 PageUp 键将分别重映射为手柄的选择键、菜单键和返回键。"
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "下载并安装安卓 SDK 以及支持包。另外,对应用包签名需要生成密钥。"
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "配置应用包名称、版本号以及关于此工程的一些其他信息。"
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "在编辑器中打开包含有 Google Play 密钥的文件。\n\n仅当您的应用使用了扩展 APK 时才需要进行此操作。更多详情请查阅说明文档。"
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "生成安卓应用包。"
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "生成安卓应用包,并将其安装到连接至此计算机的安卓设备中。"
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "生成安卓应用包,将其安装到连接至此计算机的安卓设备中,并在您的设备上打开此应用。"
-
-    # game/android.rpy:48
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "连接到一台正在 TCP/IP 模式下运行 ADB 的安卓设备。"
-
-    # game/android.rpy:49
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "从一台正在 TCP/IP 模式下运行 ADB 的安卓设备断开连接。"
-
-    # game/android.rpy:253
-    old "Android: [project.current.name!q]"
-    new "安卓:[project.current.name!q]"
-
-    # game/android.rpy:273
-    old "Emulation:"
-    new "模拟:"
-
-    # game/android.rpy:282
-    old "Phone"
-    new "手机"
-
-    # game/android.rpy:286
-    old "Tablet"
-    new "平板"
-
-    # game/android.rpy:290
-    old "Television"
-    new "电视"
-
-    # game/android.rpy:302
-    old "Build:"
-    new "生成:"
-
-    # game/android.rpy:310
-    old "Install SDK & Create Keys"
-    new "安装 SDK 并创建密钥"
-
-    # game/android.rpy:314
-    old "Configure"
-    new "配置"
-
-    # game/android.rpy:318
-    old "Build Package"
-    new "生成应用包"
-
-    # game/android.rpy:322
-    old "Build & Install"
-    new "生成应用包并安装"
-
-    # game/android.rpy:326
-    old "Build, Install & Launch"
-    new "生成应用包,安装并启动"
-
-    # game/android.rpy:337
-    old "Other:"
-    new "其他:"
-
-    # game/android.rpy:345
-    old "Remote ADB Connect"
-    new "远程 ADB 连接"
-
-    # game/android.rpy:349
-    old "Remote ADB Disconnect"
-    new "远程 ADB 断开连接"
-
-    # game/android.rpy:382
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "在为安卓应用打包之前,您需要先下载 RAPT,即 Ren'Py 安卓打包工具。您希望现在就开始下载 RAPT 吗?"
-
-    # game/android.rpy:435
-    old "Remote ADB Address"
-    new "远程 ADB 地址"
-
-    # game/android.rpy:435
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "请输入要连接的 IP 地址和端口号,格式为“192.168.1.143:5555”。请查阅您设备的说明文档来确认您的设备是否支持远程 ADB,如果是,请确认可用的 IP 地址和端口号。"
-
-    # game/android.rpy:447
-    old "Invalid remote ADB address"
-    new "无效的远程 ADB 地址"
-
-    # game/android.rpy:447
-    old "The address must contain one exactly one ':'."
-    new "地址中必须有且仅有一个“:”。"
-
-    # game/android.rpy:451
-    old "The host may not contain whitespace."
-    new "主机地址不能包含空格。"
-
-    # game/android.rpy:457
-    old "The port must be a number."
-    new "端口号必须为数字。"
-
diff --git a/launcher/game/tl/simplified_chinese/choose_directory.rpy b/launcher/game/tl/simplified_chinese/choose_directory.rpy
deleted file mode 100644
index 2bd0710..0000000
--- a/launcher/game/tl/simplified_chinese/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py 无法使用 Python 的 Tkinter 来选择目录。请安装 Python-tk 或 Tkinter 支持包。"
-
diff --git a/launcher/game/tl/simplified_chinese/choose_theme.rpy b/launcher/game/tl/simplified_chinese/choose_theme.rpy
deleted file mode 100644
index 1e42f18..0000000
--- a/launcher/game/tl/simplified_chinese/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/choose_theme.rpy:303
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "无法更改主题。可能 options.rpy 已被过度修改。"
-
-    # game/choose_theme.rpy:368
-    old "Display"
-    new "Display" # Can't display in Ren'Py.
-
-    # game/choose_theme.rpy:369
-    old "Window"
-    new "Window" # Can't display in Ren'Py.
-
-    # game/choose_theme.rpy:370
-    old "Fullscreen"
-    new "Fullscreen" # Can't display in Ren'Py.
-
-    # game/choose_theme.rpy:371
-    old "Planetarium"
-    new "Planetarium" # Can't display in Ren'Py.
-
-    # game/choose_theme.rpy:378
-    old "Sound Volume"
-    new "Sound Volume" # Can't display in Ren'Py.
-
-    # game/choose_theme.rpy:412
-    old "Choose Theme"
-    new "选择主题"
-
-    # game/choose_theme.rpy:425
-    old "Theme"
-    new "主题"
-
-    # game/choose_theme.rpy:449
-    old "Color Scheme"
-    new "配色方案"
-
-    # game/choose_theme.rpy:480
-    old "Continue"
-    new "继续"
-
diff --git a/launcher/game/tl/simplified_chinese/common.rpy b/launcher/game/tl/simplified_chinese/common.rpy
index 7f74634..fa1eba2 100644
--- a/launcher/game/tl/simplified_chinese/common.rpy
+++ b/launcher/game/tl/simplified_chinese/common.rpy
@@ -1,178 +1,335 @@
 
 translate simplified_chinese strings:
 
-    # renpy/common/00action_file.rpy:142
-    old "%b %d, %H:%M"
-    new "%m-%d  %H:%M"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00action_file.rpy:621
-    old "Quick save complete."
-    new "快速保存完成。"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-### Due the font issue, console, gltest and developer menu can't show chinese, so it is useless to translate.
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-translate simplified_chinese strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00keymap.rpy:206
-    old "Saved screenshot as %s."
-    new "截图已保存为 %s。"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-translate simplified_chinese strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
+
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
+
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
+
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
+
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
+
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
+
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00layout.rpy:444
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
+
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%m月%d日, %H:%M"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "快速存档。"
+
+    # 00gui.rpy:227
     old "Are you sure?"
-    new "您确定吗?"
+    new "是否确认?"
 
-    # renpy/common/00layout.rpy:445
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
-    new "您确定要删除此存档吗?"
+    new "您确定您要删掉这份存档吗?"
 
-    # renpy/common/00layout.rpy:446
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
-    new "您确定要覆盖此存档吗?"
+    new "您确定您要覆盖存档?"
 
-    # renpy/common/00layout.rpy:447
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
-    new "读取存档将会使未保存的进度丢失。\n您确定要继续吗?"
+    new "载入将会失去所有未储存的进度。\n您确定您要这么做吗?"
 
-    # renpy/common/00layout.rpy:448
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
-    new "您确定要退出吗?"
+    new "您确定您要退出吗?"
 
-    # renpy/common/00layout.rpy:449
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
-    new "您确定要返回到主菜单吗?\n此操作将会使未保存的进度丢失。"
+    new "您确定您想回到标题画面吗?\n未保存的进度将会丢失。"
+
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
 
-    # renpy/common/00layout.rpy:450
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
-    new "您确定要开始快进吗?"
+    new "是否确定开始快进?"
 
-    # renpy/common/00layout.rpy:451
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
-    new "您确定要直接快进到下个选择支吗?"
+    new "是否确定跳到下一个选项?"
 
-    # renpy/common/00layout.rpy:452
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "您确定要直接跳过未读对话或下个选择支吗?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "储存屏幕截图为 %s。"
 
-translate simplified_chinese strings:
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-    # renpy/common/00library.rpy:149
-    old "Skip Mode"
-    new "快进模式"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/00library.rpy:152
-    old "Fast Skip Mode"
-    new "跃进模式"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "快进"
 
-translate simplified_chinese strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:387
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "剪贴板朗读已开启。按 Shift+C 来关闭。"
 
-    # renpy/common/00preferences.rpy:389
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "自动朗读已开启。按 V 来关闭。"
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate simplified_chinese strings:
-
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "Ren'Py 更新器在移动设备上尚不支持。"
 
-    # renpy/common/00updater.rpy:478
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "已模拟一个错误。"
 
-    # renpy/common/00updater.rpy:654
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "此工程不支持更新,或者是更新状态文件已被删除。"
 
-    # renpy/common/00updater.rpy:668
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "此帐号没有执行更新的权限。"
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "此帐号没有写入更新日志的权限。"
 
-    # renpy/common/00updater.rpy:696
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "无法验证更新签名。"
 
-    # renpy/common/00updater.rpy:956
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "更新文件未能下载。"
 
-    # renpy/common/00updater.rpy:974
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "更新文件校验失败。文件可能已损坏。"
 
-    # renpy/common/00updater.rpy:1030
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "解压 {} 时出现未知错误 {}。"
 
-    # renpy/common/00updater.rpy:1380
+    # 00updater.rpy:1393
     old "Updater"
-    new "更新器"
+    new "更新"
 
-    # renpy/common/00updater.rpy:1389
+    # 00updater.rpy:1404
     old "This program is up to date."
-    new "程序已更新到最新版本。"
+    new "该程序已是最新版本。"
 
-    # renpy/common/00updater.rpy:1391
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
-    new "[u.version] 现已可用。您希望现在安装吗?"
+    new "[u.version] 已放出。是否确认安装?"
 
-    # renpy/common/00updater.rpy:1393
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "正在准备下载更新。"
 
-    # renpy/common/00updater.rpy:1395
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "正在下载更新。"
 
-    # renpy/common/00updater.rpy:1397
+    # 00updater.rpy:1412
     old "Unpacking the updates."
-    new "正在解压更新。"
+    new "解压缩更新包。"
 
-    # renpy/common/00updater.rpy:1401
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
-    new "更新已安装。程序即将重启。"
+    new "该更新包已安装,程序将会重新启动。"
 
-    # renpy/common/00updater.rpy:1403
+    # 00updater.rpy:1418
     old "The updates have been installed."
-    new "更新已安装。"
+    new "已完成更新。"
 
-    # renpy/common/00updater.rpy:1405
+    # 00updater.rpy:1420
     old "The updates were cancelled."
-    new "更新已取消。"
-
+    new "已取消更新。"
 
-translate simplified_chinese strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "空存档位。"
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "[count]个图片中的第[index]个图片被锁定。"
 
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
+    # 00gallery.rpy:583
+    old "prev"
     new "上一页"
 
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
+    # 00gallery.rpy:584
+    old "next"
     new "下一页"
 
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "幻灯片"
 
-translate simplified_chinese strings:
+    # 00gallery.rpy:586
+    old "return"
+    new "返回"
 
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "手柄按键映射"
diff --git a/launcher/game/tl/simplified_chinese/developer.rpy b/launcher/game/tl/simplified_chinese/developer.rpy
new file mode 100644
index 0000000..a1359f5
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/developer.rpy
@@ -0,0 +1,179 @@
+
+translate simplified_chinese strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "开发者菜单"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "重载游戏(Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "控制台(Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "变量查看器"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "主题测试"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "图片坐标提取器"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "文件列表"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "显示图片加载记录"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "隐藏图片加载记录"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "没有东西被检阅"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "回到开发者菜单"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "矩形区域:%r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "鼠标位置:%r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "点选鼠标右键或者按 Esc 键来退出。"
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectangle copied to clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Position copied to clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable 检阅器"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "大小"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "风格"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Location"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "检阅[displayable_name!q]的风格"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "displayable"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (没有偏好的可显示属性)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (忽略默认属性)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "按 <esc> 来退出控制台。输入 help 来查看帮助。\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "使用 Ren'Py 脚本。"
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "禁用 Ren'Py 脚本。"
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: 显示说明信息"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "命令行:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>:运行语句\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>:运行表达式或语句"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: 清除控制台历史记录"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: 离开控制台"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>:载入游戏存档(以 slot 为存档号)"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>:储存游戏存档(以 slot 为存档号)"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: 重载游戏,并重新整理脚本"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: 监视一个 python 表达式"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>:停止监视某个表达式"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall:停止监视索引表达式"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: 跳移至标签"
+
diff --git a/launcher/game/tl/simplified_chinese/distribute.rpy b/launcher/game/tl/simplified_chinese/distribute.rpy
deleted file mode 100644
index 442503c..0000000
--- a/launcher/game/tl/simplified_chinese/distribute.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "生成分发版失败:\n\n参数 build.directory_name 不能包含空格、冒号和分号。"
-
-    # game/distribute.rpy:381
-    old "No packages are selected, so there's nothing to do."
-    new "因未选择任何打包平台,故未执行任何操作。"
-
-    # game/distribute.rpy:386
-    old "Scanning project files..."
-    new "正在扫描工程文件……"
-
-    # game/distribute.rpy:396
-    old "Scanning Ren'Py files..."
-    new "正在扫描 Ren'Py 文件……"
-
-    # game/distribute.rpy:444
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "所有的分发包已生成。\n\n由于包内写入了权限信息,因此在 Windows 上解包并重新打包 Linux 和 Macintosh 分发版是不可行的。"
-
-    # game/distribute.rpy:568
-    old "Archiving files..."
-    new "正在封装文件……"
-
-    # game/distribute.rpy:845
-    old "Writing the [variant] [format] package."
-    new "正在写入 [variant] 版 [format] 包。"
-
-    # game/distribute.rpy:858
-    old "Making the [variant] update zsync file."
-    new "正在制作 [variant] 版更新同步文件。"
-
-    # game/distribute.rpy:957
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "已处理 {b}[complete]{/b} / {b}[total]{/b} 个文件。"
-
diff --git a/launcher/game/tl/simplified_chinese/distribute_gui.rpy b/launcher/game/tl/simplified_chinese/distribute_gui.rpy
deleted file mode 100644
index 1986063..0000000
--- a/launcher/game/tl/simplified_chinese/distribute_gui.rpy
+++ /dev/null
@@ -1,63 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "生成分发版:[project.current.name!q]"
-
-    # game/distribute_gui.rpy:171
-    old "Directory Name:"
-    new "目录名:"
-
-    # game/distribute_gui.rpy:175
-    old "Executable Name:"
-    new "可执行程序名:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "操作:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "编辑 options.rpy"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "向 call 语句添加 from 从句,执行一次"
-
-    # game/distribute_gui.rpy:195
-    old "Refresh"
-    new "刷新"
-
-    # game/distribute_gui.rpy:212
-    old "Build Packages:"
-    new "生成分发包:"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "选项:"
-
-    # game/distribute_gui.rpy:236
-    old "Build Updates"
-    new "生成更新"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "向 call 语句添加 from 从句"
-
-    # game/distribute_gui.rpy:242
-    old "Build"
-    new "生成"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "正在向 call 语句添加缺失的 from 从句。"
-
-    # game/distribute_gui.rpy:267
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "运行工程时检测到错误。请在生成分发版之前确保工程能够正常运行。"
-
-    # game/distribute_gui.rpy:284
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "您的工程尚未包含生成信息。您希望在 options.rpy 末端添加生成信息吗?"
-
diff --git a/launcher/game/tl/simplified_chinese/editor.rpy b/launcher/game/tl/simplified_chinese/editor.rpy
deleted file mode 100644
index a0c76d4..0000000
--- a/launcher/game/tl/simplified_chinese/editor.rpy
+++ /dev/null
@@ -1,57 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}建议使用。{/b}一个测试版编辑器,拥有简单易用的界面和诸如拼写检查之类的辅助开发功能。Editra 目前可能缺乏对中日韩输入法的良好支持。"# This is the original translation, but in fact Editra support the CJK IME, as least chinese. I'm using this editor developing.
-# So you may change it to:
-#new "{b}建议使用。{/b}一个测试版编辑器,拥有简单易用的界面,以及诸如拼写检查之类的辅助开发功能。"
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}建议使用。{/b}一个测试版编辑器,拥有简单易用的界面和诸如拼写检查之类的辅助开发功能。Editra 目前可能缺乏对中日韩输入法的良好支持。在 Linux 系统运行 Editra 需要安装 wxPython。"
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "这可能是由于您的系统中尚未安装 wxPython 造成的。"
-
-    # game/editor.rpy:169
-    old "Up to 22 MB download required."
-    new "需要下载最多 22 MB 的文件。"
-
-    # game/editor.rpy:182
-    old "A mature editor that requires Java."
-    new "一个成熟的编辑器,需要安装 Java。"
-
-    # game/editor.rpy:182
-    old "1.8 MB download required."
-    new "需要下载 1.8 MB 的文件。"
-
-    # game/editor.rpy:182
-    old "This may have occured because Java is not installed on this system."
-    new "这可能是由于您的系统中尚未安装 Java 造成的。"
-
-    # game/editor.rpy:191
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "调用您操作系统已关联到 .rpy 文件的编辑器。"
-
-    # game/editor.rpy:207
-    old "Prevents Ren'Py from opening a text editor."
-    new "禁止 Ren'Py 自动打开文本编辑器。"
-
-    # game/editor.rpy:359
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "启动编辑器时出现异常:\n[exception!q]"
-
-    # game/editor.rpy:457
-    old "Select Editor"
-    new "选择编辑器"
-
-    # game/editor.rpy:472
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "文本编辑器是指您用来编辑 Ren'Py 脚本的程序。在这里您可以选择 Ren'Py 要使用的编辑器。若您选择的编辑器并不存在,Ren'Py 将会自动下载并安装此编辑器。"
-
-    # game/editor.rpy:494
-    old "Cancel"
-    new "取消"
-
diff --git a/launcher/game/tl/simplified_chinese/error.rpy b/launcher/game/tl/simplified_chinese/error.rpy
new file mode 100644
index 0000000..8bc51fb
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/error.rpy
@@ -0,0 +1,179 @@
+
+translate simplified_chinese strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "图形加速"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "自动选择"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "强制 Angle/DirectX 渲染"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "强制 OpenGL 渲染"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "强制软件渲染"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "更改将会在下次启动程序时生效。"
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "性能影响警告"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "该计算机正在使用软件渲染。"
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "该计算机没有使用着色器"
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "该计算机图形显示缓慢。"
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "该计算机图形显示出错:[problem]。"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "目前的图形驱动程序版本可能过旧或未正确运行。这样会导致图形显示缓慢或者错误。升级 DirectX 可能会解决该问题。"
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "目前图形驱动程序版本可能过旧或未正确运行。这样会导致图形显示缓慢或者错误。"
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "更新 DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "继续,下次再显示该警告"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "继续,不再显示该警告"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "正在更新 DirectX。"
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX 在线安装已启动,它将会最小化至任务栏。请按照说明安装 DirectX。"
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}警告:{/b} Microsoft's DirectX 在线安装程序会默认安装 Bing 浏览器工具栏。如果您不需要安装这个工具栏,请取消勾选对应选项。"
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "当安装完成后请点选下方来重新启动应用程序。"
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "重新启动"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "打开日志"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "在文本编辑器中打开日志(traceback.txt)。"
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "发生一个异常状况。"
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "回滚一行"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "尝试回滚到先前的状态,使您可以存盘或者选择不同选项。"
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "忽略错误"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "忽略异常,让您可以继续。但这通常会带来更多的问题。"
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "重新加载"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "从硬盘重载游戏,请您储存游戏状态。"
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "离开游戏。"
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "解析脚本失败。"
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "开启解析错误"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "在文本编辑器中打开解析错误档案(errors.txt)。"
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/simplified_chinese/front_page.rpy b/launcher/game/tl/simplified_chinese/front_page.rpy
deleted file mode 100644
index 0defe06..0000000
--- a/launcher/game/tl/simplified_chinese/front_page.rpy
+++ /dev/null
@@ -1,91 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "打开 [text] 目录。"
-
-    # game/front_page.rpy:93
-    old "refresh"
-    new "刷新"
-
-    # game/front_page.rpy:120
-    old "+ Create New Project"
-    new "+ 创建新工程"
-
-    # game/front_page.rpy:132
-    old "Launch Project"
-    new "启动工程"
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "选择工程 [text]。"
-
-    # game/front_page.rpy:166
-    old "Tutorial"
-    new "教程"
-
-    # game/front_page.rpy:183
-    old "Active Project"
-    new "活跃工程"
-
-    # game/front_page.rpy:191
-    old "Open Directory"
-    new "打开目录"
-
-    # game/front_page.rpy:204
-    old "Edit File"
-    new "编辑文件"
-
-    # game/front_page.rpy:212
-    old "All script files"
-    new "全部脚本文件"
-
-    # game/front_page.rpy:221
-    old "Navigate Script"
-    new "定位脚本"
-
-    # game/front_page.rpy:232
-    old "Check Script (Lint)"
-    new "检查脚本并分析统计"
-
-    # game/front_page.rpy:233
-    old "Change Theme"
-    new "更改主题"
-
-    # game/front_page.rpy:234
-    old "Delete Persistent"
-    new "删除永久性数据"
-
-    # game/front_page.rpy:235
-    old "Force Recompile"
-    new "强制重新编译"
-
-    # game/front_page.rpy:243
-    old "Build Distributions"
-    new "生成分发版"
-
-    # game/front_page.rpy:245
-    old "Android"
-    new "安卓"
-
-    # game/front_page.rpy:247
-    old "Generate Translations"
-    new "生成翻译文件"
-
-    # game/front_page.rpy:248
-    old "Extract Dialogue"
-    new "导出对话"
-
-    # game/front_page.rpy:264
-    old "Checking script for potential problems..."
-    new "正在检查脚本中的潜在问题……"
-
-    # game/front_page.rpy:279
-    old "Deleting persistent data..."
-    new "正在删除永久性数据……"
-
-    # game/front_page.rpy:287
-    old "Recompiling all rpy files into rpyc files..."
-    new "正在将全部的 rpy 文件重新编译至 rpyc 文件……"
-
diff --git a/launcher/game/tl/simplified_chinese/gui.rpy b/launcher/game/tl/simplified_chinese/gui.rpy
new file mode 100644
index 0000000..ae70d11
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/gui.rpy
@@ -0,0 +1,411 @@
+
+translate simplified_chinese strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/simplified_chinese/interface.rpy b/launcher/game/tl/simplified_chinese/interface.rpy
deleted file mode 100644
index 7aa2e90..0000000
--- a/launcher/game/tl/simplified_chinese/interface.rpy
+++ /dev/null
@@ -1,79 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "说明文档"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "Ren'Py 官方网站"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "Ren'Py 游戏列表"
-
-    # game/interface.rpy:110
-    old "About"
-    new "关于"
-
-    # game/interface.rpy:117
-    old "update"
-    new "更新"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "设置"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "退出"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "确定"
-
-    # game/interface.rpy:194
-    old "No"
-    new "取消"
-
-    # game/interface.rpy:229
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "由于包格式限制,非 ASCII 文件名和目录名将不被允许。"
-
-    # game/interface.rpy:321
-    old "ERROR"
-    new "错误"
-
-    # game/interface.rpy:350
-    old "While [what!q], an error occured:"
-    new "在 [what!q] 时发生了一个错误:"
-
-    # game/interface.rpy:369
-    old "Text input may not contain the {{ or [[ characters."
-    new "文本输入不得包含 {{ 或 [[ 字符。"
-
-    # game/interface.rpy:374
-    old "File and directory names may not contain / or \\."
-    new "文件名或目录名不得包含 / 或 \\。"
-
-    # game/interface.rpy:380
-    old "File and directory names must consist of ASCII characters."
-    new "文件名或目录名必须仅由 ASCII 字符组成,不能包含中文。"
-
-    # game/interface.rpy:401
-    old "INFORMATION"
-    new "信息"
-
-    # game/interface.rpy:448
-    old "PROCESSING"
-    new "正在处理"
-
-    # game/interface.rpy:465
-    old "QUESTION"
-    new "问题"
-
-    # game/interface.rpy:478
-    old "CHOICE"
-    new "选择"
-
diff --git a/launcher/game/tl/simplified_chinese/ios.rpy b/launcher/game/tl/simplified_chinese/ios.rpy
deleted file mode 100644
index cbb29ce..0000000
--- a/launcher/game/tl/simplified_chinese/ios.rpy
+++ /dev/null
@@ -1,91 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "要生成 iOS 应用包,请下载 renios,并解压到 Ren'Py 目录中。之后重启 Ren'Py。"
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Xcode 工程所存放的目录尚未被指定。选择“指定目录”来指定。"
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "尚无与目前 Ren'Py 工程对应的 Xcode 工程。选择“创建 Xcode 工程”来进行创建。"
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "一个 Xcode 工程已经存在。选择“更新 Xcode 工程”来以最新的游戏文件更新,或使用 Xcode 来生成并安装。"
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "尝试模拟为 iPad。\n\n鼠标将仅在按键按下时模拟为触屏输入。"
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "尝试模拟为 iPad。\n\n鼠标将仅在按键按下时模拟为触屏输入。"
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "请指定即将放置 Xcode 工程的目录。"
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "创建与当前 Ren'Py 工程对应的 Xcode 工程。"
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "以最新的游戏文件更新 Xcode 工程。此操作应该在每次 Ren'Py 工程出现更改时执行一次。"
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "在 Xcode 中打开 Xcode 工程。"
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "打开包含 Xcode 工程的目录。"
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Xcode 工程已经存在。您希望重命名旧工程,并用新工程取代之吗?"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS:[project.current.name!q]"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "指定 Xcode 工程目录"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "创建 Xcode 工程"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "更新 Xcode 工程"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "启动 Xcode"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "打开 Xcode 工程目录"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "在为 iOS 应用打包之前,您需要先下载 renios,即 Ren'Py iOS 支持套件。您希望现在就开始下载 renios 吗?"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "XCODE 工程目录"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "请使用弹出的目录选择窗口来指定 Xcode 工程目录。\n{b}目录选择窗口可能因未取得焦点而被本窗口覆盖。{/b}"
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py 已将 Xcode 工程目录设置为:"
-
diff --git a/launcher/game/tl/simplified_chinese/launcher.rpy b/launcher/game/tl/simplified_chinese/launcher.rpy
new file mode 100644
index 0000000..22b2616
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate simplified_chinese strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "查看许可证"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "文件名"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "请输入文件名来创建脚本文件。"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "文件必须以 .rpy 为扩展名。"
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "文件已存在。"
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py 自动加载所有以 .rpy 为后缀的脚本。要使用此 \n# 文件,请先从其他文件中定义一个标签并跳转过来。\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "要生成安卓应用包,请下载 RAPT,并解压到 Ren'Py 目录中。之后重启 Ren'Py。"
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "要在 Windows 中创建安卓应用包,您需要一个 32 位的 Java 开发套件(JDK)。JDK 不同于 JRE,所以您可能已安装过 Java 但尚未安装 JDK。\n\n请{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}下载并安装 JDK{/a},然后重启 Ren'Py。"
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT 已安装,但您还需要安装安卓 SDK 才可以生成安卓应用包。点击安装 SDK 来继续。"
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT 已完成安装,但密钥尚未进行过配置。请创建一个新密钥,或将参数 android.keystore 恢复。"
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "当前工程尚未配置过。请在生成前使用“配置”来进行配置。"
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "选择“生成”来生成当前工程,或者在添加安卓设备之后,选择“生成并安装”来生成并安装到设备中。"
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "尝试模拟为安卓手机。\n\n鼠标将仅在按键按下时模拟为触屏输入。Esc 和 PageUp 键将分别重映射为手机的菜单键和返回键。"
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "尝试模拟为安卓平板。\n\nEsc 和 PageUp 键将分别重映射为平板的菜单键和返回键。"
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "尝试模拟为基于电视的安卓平台,例如 OUYA 或 Fire TV。\n\n键盘方向键将重映射为手柄方向键,Enter、Esc 和 PageUp 键将分别重映射为手柄的选择键、菜单键和返回键。"
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "下载并安装安卓 SDK 以及支持包。另外,对应用包签名需要生成密钥。"
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "配置应用包名称、版本号以及关于此工程的一些其他信息。"
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "在编辑器中打开包含有 Google Play 密钥的文件。\n\n仅当您的应用使用了扩展 APK 时才需要进行此操作。更多详情请查阅说明文档。"
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "生成安卓应用包。"
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "生成安卓应用包,并将其安装到连接至此计算机的安卓设备中。"
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "生成安卓应用包,将其安装到连接至此计算机的安卓设备中,并在您的设备上打开此应用。"
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "连接到一台正在 TCP/IP 模式下运行 ADB 的安卓设备。"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "从一台正在 TCP/IP 模式下运行 ADB 的安卓设备断开连接。"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "安卓:[project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "模拟:"
+
+    # android.rpy:333
+    old "Phone"
+    new "手机"
+
+    # android.rpy:337
+    old "Tablet"
+    new "平板"
+
+    # android.rpy:341
+    old "Television"
+    new "电视"
+
+    # android.rpy:353
+    old "Build:"
+    new "生成:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "安装 SDK 并创建密钥"
+
+    # android.rpy:365
+    old "Configure"
+    new "配置"
+
+    # android.rpy:369
+    old "Build Package"
+    new "生成应用包"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "生成应用包并安装"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "生成应用包,安装并启动"
+
+    # android.rpy:388
+    old "Other:"
+    new "其他:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "远程 ADB 连接"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "远程 ADB 断开连接"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "在为安卓应用打包之前,您需要先下载 RAPT,即 Ren'Py 安卓打包工具。您希望现在就开始下载 RAPT 吗?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "远程 ADB 地址"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "请输入要连接的 IP 地址和端口号,格式为“192.168.1.143:5555”。请查阅您设备的说明文档来确认您的设备是否支持远程 ADB,如果是,请确认可用的 IP 地址和端口号。"
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "无效的远程 ADB 地址"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "地址中必须有且仅有一个“:”。"
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "主机地址不能包含空格。"
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "端口号必须为数字。"
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py 无法使用 Python 的 Tkinter 来选择目录。请安装 Python-tk 或 Tkinter 支持包。"
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "无法更改主题。可能 options.rpy 已被过度修改。"
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "选择主题"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "主题"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "配色方案"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "继续"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "信息"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "正在扫描工程文件……"
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "生成分发版失败:\n\n参数 build.directory_name 不能包含空格、冒号和分号。"
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "因未选择任何打包平台,故未执行任何操作。"
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "正在扫描 Ren'Py 文件……"
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "所有的分发包已生成。\n\n由于包内写入了权限信息,因此在 Windows 上解包并重新打包 Linux 和 Macintosh 分发版是不可行的。"
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "正在封装文件……"
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "正在写入 [variant] 版 [format] 包。"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "正在制作 [variant] 版更新同步文件。"
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "已处理 {b}[complete]{/b} / {b}[total]{/b} 个文件。"
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "生成分发版:[project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "目录名:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "可执行程序名:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "操作:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "编辑 options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "向 call 语句添加 from 从句,执行一次"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "刷新"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "生成分发包:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "选项:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "生成更新"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "向 call 语句添加 from 从句"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "强制重新编译"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "生成"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "正在向 call 语句添加缺失的 from 从句。"
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "运行工程时检测到错误。请在生成分发版之前确保工程能够正常运行。"
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "您的工程尚未包含生成信息。您希望在 options.rpy 末端添加生成信息吗?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}建议使用。{/b}一个测试版编辑器,拥有简单易用的界面和诸如拼写检查之类的辅助开发功能。Editra 目前可能缺乏对中日韩输入法的良好支持。"
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}建议使用。{/b}一个测试版编辑器,拥有简单易用的界面和诸如拼写检查之类的辅助开发功能。Editra 目前可能缺乏对中日韩输入法的良好支持。在 Linux 系统运行 Editra 需要安装 wxPython。"
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "这可能是由于您的系统中尚未安装 wxPython 造成的。"
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "需要下载最多 22 MB 的文件。"
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "一个成熟的编辑器,需要安装 Java。"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "需要下载 1.8 MB 的文件。"
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "这可能是由于您的系统中尚未安装 Java 造成的。"
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "调用您操作系统已关联到 .rpy 文件的编辑器。"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "禁止 Ren'Py 自动打开文本编辑器。"
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "启动编辑器时出现异常:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "选择编辑器"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "文本编辑器是指您用来编辑 Ren'Py 脚本的程序。在这里您可以选择 Ren'Py 要使用的编辑器。若您选择的编辑器并不存在,Ren'Py 将会自动下载并安装此编辑器。"
+
+    # editor.rpy:494
+    old "Cancel"
+    new "取消"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "打开 [text] 目录。"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "刷新"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ 创建新工程"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "启动工程"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "选择工程 [text]。"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "教程"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "活跃工程"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "打开目录"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "编辑文件"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "全部脚本文件"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "定位脚本"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "检查脚本并分析统计"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "更改主题"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "删除永久性数据"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "生成分发版"
+
+    # front_page.rpy:253
+    old "Android"
+    new "安卓"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "生成翻译文件"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "导出对话"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "正在检查脚本中的潜在问题……"
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "正在删除永久性数据……"
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "正在将全部的 rpy 文件重新编译至 rpyc 文件……"
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "工程名称"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "请输入新工程的名称:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "工程名不能为空。"
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] 已存在。请指定一个不同的工程名。"
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] 已存在。请指定一个不同的工程名。"
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "说明文档"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren'Py 官方网站"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Ren'Py 游戏列表"
+
+    # interface.rpy:117
+    old "update"
+    new "更新"
+
+    # interface.rpy:119
+    old "preferences"
+    new "设置"
+
+    # interface.rpy:120
+    old "quit"
+    new "退出"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "由于包格式限制,非 ASCII 文件名和目录名将不被允许。"
+
+    # interface.rpy:327
+    old "ERROR"
+    new "错误"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "在 [what!q] 时发生了一个错误:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "文本输入不得包含 {{ 或 [[ 字符。"
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "文件名或目录名不得包含 / 或 \\。"
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "文件名或目录名必须仅由 ASCII 字符组成,不能包含中文。"
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "正在处理"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "问题"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "选择"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "要生成 iOS 应用包,请下载 renios,并解压到 Ren'Py 目录中。之后重启 Ren'Py。"
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Xcode 工程所存放的目录尚未被指定。选择“指定目录”来指定。"
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "尚无与目前 Ren'Py 工程对应的 Xcode 工程。选择“创建 Xcode 工程”来进行创建。"
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "一个 Xcode 工程已经存在。选择“更新 Xcode 工程”来以最新的游戏文件更新,或使用 Xcode 来生成并安装。"
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "尝试模拟为 iPad。\n\n鼠标将仅在按键按下时模拟为触屏输入。"
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "尝试模拟为 iPad。\n\n鼠标将仅在按键按下时模拟为触屏输入。"
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "请指定即将放置 Xcode 工程的目录。"
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "创建与当前 Ren'Py 工程对应的 Xcode 工程。"
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "以最新的游戏文件更新 Xcode 工程。此操作应该在每次 Ren'Py 工程出现更改时执行一次。"
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "在 Xcode 中打开 Xcode 工程。"
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "打开包含 Xcode 工程的目录。"
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Xcode 工程已经存在。您希望重命名旧工程,并用新工程取代之吗?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS:[project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "指定 Xcode 工程目录"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "创建 Xcode 工程"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "更新 Xcode 工程"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "启动 Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "打开 Xcode 工程目录"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "在为 iOS 应用打包之前,您需要先下载 renios,即 Ren'Py iOS 支持套件。您希望现在就开始下载 renios 吗?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE 工程目录"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "请使用弹出的目录选择窗口来指定 Xcode 工程目录。\n{b}目录选择窗口可能因未取得焦点而被本窗口覆盖。{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py 已将 Xcode 工程目录设置为:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "定位:[project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "排序方式:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "字母"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "按文件分类"
+
+    # navigation.rpy:182
+    old "natural"
+    new "出现顺序"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "类别:"
+
+    # navigation.rpy:196
+    old "files"
+    new "文件"
+
+    # navigation.rpy:197
+    old "labels"
+    new "标签"
+
+    # navigation.rpy:198
+    old "defines"
+    new "定义"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "变换"
+
+    # navigation.rpy:200
+    old "screens"
+    new "屏幕"
+
+    # navigation.rpy:201
+    old "callables"
+    new "可调用"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "待办事项"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ 添加脚本文件"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "目前尚无待办事项。将“# TODO”包含到脚本中即可创建。"
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "列表为空。"
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "工程目录尚未被设定。取消操作。"
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "指定工程模板"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "请指定一个新工程要使用的模板。模板已预先设置了默认字体和用户界面语言。如果您的语言暂未支持,请选择“英语”。"
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "启动器设置"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "工程目录:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "工程目录:[text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "未设置"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "文本编辑器:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "文本编辑器:[text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "更新通道:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "定位选项:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "包含私有名称"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "包含库名称"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "启动器选项:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "硬件渲染"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "显示模板"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "显示编辑文件部件"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "大字体"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "控制台输出"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "打开启动器工程"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "语言:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "在对脚本进行更改之后,按 Shift+R 来重新载入游戏。"
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "按 Shift+O(字母 O)来打开控制台。"
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "按 Shift+D 打开开发者菜单。"
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "您最近备份过您的工程吗?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "启动工程失败。"
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "在执行此命令之前,请确保您的工程可正常运行。"
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py 正在扫描工程……"
+
+    # project.rpy:568
+    old "Launching"
+    new "启动中"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "工程目录"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "请使用弹出的目录选择窗口来指定工程目录。\n{b}目录选择窗口可能因未取得焦点而被本窗口覆盖。{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "该启动器将会在此目录里扫描工程、创建新工程以及将生成的工程放置在此。"
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py 已将工程目录设置为:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "为翻译生成空字串"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py 正在生成翻译文件……"
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py 已完成 [language] 翻译文件的生成。"
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py 正在导出对话……"
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "指定更新通道"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "更新通道会影响更新器所下载的 Ren'Py 版本。请指定更新通道:"
+
+    # updater.rpy:91
+    old "Release"
+    new "发布版"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}建议使用。{/b}此版本的 Ren'Py 应使用在新发布的游戏上。"
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "预发布版"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Ren'Py 下个版本的预览版,可以用来测试和体验新功能,但不应该作为游戏的最终发布版本。"
+
+    # updater.rpy:114
+    old "Experimental"
+    new "试验版"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Ren'Py 的试验版。除非应 Ren'Py 开发者的要求,否则您不应选择这个通道。"
+
+    # updater.rpy:126
+    old "Nightly"
+    new "每夜版"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Ren'Py 的尖端开发版。这个版本可能包含最新的功能,也可能甚至根本无法运行。"
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "发生错误:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "正在检查更新:"
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py 已更新到最新版本。"
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] 现已可用。您希望现在安装吗?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "正在准备下载更新。"
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "正在下载更新。"
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "正在解压更新。"
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "完成。"
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "更新已安装。Ren'Py 即将重启。"
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "更新已安装。"
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "更新已取消。"
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ren'Py 更新"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "继续"
+
diff --git a/launcher/game/tl/simplified_chinese/navigation.rpy b/launcher/game/tl/simplified_chinese/navigation.rpy
deleted file mode 100644
index 66713f7..0000000
--- a/launcher/game/tl/simplified_chinese/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "定位:[project.current.name]"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "排序方式:"
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "字母"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "按文件分类"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "出现顺序"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "类别:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "文件"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "标签"
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "定义"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "变换"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "屏幕"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "可调用"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "待办事项"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ 添加脚本文件"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "目前尚无待办事项。将“# TODO”包含到脚本中即可创建。"
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "列表为空。"
-
diff --git a/launcher/game/tl/simplified_chinese/new_project.rpy b/launcher/game/tl/simplified_chinese/new_project.rpy
deleted file mode 100644
index 7552720..0000000
--- a/launcher/game/tl/simplified_chinese/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "指定工程模板"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "请指定一个新工程要使用的模板。模板已预先设置了默认字体和用户界面语言。如果您的语言暂未支持,请选择“英语”。"
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "工程目录尚未被设定。取消操作。"
-
-    # game/new_project.rpy:75
-    old "PROJECT NAME"
-    new "工程名称"
-
-    # game/new_project.rpy:75
-    old "Please enter the name of your project:"
-    new "请输入新工程的名称:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "工程名不能为空。"
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] 已存在。请指定一个不同的工程名。"
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] 已存在。请指定一个不同的工程名。"
-
diff --git a/launcher/game/tl/simplified_chinese/obsolete.rpy b/launcher/game/tl/simplified_chinese/obsolete.rpy
new file mode 100644
index 0000000..b585734
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate simplified_chinese strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "手柄映射"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "空存档位"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "上一页"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "下一页"
+
diff --git a/launcher/game/tl/simplified_chinese/options.rpy b/launcher/game/tl/simplified_chinese/options.rpy
new file mode 100644
index 0000000..5b16052
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/options.rpy
@@ -0,0 +1,195 @@
+
+translate simplified_chinese strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/simplified_chinese/preferences.rpy b/launcher/game/tl/simplified_chinese/preferences.rpy
deleted file mode 100644
index 073c2b9..0000000
--- a/launcher/game/tl/simplified_chinese/preferences.rpy
+++ /dev/null
@@ -1,79 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/preferences.rpy:64
-    old "Launcher Preferences"
-    new "启动器设置"
-
-    # game/preferences.rpy:85
-    old "Projects Directory:"
-    new "工程目录:"
-
-    # game/preferences.rpy:94
-    old "Projects directory: [text]"
-    new "工程目录:[text]"
-
-    # game/preferences.rpy:96
-    old "Not Set"
-    new "未设置"
-
-    # game/preferences.rpy:111
-    old "Text Editor:"
-    new "文本编辑器:"
-
-    # game/preferences.rpy:117
-    old "Text editor: [text]"
-    new "文本编辑器:[text]"
-
-    # game/preferences.rpy:133
-    old "Update Channel:"
-    new "更新通道:"
-
-    # game/preferences.rpy:153
-    old "Navigation Options:"
-    new "定位选项:"
-
-    # game/preferences.rpy:157
-    old "Include private names"
-    new "包含私有名称"
-
-    # game/preferences.rpy:158
-    old "Include library names"
-    new "包含库名称"
-
-    # game/preferences.rpy:168
-    old "Launcher Options:"
-    new "启动器选项:"
-
-    # game/preferences.rpy:172
-    old "Hardware rendering"
-    new "硬件渲染"
-
-    # game/preferences.rpy:173
-    old "Show templates"
-    new "显示模板"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "显示编辑文件部件"
-
-    # game/preferences.rpy:175
-    old "Large fonts"
-    new "大字体"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "为翻译生成空字串"
-
-    # game/preferences.rpy:179
-    old "Console output"
-    new "控制台输出"
-
-    # game/preferences.rpy:200
-    old "Open launcher project"
-    new "打开启动器工程"
-
-    # game/preferences.rpy:214
-    old "Language:"
-    new "语言:"
-
diff --git a/launcher/game/tl/simplified_chinese/project.rpy b/launcher/game/tl/simplified_chinese/project.rpy
deleted file mode 100644
index cd9ccb9..0000000
--- a/launcher/game/tl/simplified_chinese/project.rpy
+++ /dev/null
@@ -1,51 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/project.rpy:47
-    old "After making changes to the script, press shift+R to reload your game."
-    new "在对脚本进行更改之后,按 Shift+R 来重新载入游戏。"
-
-    # game/project.rpy:47
-    old "Press shift+O (the letter) to access the console."
-    new "按 Shift+O(字母 O)来打开控制台。"
-
-    # game/project.rpy:47
-    old "Press shift+D to access the developer menu."
-    new "按 Shift+D 打开开发者菜单。"
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "您最近备份过您的工程吗?"
-
-    # game/project.rpy:224
-    old "Launching the project failed."
-    new "启动工程失败。"
-
-    # game/project.rpy:224
-    old "Please ensure that your project launches normally before running this command."
-    new "在执行此命令之前,请确保您的工程可正常运行。"
-
-    # game/project.rpy:237
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py 正在扫描工程……"
-
-    # game/project.rpy:526
-    old "Launching"
-    new "启动中"
-
-    # game/project.rpy:555
-    old "PROJECTS DIRECTORY"
-    new "工程目录"
-
-    # game/project.rpy:555
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "请使用弹出的目录选择窗口来指定工程目录。\n{b}目录选择窗口可能因未取得焦点而被本窗口覆盖。{/b}"
-
-    # game/project.rpy:555
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "该启动器将会在此目录里扫描工程、创建新工程以及将生成的工程放置在此。"
-
-    # game/project.rpy:560
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py 已将工程目录设置为:"
-
diff --git a/launcher/game/tl/simplified_chinese/screens.rpy b/launcher/game/tl/simplified_chinese/screens.rpy
new file mode 100644
index 0000000..48b2646
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/screens.rpy
@@ -0,0 +1,643 @@
+
+translate simplified_chinese strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "返回"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "快进模式"
+
+    # screens.rpy:264
+    old "Auto"
+    new "自动"
+
+    # screens.rpy:265
+    old "Save"
+    new "储存"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.储存"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.读取"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "设定"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "环境设定"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "标题画面"
+
+    # screens.rpy:328
+    old "About"
+    new "关于"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "帮助文档"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "退出游戏"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "返回"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "显示模式"
+
+    # screens.rpy:739
+    old "Window"
+    new "窗口"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "全屏幕"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "选项后"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "转场特效"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "文字显示速度"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "自动模式等待时间"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "音乐音量"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "音效音量"
+
+    # screens.rpy:791
+    old "Test"
+    new "测试"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "语音音量"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "是"
+
+    # screens.rpy:1162
+    old "No"
+    new "否"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/simplified_chinese/script.rpym b/launcher/game/tl/simplified_chinese/script.rpym
new file mode 100644
index 0000000..732c28d
--- /dev/null
+++ b/launcher/game/tl/simplified_chinese/script.rpym
@@ -0,0 +1,37 @@
+# 您可以在此编写游戏的脚本。
+
+# 下方的image命令可用于定义一个图像。
+# 例:image eileen happy = "eileen_happy.png"
+
+# 下方的define命令可定义游戏中出现的角色名称与对应文本颜色。
+# 译注:define还可以定义很多功能,具体请参阅官方文档。
+define e = Character('Eileen', color="#c8ffc8")
+
+# 引用游戏OP视频,在进入程序主菜单显示前自动播放。
+# 此处也可以使用图片代替。
+# label splashscreen:
+    # $ renpy.movie_cutscene('data/op.avi')
+    # return
+
+# 游戏从这里开始。
+label start:
+
+# 下面的参数用于设定是否允许用户通过点击或快进功能跳过转场特效。
+# $ _skipping = True
+
+# 是否允许用户通过点击或快进跳过暂停时间。
+# 暂停时间是通过pause命令实现的,具体请参阅官方文档。
+# $ _dismiss_pause = True
+
+# 译注:以上两个命令都是出现后生效,并且有跨label继承性,
+# 通常我们设置为True以保证用户能够使用快进,
+# 但如果您在特殊情况下设置为False后,应在合适的地方重新
+# 调整为True,以便用户能够正常进行游戏。
+# 此功能包含在最新的每夜版SDK中,当您发现正式版SDK不兼容此命令时,
+# 请将SDK的更新通道设置为每夜版,并进行更新。
+
+    e "您已经创建了一个新的Ren'py游戏。"
+
+    e "当您给您的游戏加入了故事剧情,图片和音乐,您就能将它与世界分享了。"
+
+    return
diff --git a/launcher/game/tl/simplified_chinese/style.rpy b/launcher/game/tl/simplified_chinese/style.rpy
index 79a84c4..88cca48 100644
--- a/launcher/game/tl/simplified_chinese/style.rpy
+++ b/launcher/game/tl/simplified_chinese/style.rpy
@@ -1,35 +1,5 @@
-translate simplified_chinese python:
-    CNL = "tl/simplified_chinese/DroidSansFallback.ttf"
-
-translate simplified_chinese style l_default:
-    font CNL
-    line_leading 1.5
-    line_spacing 1.5
-    #size 16
-
-translate simplified_chinese style l_button_text:
-    selected_font CNL
-    selected_bold True
-
-translate simplified_chinese style l_link_text:
-    font CNL
-
-translate simplified_chinese style l_alternate_text:
-    font CNL
-
-translate simplified_chinese style l_navigation_button_text:
-    font CNL
-    bold True
-
-translate simplified_chinese style l_navigation_text:
-    font CNL
-
-translate simplified_chinese style l_checkbox_text:
-    selected_font CNL
-
-translate simplified_chinese style l_nonbox_text:
-    selected_font CNL
-
-translate simplified_chinese style hyperlink_text:
-    font CNL
+init python:
+    translate_font("simplified_chinese", "DroidSansFallback.ttf")
 
+translate simplified_chinese python:
+    gui.FONT_SCALE = .9
diff --git a/launcher/game/tl/simplified_chinese/translations.rpy b/launcher/game/tl/simplified_chinese/translations.rpy
deleted file mode 100644
index eb37a52..0000000
--- a/launcher/game/tl/simplified_chinese/translations.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/translations.rpy:34
-    old "Create or Update Translations"
-    new "创建或更新翻译"
-
-    # game/translations.rpy:34
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "请输入您想要创建或更新的语言名称。"
-
-    # game/translations.rpy:39
-    old "The language name can not be the empty string."
-    new "语言名称不能为空字串。"
-
-    # game/translations.rpy:50
-    old "Ren'Py is generating translations...."
-    new "Ren'Py 正在生成翻译文件……"
-
-    # game/translations.rpy:54
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py 已完成 [language] 翻译文件的生成。"
-
-    # game/translations.rpy:67
-    old "What format would you like for the extracted dialogue?"
-    new "您想要以哪种格式来导出对话?"
-
-    # game/translations.rpy:80
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py 正在导出对话……"
-
-    # game/translations.rpy:84
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py 已完成导出对话。已导出的对话可在基础路径的 dialogue.[format] 中查看。"
-
diff --git a/launcher/game/tl/simplified_chinese/updater.rpy b/launcher/game/tl/simplified_chinese/updater.rpy
deleted file mode 100644
index 2af40e9..0000000
--- a/launcher/game/tl/simplified_chinese/updater.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-
-translate simplified_chinese strings:
-
-    # game/updater.rpy:78
-    old "Select Update Channel"
-    new "指定更新通道"
-
-    # game/updater.rpy:89
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "更新通道会影响更新器所下载的 Ren'Py 版本。请指定更新通道:"
-
-    # game/updater.rpy:94
-    old "Release"
-    new "发布版"
-
-    # game/updater.rpy:100
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}建议使用。{/b}此版本的 Ren'Py 应使用在新发布的游戏上。"
-
-    # game/updater.rpy:105
-    old "Prerelease"
-    new "预发布版"
-
-    # game/updater.rpy:111
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Ren'Py 下个版本的预览版,可以用来测试和体验新功能,但不应该作为游戏的最终发布版本。"
-
-    # game/updater.rpy:117
-    old "Experimental"
-    new "试验版"
-
-    # game/updater.rpy:123
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Ren'Py 的试验版。除非应 Ren'Py 开发者的要求,否则您不应选择这个通道。"
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "每夜版"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Ren'Py 的尖端开发版。这个版本可能包含最新的功能,也可能甚至根本无法运行。"
-
-    # game/updater.rpy:155
-    old "An error has occured:"
-    new "发生错误:"
-
-    # game/updater.rpy:157
-    old "Checking for updates."
-    new "正在检查更新:"
-
-    # game/updater.rpy:159
-    old "Ren'Py is up to date."
-    new "Ren'Py 已更新到最新版本。"
-
-    # game/updater.rpy:161
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] 现已可用。您希望现在安装吗?"
-
-    # game/updater.rpy:163
-    old "Preparing to download the update."
-    new "正在准备下载更新。"
-
-    # game/updater.rpy:165
-    old "Downloading the update."
-    new "正在下载更新。"
-
-    # game/updater.rpy:167
-    old "Unpacking the update."
-    new "正在解压更新。"
-
-    # game/updater.rpy:169
-    old "Finishing up."
-    new "完成。"
-
-    # game/updater.rpy:171
-    old "The update has been installed. Ren'Py will restart."
-    new "更新已安装。Ren'Py 即将重启。"
-
-    # game/updater.rpy:173
-    old "The update has been installed."
-    new "更新已安装。"
-
-    # game/updater.rpy:175
-    old "The update was cancelled."
-    new "更新已取消。"
-
-    # game/updater.rpy:192
-    old "Ren'Py Update"
-    new "Ren'Py 更新"
-
-    # game/updater.rpy:198
-    old "Proceed"
-    new "继续"
-
diff --git a/launcher/game/tl/spanish/about.rpy b/launcher/game/tl/spanish/about.rpy
deleted file mode 100644
index 7766853..0000000
--- a/launcher/game/tl/spanish/about.rpy
+++ /dev/null
@@ -1,9 +0,0 @@
-translate spanish strings:
-
-    # game/about.rpy:21
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:25
-    old "View license"
-    new "Ver licencia"
diff --git a/launcher/game/tl/spanish/add_file.rpy b/launcher/game/tl/spanish/add_file.rpy
deleted file mode 100644
index 0ab03b8..0000000
--- a/launcher/game/tl/spanish/add_file.rpy
+++ /dev/null
@@ -1,21 +0,0 @@
-translate spanish strings:
-
-    # game/add_file.rpy:7
-    old "FILENAME"
-    new "Nombre del archivo"
-
-    # game/add_file.rpy:7
-    old "Enter the name of the script file to create."
-    new "Introduce el nombre del archivo de script para crearlo."
-
-    # game/add_file.rpy:10
-    old "The filename must have the .rpy extension."
-    new "El nombre del archivo debe tener la extensión .rpy."
-
-    # game/add_file.rpy:18
-    old "The file already exists."
-    new "El archivo ya existe."
-
-    # game/add_file.rpy:21
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py carga automaticamente todos los archivos que terminan en .rpy. Para usar este\n# archivo, defina una etiqueta y salte a el desde otro archivo\n"
diff --git a/launcher/game/tl/spanish/android.rpy b/launcher/game/tl/spanish/android.rpy
deleted file mode 100644
index 024a3e4..0000000
--- a/launcher/game/tl/spanish/android.rpy
+++ /dev/null
@@ -1,174 +0,0 @@
-translate spanish strings:
-
-    # game/android.rpy:12
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Para construir un paquete para Android, por favor descarga RAPT, descomprimelo y colocalo dentro de la carpeta de Ren'Py. Despues reinicia el launcher de Ren'Py."
-
-    # game/android.rpy:13
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Se necesita Java Development Kit de 32-bit para construir paquetes de Android en Windows. El JDK es diferente al JRE, es posible que tenga Java sin tener el JDK.\n\nPor favor {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}descarga e instala el JDK{/a}, después, reinicia Ren'Py."
-
-    # game/android.rpy:14
-    old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Para construir paquetes de Android, por favor descarga RAPT (desde {a=http://www.renpy.org/dl/android}aquí{/a}), descomprímelo y cópialo dentro de la carpeta de Ren'Py. Después reinicia el launcher de Ren'Py."
-
-    # game/android.rpy:15
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT está instalado, pero tendrás que instalar el SDK de Android para poder construir paquetes de Android. Selecciona instalar SDK para instalarlo."
-
-    # game/android.rpy:16
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT está instalado, pero la clave aun no se ha configurado. Por favor crea una nueva clave, o restaura android.keystore."
-
-    # game/android.rpy:17
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "El proyecto actual no se ha configurado. Usa \"Configurar\" para configurarlo antes de construirlo."
-
-    # game/android.rpy:18
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Selecciona \"Construir\" para construir el proyecto actual, o conecta un dispositivo Android y selecciona \"Construir & instalar\" para construirlo e instalarlo en el dispositivo."
-
-    # game/android.rpy:20
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Al intentar emular un teléfono Android. \n\nLa entrada táctil se emula mediante el ratón, pero sólo cuando el botón se mantiene pulsado. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
-
-    # game/android.rpy:21
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Al intentar emular una tablet Android. \n\nLa entrada táctil se emula mediante el ratón, pero sólo cuando el botón se mantiene pulsado. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
-
-    # game/android.rpy:22
-    old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Al intentar emular una consola OUYA. \n\nPara el control se usan las flechas, Intro está asignado al botón select. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
-
-    # game/android.rpy:23
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Descarga e instala el SDK de android y los paquetes de soporte. Opcionalmente, genera la clave necesaria para firmar el paquete."
-
-    # game/android.rpy:24
-    old "Configures the package name, version, and other information about this project."
-    new "Configura el nombre del paquete, la versión, y otra información de este proyecto."
-
-    # game/android.rpy:25
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Abre el archivo que contiene las claves de Google Play en el editor. \n\nEsto sólo es necesario si la aplicación usa una expansión APK. Para más información lee la documentación."
-
-    # game/android.rpy:26
-    old "Builds the Android package."
-    new "Construir el paquete de Android."
-
-    # game/android.rpy:27
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Construye el paquete de Android, e instálalo en un dispositivo Android connectado a tu ordenador."
-
-    # game/android.rpy:148
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
-    # game/android.rpy:157
-    old "QUESTION"
-    new "PREGUNTA"
-
-    # game/android.rpy:367
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:387
-    old "Emulation:"
-    new "Emulación:"
-
-    # game/android.rpy:395
-    old "Phone"
-    new "Teléfono"
-
-    # game/android.rpy:399
-    old "Tablet"
-    new "Tablet"
-
-    # game/android.rpy:403
-    old "Television / OUYA"
-    new "Televisión / OUYA"
-
-    # game/android.rpy:415
-    old "Build:"
-    new "Construir:"
-
-    # game/android.rpy:423
-    old "Install SDK & Create Keys"
-    new "Instalar SDK y Crear claves"
-
-    # game/android.rpy:427
-    old "Configure"
-    new "Configurar"
-
-    # game/android.rpy:431
-    old "Build Package"
-    new "Construir Paquete"
-
-    # game/android.rpy:435
-    old "Build & Install"
-    new "Construir & Instalar"
-
-    # game/android.rpy:486
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Antes de empaquetar apps para Android, vas a necesitar descargar RAPT, Ren'Py Android Packaging Tool. ¿Quieres descargar RAPT ahora?"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Al intentar emular una consola Android basada en televisión, como OUYA o Fire TV.\n\nPara el control se usan las flechas, Intro está asignado al botón select. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
-
-    # game/android.rpy:47
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Conectar a un dispositivo Android ejecutando ADB en modo TCP/IP."
-
-    # game/android.rpy:48
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Desconectar de un dispositivo Android corriendo ADB en modo TCP/IP."
-
-    # game/android.rpy:516
-    old "Other:"
-    new "Otros:"
-
-    # game/android.rpy:524
-    old "Remote ADB Connect"
-    new "Conexión remota ADB"
-
-    # game/android.rpy:528
-    old "Remote ADB Disconnect"
-    new "Desconexión remota ADB"
-
-    # game/android.rpy:608
-    old "Remote ADB Address"
-    new "Dirección remota ADB"
-
-    # game/android.rpy:609
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Por favor introduce la dirección IP y el número de puerto para conectarte, con el formato \"192.168.1.143:5555\". Consulta la documentación de tu dispositivo para averiguar si es compatible con ADB remoto, y si es así, la dirección y el puerto a utilizar."
-
-    # game/android.rpy:619
-    old "Invalid remote ADB address"
-    new "Dirección remota ADB no válida"
-
-    # game/android.rpy:619
-    old "The address must contain one exactly one ':'."
-    new "La dirección debe contener exactamente un ':'."
-
-    # game/android.rpy:623
-    old "The host may not contain whitespace."
-    new "El host no puede contener espacios en blanco."
-
-    # game/android.rpy:629
-    old "The port must be a number."
-    new "El puerto debe ser un número."
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Construye un paquete para Android, lo instala en un dispositivo conectado a su ordenador, y luego ejecuta la aplicación en su dispositivo."
-
-    # game/android.rpy:290
-    old "Television"
-    new "Televisión"
-
-    # game/android.rpy:326
-    old "Build, Install & Launch"
-    new "Construir, instalar & Ejecutar"
-
diff --git a/launcher/game/tl/spanish/choose_directory.rpy b/launcher/game/tl/spanish/choose_directory.rpy
deleted file mode 100644
index 1f097c0..0000000
--- a/launcher/game/tl/spanish/choose_directory.rpy
+++ /dev/null
@@ -1,6 +0,0 @@
-translate spanish strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py fue incapaz de ejecutar python con tkinter para elegir el directorio. Por favor instale el paquete python-tk o tkinter."
-
diff --git a/launcher/game/tl/spanish/choose_theme.rpy b/launcher/game/tl/spanish/choose_theme.rpy
deleted file mode 100644
index 2396955..0000000
--- a/launcher/game/tl/spanish/choose_theme.rpy
+++ /dev/null
@@ -1,37 +0,0 @@
-translate spanish strings:
-
-    # game/choose_theme.rpy:274
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "No se puede cambiar el tema. Quizás options.rpy ha sufrido muchos cambios."
-
-    # game/choose_theme.rpy:332
-    old "Display"
-    new "Display"
-
-    # game/choose_theme.rpy:333
-    old "Window"
-    new "Window"
-
-    # game/choose_theme.rpy:334
-    old "Fullscreen"
-    new "Fullscreen"
-
-    # game/choose_theme.rpy:335
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:342
-    old "Sound Volume"
-    new "Sound Volume"
-
-    # game/choose_theme.rpy:376
-    old "Choose Theme"
-    new "Elegir Tema"
-
-    # game/choose_theme.rpy:389
-    old "Theme"
-    new "Tema"
-
-    # game/choose_theme.rpy:413
-    old "Color Scheme"
-    new "Combinación de colores"
diff --git a/launcher/game/tl/spanish/common.rpy b/launcher/game/tl/spanish/common.rpy
index 16c3ea8..24d7b57 100644
--- a/launcher/game/tl/spanish/common.rpy
+++ b/launcher/game/tl/spanish/common.rpy
@@ -1,555 +1,335 @@
-#translation: renpy/common/00action_file.rpy
+
 translate spanish strings:
 
-    # renpy/common/00action_file.rpy:124
-    old "%b %d, %H:%M"
-    new "%d %b, %H:%M"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "Lunes"
 
-    # renpy/common/00action_file.rpy:587
-    old "Quick save complete."
-    new "Guardado rápido completado"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "Martes"
 
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "Miércoles"
 
-#translation: renpy/common/00gallery.rpy
-translate spanish strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "Jueves"
 
-    # renpy/common/00gallery.rpy:521
-    old "Image [index] of [count] locked."
-    new "Imagen [index] de [count] bloqueada."
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "Viernes"
 
-    # renpy/common/00gallery.rpy:539
-    old "prev"
-    new "prev"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "Sábado"
 
-    # renpy/common/00gallery.rpy:540
-    old "next"
-    new "siguiente"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "Domingo"
 
-    # renpy/common/00gallery.rpy:541
-    old "slideshow"
-    new "presentación"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "Lun."
 
-    # renpy/common/00gallery.rpy:542
-    old "return"
-    new "volver"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "Mar."
 
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "Mié."
 
-#translation: renpy/common/00gltest.rpy
-translate spanish strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "Jue."
 
-    # renpy/common/00gltest.rpy:50
-    old "Graphics Acceleration"
-    new "Aceleración Gráfica"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "Vie."
 
-    # renpy/common/00gltest.rpy:54
-    old "Automatically Choose"
-    new "Seleccionar automaticamente"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "Sab."
 
-    # renpy/common/00gltest.rpy:59
-    old "Force Angle/DirectX Renderer"
-    new "Forzar Angle/DirectX Renderer"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "Dom."
 
-    # renpy/common/00gltest.rpy:63
-    old "Force OpenGL Renderer"
-    new "Forzar OpenGL Renderer"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "Enero"
 
-    # renpy/common/00gltest.rpy:67
-    old "Force Software Renderer"
-    new "Forzar renderización por software"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "Febrero"
 
-    # renpy/common/00gltest.rpy:73
-    old "Changes will take effect the next time this program is run."
-    new "Los cambios tendrán efecto la próxima vez que este programa se ejecute."
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "Marzo"
 
-    # renpy/common/00gltest.rpy:77
-    old "Quit"
-    new "Salir"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "Abril"
 
-    # renpy/common/00gltest.rpy:82
-    old "Return"
-    new "Volver"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "Mayo"
 
-    # renpy/common/00gltest.rpy:112
-    old "Performance Warning"
-    new "Advertencia de rendimiento"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "Junio"
 
-    # renpy/common/00gltest.rpy:117
-    old "This computer is using software rendering."
-    new "Este equipo usa renderización por software."
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "Julio"
 
-    # renpy/common/00gltest.rpy:119
-    old "This computer is not using shaders."
-    new "Este equipo no utiliza shaders."
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "Agosto"
 
-    # renpy/common/00gltest.rpy:121
-    old "This computer is displaying graphics slowly."
-    new "Este equipo está mostrando gráficos lentamente."
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "Septiembre"
 
-    # renpy/common/00gltest.rpy:123
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Este equipo tiene un problema monstrando gráficos: [problem]."
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "Octubre"
 
-    # renpy/common/00gltest.rpy:128
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Sus drivers gráficos pueden estar desactualizados o no funcionar correctamente. Esto puede ocasionar visualización de gráficos lenta o incorrecta. Actualizar DirectX podría solucionar este problema."
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "Noviembre"
 
-    # renpy/common/00gltest.rpy:130
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Sus drivers gráficos pueden estar desactualizados o no funcionar correctamente. Esto puede ocasionar visualización de gráficos lenta o incorrecta."
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "Diciembre"
 
-    # renpy/common/00gltest.rpy:135
-    old "Update DirectX"
-    new "Actualizar DirectX"
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "Ene."
 
-    # renpy/common/00gltest.rpy:141
-    old "Continue, Show this warning again"
-    new "Continuar, Mostrar este aviso otra vez"
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "Feb."
 
-    # renpy/common/00gltest.rpy:145
-    old "Continue, Don't show warning again"
-    new "Continuar, No mostrar este aviso otra vezn"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "Mar."
 
-    # renpy/common/00gltest.rpy:171
-    old "Updating DirectX."
-    new "Actualizando DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "Abr."
 
-    # renpy/common/00gltest.rpy:175
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "Se ha iniciado DirectX web setup. Puede inciiar minimizado en la barra de tareas. Por favor siga las instrucciones para instalar DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "May."
 
-    # renpy/common/00gltest.rpy:179
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}Nota:{/b} Programa de instalación web de Microsoft DirectX, por defecto, instala la barra de herramientas de Bing. Si no quieres que se instale, desactiva la casilla correspondiente."
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "Jun."
 
-    # renpy/common/00gltest.rpy:183
-    old "When setup finishes, please click below to restart this program."
-    new "Cuando finalize la configuración, por favor haga click abajo para reiniciar el programa."
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "Jul."
 
-    # renpy/common/00gltest.rpy:185
-    old "Restart"
-    new "Reiniciar"
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "Ago."
 
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "Sep."
 
-#translation: renpy/common/00keymap.rpy
-translate spanish strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "Oct."
 
-    # renpy/common/00keymap.rpy:168
-    old "Saved screenshot as %s."
-    new "Screenshot guardada como %s."
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "Nov."
 
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "Dic."
 
-#translation: renpy/common/00layout.rpy
-translate spanish strings:
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%d %b, %H:%M"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Grabar rápido completo."
 
-    # renpy/common/00layout.rpy:421
+    # 00gui.rpy:227
     old "Are you sure?"
-    new "¿Estás seguro?"
+    new "¿Seguro?"
 
-    # renpy/common/00layout.rpy:422
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
-    new "¿Seguro que quieres eliminar esta partida guardada?"
+    new "¿Seguro que quieres borrar esta partida?"
 
-    # renpy/common/00layout.rpy:423
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
-    new "¿Seguro que quieres sobreescribir esta partida guardada?"
+    new "¿Seguro que quieres sobreescribir esta partida?"
 
-    # renpy/common/00layout.rpy:424
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
-    new "Cargando, perderas el progreso no guardado. \n¿Seguro que quieres hacer esto?"
+    new "Al cargar se perderá el progreso no guardado.\n¿Seguro que quieres hacer esto?"
 
-    # renpy/common/00layout.rpy:425
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "¿Seguro que quieres salir?"
 
-    # renpy/common/00layout.rpy:426
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
-    new "Seguro que quieres volver al menu principal?\nPerderas el progreso no guardado."
+    new "¿Seguro que quieres volver al menú principal?\nSe perderá el progreso no guardado."
 
-    # renpy/common/00layout.rpy:427
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "¿Seguro que quieres finalizar la repetición?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
-    new "Seguro que quieres comenzar a omitir?"
+    new "¿Seguro que quieres empezar el modo salto?"
 
-    # renpy/common/00layout.rpy:428
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
-    new "¿Seguro que quieres saltarte la siguiente eleccion?"
-
-    # renpy/common/00layout.rpy:429
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "¿Seugro que quieres saltarte los diálogos no vistos o la sigueinte elección?"
-
-
-#translation: renpy/common/00library.rpy
-translate spanish strings:
-
-    # renpy/common/00library.rpy:77
-    old "Skip Mode"
-    new "Modo Salto"
-
-    # renpy/common/00library.rpy:80
-    old "Fast Skip Mode"
-    new "Modo de salto rápido"
-
-
-#translation: renpy/common/00updater.rpy
-translate spanish strings:
-
-    # renpy/common/00updater.rpy:1258
-    old "Updater"
-    new "Actualizador"
-
-    # renpy/common/00updater.rpy:1267
-    old "This program is up to date."
-    new "Este programa está actualizado."
+    new "¿Seguro que quieres saltar hasta la próxima elección?"
 
-    # renpy/common/00updater.rpy:1269
-    old "[u.version] is available. Do you want to install it?"
-    new "[u.version] está disponible. ¿Quieres instalarla?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "¿Seguro que quieres saltar el texto no visto hasta la próxima elección?"
 
-    # renpy/common/00updater.rpy:1271
-    old "Preparing to download the updates."
-    new "Preparando para descargar las actualizaciones."
-
-    # renpy/common/00updater.rpy:1273
-    old "Downloading the updates."
-    new "Descargando actualizaciones."
-
-    # renpy/common/00updater.rpy:1275
-    old "Unpacking the updates."
-    new "Desempaquetando las actualizaciones."
-
-    # renpy/common/00updater.rpy:1279
-    old "The updates have been installed. The program will restart."
-    new "Se han instalado las actualizaciones. El programa se reiniciará."
-
-    # renpy/common/00updater.rpy:1281
-    old "The updates have been installed."
-    new "se han instalado las actualizaciones."
-
-    # renpy/common/00updater.rpy:1283
-    old "The updates were cancelled."
-    new "Se han cancelado las actualizaciones."
-
-
-#translation: renpy/common/_compat/gamemenu.rpym
-translate spanish strings:
-
-    # renpy/common/_compat/gamemenu.rpym:180
-    old "Empty Slot."
-    new "Ranura vacía."
-
-    # renpy/common/_compat/gamemenu.rpym:337
-    old "Previous"
-    new "Anterior"
-
-    # renpy/common/_compat/gamemenu.rpym:344
-    old "Next"
-    new "Siguiente"
-
-
-#translation: renpy/common/_compat/preferences.rpym
-translate spanish strings:
-
-    # renpy/common/_compat/preferences.rpym:411
-    old "Joystick Mapping"
-    new "Asignar Joystick"
-
-
-#translation: renpy/common/_errorhandling.rpym
-translate spanish strings:
-
-    # renpy/common/_errorhandling.rpym:408
-    old "An exception has occurred."
-    new "Se ha producido una excepción."
-
-    # renpy/common/_errorhandling.rpym:434
-    old "Rollback"
-    new "Regresar"
-
-    # renpy/common/_errorhandling.rpym:436
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Intente volver atŕas, le permitirá guardar o elegir una opción diferente."
-
-    # renpy/common/_errorhandling.rpym:439
-    old "Ignore"
-    new "Ignorar"
-
-    # renpy/common/_errorhandling.rpym:441
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Ignora la excepción, le permite continuar. Esto suele conducir a errores adicionales."
-
-    # renpy/common/_errorhandling.rpym:444
-    old "Reload"
-    new "recargar"
-
-    # renpy/common/_errorhandling.rpym:446
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Vuelve a cargar el juego desde el disco. guarda y restaura el estado del juego si es posible."
-
-    # renpy/common/_errorhandling.rpym:448
-    old "Open Traceback"
-    new "Abrir Traceback"
-
-    # renpy/common/_errorhandling.rpym:450
-    old "Opens the traceback.txt file in a text editor."
-    new "Abrir el archivo traceback.txt en un editor de texto."
-
-    # renpy/common/_errorhandling.rpym:456
-    old "Quits the game."
-    new "Salir del juego."
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Parsing the script failed."
-    new "Analizando el script fallido."
-
-    # renpy/common/_errorhandling.rpym:510
-    old "Open Parse Errors"
-    new "Abrir Analisis de Errores"
-
-    # renpy/common/_errorhandling.rpym:512
-    old "Opens the errors.txt file in a text editor."
-    new "Abre el archivo errors.txt en un editor de texto."
-
-
-#translation: renpy/common/_layout/classic_load_save.rpym
-translate spanish strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:152
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:161
-    old "q"
-    new "q"
-
-    # renpy/common/_developer/inspector.rpym:25
-    old "Displayable Inspector"
-    new "Displayable Inspector"
-
-    # renpy/common/_developer/inspector.rpym:31
-    old "Nothing to inspect."
-    new "Nada para inspeccionar."
-
-    # renpy/common/_developer/inspector.rpym:40
-    old "Size"
-    new "Tamaño"
-
-    # renpy/common/_developer/inspector.rpym:45
-    old "Style"
-    new "Estilo"
-
-    # renpy/common/_developer/inspector.rpym:105
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Inspeccionando estilos de [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:117
-    old "displayable:"
-    new "visualizable:"
-
-    # renpy/common/_developer/inspector.rpym:124
-    old "        (no properties affect the displayable)"
-    new "        (no hay propiedades que afecten la visualización)"
-
-    # renpy/common/_developer/inspector.rpym:126
-    old "        (default properties omitted)"
-    new "        (propiedades por defecto omitidas)"
-
-    # renpy/common/_developer/inspector.rpym:156
-    old "<repr() failed>"
-    new "<repr() fallido>"
-
-    # renpy/common/_developer/developer.rpym:46
-    old "Reload Game (Shift+R)"
-    new "Reiniciar Juego (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:49
-    old "Variable Viewer"
-    new "Visor De Variables"
-
-    # renpy/common/_developer/developer.rpym:52
-    old "Theme Test"
-    new "Probar Tema"
-
-    # renpy/common/_developer/developer.rpym:58
-    old "Image Location Picker"
-    new "Selector de posición en imágenes"
-
-    # renpy/common/_developer/developer.rpym:61
-    old "Filename List"
-    new "Lista De Archivos"
-
-    # renpy/common/_developer/developer.rpym:307
-    old "Undefined Images"
-    new "Imagenes No Definidas"
-
-    # renpy/common/_developer/developer.rpym:410
-    old "Mouse position: %r"
-    new "Posición del ratón: %r"
-
-    # renpy/common/_developer/developer.rpym:412
-    old "Right-click or escape to quit."
-    new "Click-derecho o escape para salir."
-
-    # renpy/common/_developer/developer.rpym:465
-    old "Done"
-    new "Hecho"
-
-    # renpy/common/_developer/developer.rpym:44
-    old "Developer Menu"
-    new "Menú De Desarrollo"
-
-    # renpy/common/_developer/developer.rpym:405
-    old "Rectangle: %r"
-    new "Rectángulo: %r"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Consola (Mayús.+O)"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Muestra registro de carga de imagen"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Oculta registro de carga de imagen"
-
-    # renpy/common/_developer/developer.rpym:149
-    old "No variables have changed since the game started."
-    new "Ninguna variable ha cambiado desde el inicio del juego."
-
-    # renpy/common/_developer/developer.rpym:152
-    old "Return to the developer menu"
-    new "Volver al menú de desarrollo"
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "Consola %(version)s, original de Shiz, C, y delta.\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Presiona <esc> para salir de la consola. Escribe 'help' para la ayuda.\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "Script Ren'Py habilitado."
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "Script Ren'Py deshabilitado."
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: muestra esta ayuda"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "comandos:\n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new " <sentencia renpy script>: ejecuta la sentencia\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <expresión o sentencia python>: ejecuta la expresión o sentencia"
-
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: limpia el historial de la consola"
-
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: sale de la consola"
-
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: carga el juego desde el 'slot'"
-
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: graba el juego en el 'slot'"
-
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: recarga el juego, actualizando los scripts"
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Captura de pantalla guardada como %s."
 
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <expresión>: observa una expresión python"
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Voz automática desactivada."
 
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expresión>: deja de observar una expresión"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "'Portapapeles a voz' activado. "
 
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: deja de observar todas las expresiones"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Voz automática activada. "
 
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <label>: salta a la etiqueta"
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Modo salto"
 
-    # renpy/common/_developer/developer.rpym:272
-    old "{b}Missing Images{/b}"
-    new "{b}Imágenes ausentes{/b}"
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "Este programa contiene software libre sujeto a diversas licencias que incluyen la licencia MIT y la {i}GNU Lesser General Public License{/i} (Licencia Pública General Reducida de GNU). Puedes encontrar la lista completa de software, con enlaces al código fuente completo, {a=https://www.renpy.org/l/license}aquí (en inglés){/a}."
 
-    # renpy/common/00keymap.rpy:332
-    old "Autoreload"
-    new "Autorecarga"
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "'Portapapeles a voz' activado. Pulsa 'Mayús.+C' para desactivarlo."
 
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "Ubicación"
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Voz automática dirà \"[renpy.display.tts.last]\". Pulsa 'alt+shift+V' para desactivar."
 
-    # renpy/common/00preferences.rpy:373
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
-    new "Self-voicing activado. Presiona 'v' para desactivarlo."
+    new "Voz automática activada. Presiona 'v' para desactivarla."
 
-    # renpy/common/00preferences.rpy:387
-    old "Clipboard voicing enabled. Press 'shift+C' to disable."
-    new "'Portapapeles a voz' activado. Pulsa 'Mayús.+C' para desactivarlo."
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contactando App Store\nPor favor, espera..."
 
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "El Actualizador de Ren'Py no es compatible con dispositivos móviles."
 
-    # renpy/common/00updater.rpy:478
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "Se simula un error."
 
-    # renpy/common/00updater.rpy:654
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "O bien este proyecto no es compatible con la actualización o el archivo de estado de la actualización se ha eliminado."
 
-    # renpy/common/00updater.rpy:668
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "Esta cuenta no tiene permiso para realizar una actualización."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "Esta cuenta no tiene permiso para escribir en el registro de actualización."
 
-    # renpy/common/00updater.rpy:696
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "No se pudo verificar la actualización de firmas."
 
-    # renpy/common/00updater.rpy:956
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "El archivo de actualización no se ha descargado."
 
-    # renpy/common/00updater.rpy:974
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "El archivo de actualización no tiene el 'digest' correcto - es posible que esté dañado."
 
-    # renpy/common/00updater.rpy:1030
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "Tipo desconocido {1} al desempaquetar {0}."
 
-    # renpy/common/_developer/developer.rpym:437
-    old "Rectangle copied to clipboard."
-    new "Rectángulo copiado al portapapeles."
+    # 00updater.rpy:1393
+    old "Updater"
+    new "Actualizador"
+
+    # 00updater.rpy:1404
+    old "This program is up to date."
+    new "Este programa está actualizado."
+
+    # 00updater.rpy:1406
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] está disponible. ¿Quieres instalarla?"
 
-    # renpy/common/_developer/developer.rpym:440
-    old "Position copied to clipboard."
-    new "Posición copiada al portapapeles."
+    # 00updater.rpy:1408
+    old "Preparing to download the updates."
+    new "Preparando para descargar la actualización."
+
+    # 00updater.rpy:1410
+    old "Downloading the updates."
+    new "Descargando la actualización."
+
+    # 00updater.rpy:1412
+    old "Unpacking the updates."
+    new "Desempaquetando la actualización."
+
+    # 00updater.rpy:1416
+    old "The updates have been installed. The program will restart."
+    new "La actualización ha sido instalada. El programa se reiniciará."
+
+    # 00updater.rpy:1418
+    old "The updates have been installed."
+    new "La actualización ha sido instalada."
+
+    # 00updater.rpy:1420
+    old "The updates were cancelled."
+    new "La actualización ha sido cancelada."
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Imagen [index] de [count] bloqueada."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "ant."
+
+    # 00gallery.rpy:584
+    old "next"
+    new "sig."
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "presentación"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "volver"
 
diff --git a/launcher/game/tl/spanish/developer.rpy b/launcher/game/tl/spanish/developer.rpy
new file mode 100644
index 0000000..3f212c3
--- /dev/null
+++ b/launcher/game/tl/spanish/developer.rpy
@@ -0,0 +1,179 @@
+
+translate spanish strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Menú De Desarrollo"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Reiniciar Juego (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Consola (Mayús.+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Visor De Variables"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Probar Tema"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Selector de posición en imágenes"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Lista De Archivos"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Muestra registro de carga de imagen"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Oculta registro de carga de imagen"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Nada para inspeccionar."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Volver al menú de desarrollo"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rectángulo: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Posición del ratón: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Clic-derecho o escape para salir."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectángulo copiado al portapapeles."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Posición copiada al portapapeles."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable Inspector"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Tamaño"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Estilo"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Ubicación"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Inspeccionando estilos de [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "visualizable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (no hay propiedades que afecten la visualización)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (propiedades por defecto omitidas)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() fallido>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Presiona <esc> para salir de la consola. Escribe 'help' para la ayuda.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Script Ren'Py habilitado."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Script Ren'Py deshabilitado."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: muestra esta ayuda"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "comandos:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <sentencia renpy script>: ejecuta la sentencia\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <expresión o sentencia python>: ejecuta la expresión o sentencia"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: limpia el historial de la consola"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: sale de la consola"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: carga el juego desde el 'slot'"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: graba el juego en el 'slot'"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: recarga el juego, actualizando los scripts"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expresión>: observa una expresión python"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expresión>: deja de observar una expresión"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: deja de observar todas las expresiones"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: salta a la etiqueta"
+
diff --git a/launcher/game/tl/spanish/distribute.rpy b/launcher/game/tl/spanish/distribute.rpy
deleted file mode 100644
index 2e4fe4e..0000000
--- a/launcher/game/tl/spanish/distribute.rpy
+++ /dev/null
@@ -1,37 +0,0 @@
-translate spanish strings:
-
-    # game/distribute.rpy:358
-    old "No packages are selected, so there's nothing to do."
-    new "Ningún paquete seleccionado. No hay nada que hacer."
-
-    # game/distribute.rpy:363
-    old "Scanning project files..."
-    new "Escaneando archivos del proyecto..."
-
-    # game/distribute.rpy:373
-    old "Scanning Ren'Py files..."
-    new "Escaneando los archivos de Ren'Py..."
-
-    # game/distribute.rpy:421
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "Se han construido todos los paquetes.\n\nDebido a la presencia de información de permisos, desempaquetar y reempaquetar las distribuciones para Linux y Macintosh no es compatible en Windows."
-
-    # game/distribute.rpy:545
-    old "Archiving files..."
-    new "Archivando archivos..."
-
-    # game/distribute.rpy:801
-    old "Writing the [variant] [format] package."
-    new "Escribiendo el paquete [format] para [variant]."
-
-    # game/distribute.rpy:814
-    old "Making the [variant] update zsync file."
-    new "Creando el archivo de actualización zsync para [variant]."
-
-    # game/distribute.rpy:910
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "Procesados {b}[complete]{/b} de {b}[total]{/b} archivos."
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "Ha fallado la construcción de distribuciones:\n\nLa variable build.directory_name no puede incluir espacios, dos puntos ni punto y coma."
diff --git a/launcher/game/tl/spanish/distribute_gui.rpy b/launcher/game/tl/spanish/distribute_gui.rpy
deleted file mode 100644
index 059ef46..0000000
--- a/launcher/game/tl/spanish/distribute_gui.rpy
+++ /dev/null
@@ -1,62 +0,0 @@
-translate spanish strings:
-
-    # game/distribute_gui.rpy:139
-    old "Build Distributions: [project.current.name!q]"
-    new "Construir Distibuciones: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:154
-    old "Directory Name:"
-    new "Nombre de la carpeta:"
-
-    # game/distribute_gui.rpy:158
-    old "Executable Name:"
-    new "Nombre del ejecutable:"
-
-    # game/distribute_gui.rpy:167
-    old "Actions:"
-    new "Acciones:"
-
-    # game/distribute_gui.rpy:175
-    old "Edit options.rpy"
-    new "Editar options.rpy"
-
-    # game/distribute_gui.rpy:176
-    old "Refresh"
-    new "Recargar"
-
-    # game/distribute_gui.rpy:193
-    old "Build Packages:"
-    new "Construir Paquetes:"
-
-    # game/distribute_gui.rpy:208
-    old "Build Updates"
-    new "Construir Actualizaciones"
-
-    # game/distribute_gui.rpy:212
-    old "Build"
-    new "Construir"
-
-    # game/distribute_gui.rpy:219
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Se detectaron errores al ejecutar el proyecto. Por favor asegúrese de que el proyecto se ejecuta sin errores antes de construir distibuciones."
-
-    # game/distribute_gui.rpy:236
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Tu proyecto no tiene información de construcción. ¿Te gustaría añadir la información de construcción al final del archivo options.rpy?"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "Añadir desde cláusulas a las llamadas, una vez"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "Opciones:"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "Añadir desde cláusula a las llamadas"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "Añadiendo desde cláusulas para llamar a las declaraciones que no las tienen."
-
diff --git a/launcher/game/tl/spanish/editor.rpy b/launcher/game/tl/spanish/editor.rpy
deleted file mode 100644
index 4a6de24..0000000
--- a/launcher/game/tl/spanish/editor.rpy
+++ /dev/null
@@ -1,64 +0,0 @@
-translate spanish strings:
-
-    # description for the option: "Editra"
-    # game/editor.rpy:120
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Recomendado.{/b} Un editor beta con una interfaz fácil de usar y funciones que ayudan en el desarrollo, como la corrección ortográfica. Editra actualmente carece de soporte IME necesario para la introducción de texto Chino, Japonés y Coreano."
-
-    # description for "Editra" on Linux
-    # game/editor.rpy:121
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Recomendado.{/b} Un editor beta con una interfaz fácil de usar y funciones que ayudan en el desarrollo, como la corrección ortográfica. Editra actualmente carece de soporte IME necesario para la introducción de texto Chino, Japonés y Coreano. En Linux, Editra requiere wxPython."
-
-    # game/editor.rpy:137
-    old "This may have occured because wxPython is not installed on this system."
-    new "Esto puede haber ocurrido porque wxPython no está instalado en este sistema."
-
-    # game/editor.rpy:144
-    old "Up to 22 MB download required."
-    new "Requiere descargar hasta 22 MB."
-
-    # description for the option: "JEdit"
-    # game/editor.rpy:155
-    old "A mature editor that requires Java."
-    new "Un editor muy maduro que requiere Java."
-
-    # game/editor.rpy:157
-    old "1.8 MB download required."
-    new "Requiere descargar 1.8 MB."
-
-    # game/editor.rpy:158
-    old "This may have occured because Java is not installed on this system."
-    new "Esto puede haber ocurrido porque Java no está instalado en este sistema"
-
-    # option: "System Editor"
-    # game/editor.rpy:163
-    old "System Editor"
-    new "Editor del sistema"
-
-    # description for the option: "System Editor"
-    # game/editor.rpy:164
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Usar el editor de su sistema operativo para que se asocie con los archivos .rpy."
-
-    # option: "None"
-    # game/editor.rpy:179
-    old "None"
-    new "Ninguno"
-
-    # description for the option: "None"
-    # game/editor.rpy:180
-    old "Prevents Ren'Py from opening a text editor."
-    new "Evita que Ren'Py abra un editor de texto."
-
-    # game/editor.rpy:327
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Ha ocurrido una excepción mientras se ejecutaba el editor de texto:\[exception!q]"
-
-    # game/editor.rpy:423
-    old "Select Editor"
-    new "Seleccionar Editor"
-
-    # game/editor.rpy:438
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Un editor de texto es el programa que vas a utilizar para editar los scripts de Ren'Py. Aquí, puedes seleccionar el editor que Ren'Py usará. Si no está disponible, el editor se descargará e instalará automáticamente."
diff --git a/launcher/game/tl/spanish/error.rpy b/launcher/game/tl/spanish/error.rpy
new file mode 100644
index 0000000..5a69261
--- /dev/null
+++ b/launcher/game/tl/spanish/error.rpy
@@ -0,0 +1,179 @@
+
+translate spanish strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Aceleración gráfica"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Escoger automáticamente"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Forzar 'Angle/DirectX Renderer'"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Forzar 'OpenGL Renderer'"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Forzar 'Software Renderer'"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Activar"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Los cambios se aplicarán la próxima vez que el programa se ejecute."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Aviso de funcionamiento"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Este ordenador usa 'software rendering'."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Este ordenador no usa 'shaders'."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Este ordenador muestra los gráficos lentamente."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Este ordenador tiene un problema mostrando los gráficos: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Los controladores gráficos pueden estar obsoletos o no funcionar adecuadamente. Esto puede conllevar que los gráficos se muestren lenta o incorrectamente. Actualizar DirectX puede solucionar este problema."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Los controladores gráficos pueden estar obsoletos o no funcionar adecuadamente. Esto puede conllevar que los gráficos se muestren lenta o incorrectamente."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Actualizar DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Continuar. Mostrar este aviso de nuevo"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Continuar. No mostrar este aviso de nuevo"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Actualizando DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "La instalación web de DirectX ha comenzado. Puede haber iniciado minimizada en la barra de tareas. Siga las instrucciones para instalar DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Nota:{/b} El programa de instalación de DirectX de Microsoft instalará, por defecto, la barra Bing. Si no desea esta barra, desactive la casilla correspondiente."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Cuando la instalación acabe, haga clic abajo para reiniciar el programa."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Reiniciar"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Selecciona mando para calibrar"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No hay mandos disponibles"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrando [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Pulsa o mueve: [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Salto (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Atrás (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Abrir rastreo"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Abre el archivo de rastreo 'traceback.txt' en un editor de texto."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copiar al portapapeles"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copia el archivo traceback.txt al portapapeles."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Ha sucedido una excepción."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Volver atrás"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Intenta volver a un momento anterior y permite guardar o escoger una opción diferente."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Ignorar"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Ignora la excepción y permite continuar. Suele conllevar más errores."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Recargar"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Recarga el juego del disco, guardando y restaurando la partida si es posible."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Sale del juego."
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Error en el análisis del código."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Abre errores de análisis"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Abre el archivo de errores, 'errors.txt', en un editor de texto."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copia el archivo errors.txt al portapapeles."
+
diff --git a/launcher/game/tl/spanish/front_page.rpy b/launcher/game/tl/spanish/front_page.rpy
deleted file mode 100644
index 5dfbdc8..0000000
--- a/launcher/game/tl/spanish/front_page.rpy
+++ /dev/null
@@ -1,114 +0,0 @@
-translate spanish strings:
-
-    # game/font_page.rpy 65
-    old "PROJECTS:"
-    new "PROYECTOS:"
-
-    # game/front_page.rpy:67
-    old "refresh"
-    new "recargar"
-
-    # game/front_page.rpy:94
-    old "+ Create New Project"
-    new "+ Crear Un Proyecto Nuevo"
-
-    # game/front_page.rpy:106
-    old "Launch Project"
-    new "Ejecutar Proyecto"
-
-    # game/front_page.rpy:122
-    old "[p.name!q] (template)"
-    new "[p.name!q] (plantilla)"
-
-    # game/front_page.rpy:127
-    old "Tutorial"
-    new "Tutorial"
-
-    # game/front_page.rpy:128
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:144
-    old "Active Project"
-    new "Proyecto Activo"
-
-    # game/front_page.rpy:152
-    old "Open Directory"
-    new "Abrir Carpeta"
-
-    # game/front_page.rpy:157
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:158
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:164
-    old "Edit File"
-    new "Editar Archivo"
-
-    # game/front_page.rpy:172
-    old "All script files"
-    new "Todos los scripts"
-
-    # game/front_page.rpy:181
-    old "Navigate Script"
-    new "Navegar por los Scripts"
-
-    # game/front_page.rpy:192
-    old "Check Script (Lint)"
-    new "Comprobar Script (Lint)"
-
-    # game/front_page.rpy:193
-    old "Change Theme"
-    new "Cambiar Tema"
-
-    # game/front_page.rpy:194
-    old "Delete Persistent"
-    new "Eliminar Datos Persistentes"
-
-    # game/front_page.rpy:202
-    old "Build Distributions"
-    new "Construir Distibuciones"
-
-    # game/front_page.rpy:204
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:205
-    old "Generate Translations"
-    new "Generar Traducciones"
-
-    # game/front_page.rpy:206
-    old "Extract Dialogue"
-    new "Extraer Diálogos"
-
-    # game/front_page.rpy:222
-    old "Checking script for potential problems..."
-    new "Comprobando script por problemas potenciales..."
-
-    # game/front_page.rpy:237
-    old "Deleting persistent data..."
-    new "Eliminando datos persistentes..."
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Abrir directorio [text]."
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "Seleccionar proyecto [text]."
-
-    # game/front_page.rpy:234
-    old "Force Recompile"
-    new "Forzar Recompilación"
-
-    # game/front_page.rpy:285
-    old "Recompiling all rpy files into rpyc files..."
-    new "Recompilando todos los archivos rpy en archivos rpyc..."
-
-    # game/front_page.rpy:246
-    old "iOS"
-    new "iOS"
-
diff --git a/launcher/game/tl/spanish/gui.rpy b/launcher/game/tl/spanish/gui.rpy
new file mode 100644
index 0000000..22db723
--- /dev/null
+++ b/launcher/game/tl/spanish/gui.rpy
@@ -0,0 +1,434 @@
+
+translate spanish strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
+    # gui.rpy:17
+    old "## GUI Configuration Variables"
+    new "## Variables de configuración de la interfaz."
+
+    # gui.rpy:168
+    old "## The color of button text in various states."
+    new "## El color del texto del botón en varios estados."
+
+    # gui.rpy:174
+    old "## The horizontal alignment of the button text. (0.0 is left, 0.5 is center, 1.0 is right)."
+    new "## La alineación horizontal del texto del botón. (0.0 es izquierda, 0.5 es centro, 1.0 es derecha)."
+
+    # gui.rpy:395
+    old "## Localization"
+    new "## Localización"
+
+    # gui.rpy:397
+    old "## This controls where a line break is permitted. The default is suitable for most languages. A list of available values can be found at https://www.renpy.org/doc/html/style_properties.html#style-property-language"
+    new "## Esto controla donde se permite un salto de linea. El valor por defecto es adecuado para la mayoria de idiomas. Puede encontrar una lista de valores disponibles en https://www.renpy.org/doc/html/style_properties.html#style-property-language"
+
+    # gui.rpy:405
+    old "## Mobile devices"
+    new "## Dispositivos Móviles"
diff --git a/launcher/game/tl/spanish/interface.rpy b/launcher/game/tl/spanish/interface.rpy
deleted file mode 100644
index 892da49..0000000
--- a/launcher/game/tl/spanish/interface.rpy
+++ /dev/null
@@ -1,93 +0,0 @@
-translate spanish strings:
-
-    # game/interface.rpy:89
-    old "Documentation"
-    new "Documentación"
-
-    # game/interface.rpy:90
-    old "Ren'Py Website"
-    new "Web de Ren'Py"
-
-    # game/interface.rpy:91
-    old "Ren'Py Games List"
-    new "Lista de juegos Ren'Py"
-
-    # game/interface.rpy:92
-    old "About"
-    new "Acerca de"
-
-    # game/interface.rpy:99
-    old "update"
-    new "actualizar"
-
-    # game/interface.rpy:101
-    old "preferences"
-    new "preferencias"
-
-    # game/interface.rpy:102
-    old "quit"
-    new "salir"
-
-    # game/interface.rpy:174
-    old "Yes"
-    new "Sí"
-
-    # game/interface.rpy:176
-    old "No"
-    new "No"
-
-    # game/interface.rpy:182
-    old "Back"
-    new "Atrás"
-
-    # game/interface.rpy:184
-    old "Cancel"
-    new "Cancelar"
-
-    # game/interface.rpy:187
-    old "Continue"
-    new "Continuar"
-
-    # game/interface.rpy:211
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Debido a las limitaciones del formato de paquete, no se permite el uso de nombres de archivos y carpetas que no sean ASCII"
-
-    # game/interface.rpy:213
-    old "[title]"
-    new "[title]"
-
-    # game/interface.rpy:299
-    old "ERROR"
-    new "ERROR"
-
-    # game/interface.rpy:328
-    old "While [what!q], an error occured:"
-    new "Mientras [what!q], se produjo un error:"
-
-    # game/interface.rpy:329
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:347
-    old "Text input may not contain the {{ or [[ characters."
-    new "La entrada de texto no puede contener los caracteres {{ o [[."
-
-    # game/interface.rpy:352
-    old "File and directory names may not contain / or \\."
-    new "Los nombres de archivos y carpetas no pueden contener / o \\."
-
-    # game/interface.rpy:358
-    old "File and directory names must consist of ASCII characters."
-    new "Los nombres de archivos y carpetas deben ser caracteres ASCII."
-
-    # game/interface.rpy:379
-    old "INFORMATION"
-    new "INFORMACIÓN"
-
-    # game/interface.rpy:422
-    old "PROCESSING"
-    new "PROCESANDO"
-
-    # game/interface.rpy:452
-    old "CHOICE"
-    new "SELECCIONA"
diff --git a/launcher/game/tl/spanish/ios.rpy b/launcher/game/tl/spanish/ios.rpy
deleted file mode 100644
index 55f5d91..0000000
--- a/launcher/game/tl/spanish/ios.rpy
+++ /dev/null
@@ -1,98 +0,0 @@
-translate spanish strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Para construir paquetes para iOS, por favor descargue renios, descomprímalo, y colóquelo dentro de la carpeta de Ren'Py. Después reinicie el launcher de Ren'Py."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "El directorio donde se colocarán los proyectos de Xcode no se ha seleccionado. Seleccione 'Seleccionar directorio' para seleccionarlo."
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "No hay proyecto de Xcode correspondiente al proyecto de Ren'Py actual. Elija 'Crear proyecto de Xcode' para crear uno."
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Existe un proyecto de Xcode. Elija 'Actualizar proyecto de Xcode' para actualizarlo con los últimos archivos del juego, o use Xcode para construirlo e instalarlo."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Al intentar emular un iPhone.\n\nLa entrada táctil se emula a través del ratón, pero solo cuando se mantiene pulsado el botón."
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Al intentar emular un iPad.\n\nLa entrada táctil se emula a través del ratón, pero solo cuando se mantiene pulsado el botón."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Selecciona el directorio donde se colocarán los proyectos de Xcode."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "Crea un proyecto de Xcode correspondiente al proyecto de Ren'Py actual."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Actualiza el proyecto de Xcode con los últimos archivos del juego. Esto debe hacerse cada vez que el proyecto de Ren'Py cambie."
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Abre el proyecto de Xcode en Xcode."
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Abre el directorio que contiene los proyectos de Xcode."
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "El proyecto de Xcode ya existe. ¿Quiere cambiar el nombre del antiguo proyecto, y sustituirlo por uno nuevo?"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:229
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:233
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "Seleccionar directorio para los proyectos de Xcode"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "Crear Proyecto de Xcode"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "Actaulizar Proyecto de Xcode"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "Ejecutar Xcode"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "Abrir directorio de proyectos de Xcode"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "Antes de empaquetar aplicaciones de iOS, tendrá que descargar renios, el soporte de iOS para Ren'Py. ¿Quiere descargar renios ahora?"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "DIRECTORIO DE PROYECTOS DE XCODE"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Por favor elija el directorio de proyectos de Xcode usando el selector de directorio. \n{b}El selector de directorio puede haberse abierto detras de esta ventana.{/b}"
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py ha establecidio el directorio de proyectos de Xcode en: "
-
diff --git a/launcher/game/tl/spanish/launcher.rpy b/launcher/game/tl/spanish/launcher.rpy
new file mode 100644
index 0000000..b339df7
--- /dev/null
+++ b/launcher/game/tl/spanish/launcher.rpy
@@ -0,0 +1,1198 @@
+
+translate spanish strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Ver licencia"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "Nombre del archivo"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Introduce el nombre del archivo de script para crearlo."
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "El nombre del archivo debe tener la extensión .rpy."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "El archivo ya existe."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py carga automaticamente todos los archivos que terminan en .rpy. Para usar este\n# archivo, defina una etiqueta y salte a el desde otro archivo\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Para construir un paquete para Android, por favor descarga RAPT, descomprimelo y colocalo dentro de la carpeta de Ren'Py. Despues reinicia el launcher de Ren'Py."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Se necesita Java Development Kit de 32-bit para construir paquetes de Android en Windows. El JDK es diferente al JRE, es posible que tenga Java sin tener el JDK.\n\nPor favor {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}descarga e instala el JDK{/a}, después, reinicia Ren'Py."
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT está instalado, pero tendrás que instalar el SDK de Android para poder construir paquetes de Android. Selecciona instalar SDK para instalarlo."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT está instalado, pero la clave aun no se ha configurado. Por favor crea una nueva clave, o restaura android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "El proyecto actual no se ha configurado. Usa \"Configurar\" para configurarlo antes de construirlo."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Selecciona \"Construir\" para construir el proyecto actual, o conecta un dispositivo Android y selecciona \"Construir & instalar\" para construirlo e instalarlo en el dispositivo."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Al intentar emular un teléfono Android. \n\nLa entrada táctil se emula mediante el ratón, pero sólo cuando el botón se mantiene pulsado. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Al intentar emular una tablet Android. \n\nLa entrada táctil se emula mediante el ratón, pero sólo cuando el botón se mantiene pulsado. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Al intentar emular una consola Android basada en televisión, como OUYA o Fire TV.\n\nPara el control se usan las flechas, Intro está asignado al botón select. Escape está asignado al botón de menú, y PageUp está asignado al botón Atrás."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Descarga e instala el SDK de android y los paquetes de soporte. Opcionalmente, genera la clave necesaria para firmar el paquete."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Configura el nombre del paquete, la versión, y otra información de este proyecto."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Abre el archivo que contiene las claves de Google Play en el editor. \n\nEsto sólo es necesario si la aplicación usa una expansión APK. Para más información lee la documentación."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Construir el paquete de Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Construye el paquete de Android, e instálalo en un dispositivo Android connectado a tu ordenador."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Construye un paquete para Android, lo instala en un dispositivo conectado a su ordenador, y luego ejecuta la aplicación en su dispositivo."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Conectar a un dispositivo Android ejecutando ADB en modo TCP/IP."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Desconectar de un dispositivo Android corriendo ADB en modo TCP/IP."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Emulación:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Teléfono"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Tablet"
+
+    # android.rpy:341
+    old "Television"
+    new "Televisión"
+
+    # android.rpy:353
+    old "Build:"
+    new "Construir:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Instalar SDK y Crear claves"
+
+    # android.rpy:365
+    old "Configure"
+    new "Configurar"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Construir Paquete"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Construir & Instalar"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Construir, instalar & Ejecutar"
+
+    # android.rpy:388
+    old "Other:"
+    new "Otros:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Conexión remota ADB"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Desconexión remota ADB"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Antes de empaquetar apps para Android, vas a necesitar descargar RAPT, Ren'Py Android Packaging Tool. ¿Quieres descargar RAPT ahora?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Dirección remota ADB"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Por favor introduce la dirección IP y el número de puerto para conectarte, con el formato \"192.168.1.143:5555\". Consulta la documentación de tu dispositivo para averiguar si es compatible con ADB remoto, y si es así, la dirección y el puerto a utilizar."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Dirección remota ADB no válida"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "La dirección debe contener exactamente un ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "El host no puede contener espacios en blanco."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "El puerto debe ser un número."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py fue incapaz de ejecutar python con tkinter para elegir el directorio. Por favor instale el paquete python-tk o tkinter."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "No se puede cambiar el tema. Quizás options.rpy ha sufrido muchos cambios."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Elegir Tema"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Tema"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Combinación de colores"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Continuar"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "INFORMACIÓN"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Escaneando archivos del proyecto..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Ha fallado la construcción de distribuciones:\n\nLa variable build.directory_name no puede incluir espacios, dos puntos ni punto y coma."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "Ningún paquete seleccionado. No hay nada que hacer."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Escaneando los archivos de Ren'Py..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "Se han construido todos los paquetes.\n\nDebido a la presencia de información de permisos, desempaquetar y reempaquetar las distribuciones para Linux y Macintosh no es compatible en Windows."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Archivando archivos..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Escribiendo el paquete [format] para [variant]."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Creando el archivo de actualización zsync para [variant]."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Procesados {b}[complete]{/b} de {b}[total]{/b} archivos."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Construir Distibuciones: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Nombre de la carpeta:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Nombre del ejecutable:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Acciones:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Editar options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Añadir desde cláusulas a las llamadas, una vez"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Recargar"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Construir Paquetes:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Opciones:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Construir Actualizaciones"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Añadir desde cláusula a las llamadas"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Forzar Recompilación"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Construir"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Añadiendo desde cláusulas para llamar a las declaraciones que no las tienen."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Se detectaron errores al ejecutar el proyecto. Por favor asegúrese de que el proyecto se ejecuta sin errores antes de construir distibuciones."
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Tu proyecto no tiene información de construcción. ¿Te gustaría añadir la información de construcción al final del archivo options.rpy?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Recomendado.{/b} Un editor beta con una interfaz fácil de usar y funciones que ayudan en el desarrollo, como la corrección ortográfica. Editra actualmente carece de soporte IME necesario para la introducción de texto Chino, Japonés y Coreano."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Recomendado.{/b} Un editor beta con una interfaz fácil de usar y funciones que ayudan en el desarrollo, como la corrección ortográfica. Editra actualmente carece de soporte IME necesario para la introducción de texto Chino, Japonés y Coreano. En Linux, Editra requiere wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Esto puede haber ocurrido porque wxPython no está instalado en este sistema."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Requiere descargar hasta 22 MB."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Un editor muy maduro que requiere Java."
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "Requiere descargar 1.8 MB."
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Esto puede haber ocurrido porque Java no está instalado en este sistema"
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Usar el editor de su sistema operativo para que se asocie con los archivos .rpy."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Evita que Ren'Py abra un editor de texto."
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Ha ocurrido una excepción mientras se ejecutaba el editor de texto:\\[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Seleccionar Editor"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Un editor de texto es el programa que vas a utilizar para editar los scripts de Ren'Py. Aquí, puedes seleccionar el editor que Ren'Py usará. Si no está disponible, el editor se descargará e instalará automáticamente."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Cancelar"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Abrir directorio [text]."
+
+    # front_page.rpy:93
+    old "refresh"
+    new "recargar"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Crear Un Proyecto Nuevo"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Ejecutar Proyecto"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (plantilla)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Seleccionar proyecto [text]."
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Proyecto Activo"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Abrir Carpeta"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Editar Archivo"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Todos los scripts"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Navegar por los Scripts"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Comprobar Script (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Cambiar Tema"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Eliminar Datos Persistentes"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Construir Distibuciones"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Generar Traducciones"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Extraer Diálogos"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Comprobando script por problemas potenciales..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Eliminando datos persistentes..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Recompilando todos los archivos rpy en archivos rpyc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "NOMBRE DEL PROYECTO"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Por favor introduce el nombre de tu proyecto:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "El nombre del proyecto no puede estar vacío."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] ya existe. Por favor elige un nombre diferente para el proyecto."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] ya existe. Por favor elige un nombre diferente para el proyecto."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Documentación"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Web de Ren'Py"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Lista de juegos Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "actualizar"
+
+    # interface.rpy:119
+    old "preferences"
+    new "preferencias"
+
+    # interface.rpy:120
+    old "quit"
+    new "salir"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Debido a las limitaciones del formato de paquete, no se permite el uso de nombres de archivos y carpetas que no sean ASCII"
+
+    # interface.rpy:327
+    old "ERROR"
+    new "ERROR"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Mientras [what!q], se produjo un error:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "La entrada de texto no puede contener los caracteres {{ o [[."
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Los nombres de archivos y carpetas no pueden contener / o \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Los nombres de archivos y carpetas deben ser caracteres ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "PROCESANDO"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "PREGUNTA"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "SELECCIONA"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Para construir paquetes para iOS, por favor descargue renios, descomprímalo, y colóquelo dentro de la carpeta de Ren'Py. Después reinicie el launcher de Ren'Py."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "El directorio donde se colocarán los proyectos de Xcode no se ha seleccionado. Seleccione 'Seleccionar directorio' para seleccionarlo."
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "No hay proyecto de Xcode correspondiente al proyecto de Ren'Py actual. Elija 'Crear proyecto de Xcode' para crear uno."
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Existe un proyecto de Xcode. Elija 'Actualizar proyecto de Xcode' para actualizarlo con los últimos archivos del juego, o use Xcode para construirlo e instalarlo."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Al intentar emular un iPhone.\n\nLa entrada táctil se emula a través del ratón, pero solo cuando se mantiene pulsado el botón."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Al intentar emular un iPad.\n\nLa entrada táctil se emula a través del ratón, pero solo cuando se mantiene pulsado el botón."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Selecciona el directorio donde se colocarán los proyectos de Xcode."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Crea un proyecto de Xcode correspondiente al proyecto de Ren'Py actual."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Actualiza el proyecto de Xcode con los últimos archivos del juego. Esto debe hacerse cada vez que el proyecto de Ren'Py cambie."
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Abre el proyecto de Xcode en Xcode."
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Abre el directorio que contiene los proyectos de Xcode."
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "El proyecto de Xcode ya existe. ¿Quiere cambiar el nombre del antiguo proyecto, y sustituirlo por uno nuevo?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Seleccionar directorio para los proyectos de Xcode"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Crear Proyecto de Xcode"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Actaulizar Proyecto de Xcode"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Ejecutar Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Abrir directorio de proyectos de Xcode"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Antes de empaquetar aplicaciones de iOS, tendrá que descargar renios, el soporte de iOS para Ren'Py. ¿Quiere descargar renios ahora?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "DIRECTORIO DE PROYECTOS DE XCODE"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Por favor elija el directorio de proyectos de Xcode usando el selector de directorio. \n{b}El selector de directorio puede haberse abierto detras de esta ventana.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py ha establecidio el directorio de proyectos de Xcode en: "
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Navegando por: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Orden: "
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "alfabético"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "por archivo"
+
+    # navigation.rpy:182
+    old "natural"
+    new "natural"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Categoría:"
+
+    # navigation.rpy:196
+    old "files"
+    new "archivos"
+
+    # navigation.rpy:197
+    old "labels"
+    new "Etiquetas"
+
+    # navigation.rpy:198
+    old "defines"
+    new "defines"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "transforms"
+
+    # navigation.rpy:200
+    old "screens"
+    new "pantallas"
+
+    # navigation.rpy:201
+    old "callables"
+    new "callables"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "TODO"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Añadir archivo de script"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "No se han encontrado comentarios \"TODO\". Para crear uno, incluye \"# TODO\" en tu script."
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "La lista de nombres está vacía."
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "No se puede establecer el directorio de proyectos. Abandonando."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Elige una plantilla para el proyecto"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Por favor selecciona una plantilla para usar en tu nuevo proyecto. La plantilla establece la fuente predeterminada y el idioma de la interfaz de usuario, Si tu idioma no está soportado, elige \"English\"."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Preferencias del Launcher"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Carpeta de Proyectos:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Directorio de proyectos: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "No establecido"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Editor de texto:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Editor de texto: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Canal de actualización"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Opciones de navegación:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Incluir nombres privados"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Incluir nombres de bibliotecas"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Opciones del Launcher:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Renderización por hardware"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Mostrar plantillas"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Mostrar la sección Editar Archivo"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Fuentes grandes"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Salida de la consola"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Abrir el launcher"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Idioma:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Despues de hacer cambios a un script, presiona shift+R para recargar tu juego."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Presiona shift+O (la letra) para acceder a la consola."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Presiona shift+D para acceder al menú de desarrollador."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "¿Has respaldado tus proyectos recientemente?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "La ejecución del proyecto ha fallado."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Por favor, asegurate de que tu proyecto se ejecuta normalmente antes de ejecutar este comando."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py está escaneando el proyecto..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Ejecutando"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "CARPETA DEL PROYECTO"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Por favor elige la carpeta del proyecto usando el selector de proyecto. \n{b}El selector de carpetas puede haberse abierto detrás de esta ventana."
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "El launcher buscará proyectos en esta carpeta, creará nuevos proyectos en esta carpeta, y colocará los proyectos en este directorio."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py ha establecido el directorio de proyectos:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Generar cadenas vacías para las traducciones"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py está generando las traducciones..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py ha terminado de generar las traducciones [language]"
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py está extrayendo los diálogos..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Selecciona el Canal de Actualización"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "El canal de actualización controla la versión de Ren'Py que el actualizador descargará. Por favor selecciona un canal de actualización:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Release"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Recomendado.{/b} La versión the Ren'Py que se recomienda usar en todos los juegos recién liberados."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Prerelease"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Una vista previa de la próxima versión de Ren'Py que puede ser utilizada para probar y aprovechar las nuevas características, pero no para las versiones finales de los juegos."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Experimental"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Versiones experimentales de Ren'Py. No debes seleccionar el canal a menos que te lo pida un desarrollador de Ren'Py."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Versión de desarrollo de Ren'Py. Puede tener las últimas características o puede no funcionar."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Ha sucedido un error:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Buscando actualizaciones."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py está actualizado."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] ahora está disponible. ¿Quieres instalarla?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Preparando para descargar la actualización."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Descargando la actualización."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Descomprimiendo la actualización."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Finalizando."
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "La actualización se ha instalado. Ren'Py se reiniciará."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "La actualización se ha instalado."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Se ha cancelado la actualización."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Actualizar Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Continuar"
+
+    # choose_directory.rpy:104
+    old "The selected projects directory is not writable."
+    new "El directorio de proyectos seleccionado no puede ser escrito"
+
+    # distribute.rpy:1061
+    old "Signing the Macintosh application...\n(This may take a long time.)"
+    new "Firmando la aplicación para Macintosh...\n(Esto puede tardar mucho tiempo)"
+
+    # front_page.rpy:91
+    old "PROJECTS:"
+    new "PROYECTOS:"
diff --git a/launcher/game/tl/spanish/navigation.rpy b/launcher/game/tl/spanish/navigation.rpy
deleted file mode 100644
index a058064..0000000
--- a/launcher/game/tl/spanish/navigation.rpy
+++ /dev/null
@@ -1,65 +0,0 @@
-translate spanish strings:
-
-    # game/navigation.rpy:150
-    old "Navigate: [project.current.name]"
-    new "Navegando por: [project.current.name]"
-
-    # game/navigation.rpy:159
-    old "Order: "
-    new "Orden: "
-
-    # game/navigation.rpy:160
-    old "alphabetical"
-    new "alfabético"
-
-    # game/navigation.rpy:162
-    old "by-file"
-    new "por archivo"
-
-    # game/navigation.rpy:164
-    old "natural"
-    new "natural"
-
-    # game/navigation.rpy:176
-    old "Category:"
-    new "Categoría:"
-
-    # game/navigation.rpy:178
-    old "files"
-    new "archivos"
-
-    # game/navigation.rpy:179
-    old "labels"
-    new "Etiquetas"
-
-    # game/navigation.rpy:180
-    old "defines"
-    new "defines"
-
-    # game/navigation.rpy:181
-    old "transforms"
-    new "transforms"
-
-    # game/navigation.rpy:182
-    old "screens"
-    new "pantallas"
-
-    # game/navigation.rpy:183
-    old "callables"
-    new "callables"
-
-    # game/navigation.rpy:184
-    old "TODOs"
-    new "TODO"
-
-    # game/navigation.rpy:223
-    old "+ Add script file"
-    new "+ Añadir archivo de script"
-
-    # game/navigation.rpy:231
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "No se han encontrado comentarios \"TODO\". Para crear uno, incluye \"# TODO\" en tu script."
-
-    # game/navigation.rpy:238
-    old "The list of names is empty."
-    new "La lista de nombres está vacía."
diff --git a/launcher/game/tl/spanish/new_project.rpy b/launcher/game/tl/spanish/new_project.rpy
deleted file mode 100644
index 8148f3f..0000000
--- a/launcher/game/tl/spanish/new_project.rpy
+++ /dev/null
@@ -1,34 +0,0 @@
-translate spanish strings:
-
-    # game/new_project.rpy:22
-    old "Choose Project Template"
-    new "Elige una plantilla para el proyecto"
-
-    # game/new_project.rpy:40
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Por favor selecciona una plantilla para usar en tu nuevo proyecto. La plantilla establece la fuente predeterminada y el idioma de la interfaz de usuario, Si tu idioma no está soportado, elige \"English\"."
-
-    # game/new_project.rpy:55
-    old "PROJECT NAME"
-    new "NOMBRE DEL PROYECTO"
-
-    # game/new_project.rpy:56
-    old "Please enter the name of your project:"
-    new "Por favor introduce el nombre de tu proyecto:"
-
-    # game/new_project.rpy:62
-    old "The project name may not be empty."
-    new "El nombre del proyecto no puede estar vacío."
-
-    # game/new_project.rpy:67
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] ya existe. Por favor elige un nombre diferente para el proyecto."
-
-    # game/new_project.rpy:70
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] ya existe. Por favor elige un nombre diferente para el proyecto."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "No se puede establecer el directorio de proyectos. Abandonando."
-
diff --git a/launcher/game/tl/spanish/obsolete.rpy b/launcher/game/tl/spanish/obsolete.rpy
new file mode 100644
index 0000000..b0fe9da
--- /dev/null
+++ b/launcher/game/tl/spanish/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate spanish strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Mapeado del Joystick"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Vacío."
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "r"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Anterior"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Siguiente"
+
diff --git a/launcher/game/tl/spanish/options.rpy b/launcher/game/tl/spanish/options.rpy
new file mode 100644
index 0000000..3024433
--- /dev/null
+++ b/launcher/game/tl/spanish/options.rpy
@@ -0,0 +1,198 @@
+
+translate spanish strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
+    # options.rpy:146
+    old "## Icon"
+    new "## Icono"
diff --git a/launcher/game/tl/spanish/preferences.rpy b/launcher/game/tl/spanish/preferences.rpy
deleted file mode 100644
index bb5b0a4..0000000
--- a/launcher/game/tl/spanish/preferences.rpy
+++ /dev/null
@@ -1,82 +0,0 @@
-translate spanish strings:
-
-    # game/preferences.rpy:40
-    old "Launcher Preferences"
-    new "Preferencias del Launcher"
-
-    # game/preferences.rpy:61
-    old "Projects Directory:"
-    new "Carpeta de Proyectos:"
-
-    # game/preferences.rpy:68
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:70
-    old "Not Set"
-    new "No establecido"
-
-    # game/preferences.rpy:84
-    old "Text Editor:"
-    new "Editor de texto:"
-
-    # game/preferences.rpy:106
-    old "Update Channel:"
-    new "Canal de actualización"
-
-    # game/preferences.rpy:126
-    old "Navigation Options:"
-    new "Opciones de navegación:"
-
-    # game/preferences.rpy:130
-    old "Include private names"
-    new "Incluir nombres privados"
-
-    # game/preferences.rpy:131
-    old "Include library names"
-    new "Incluir nombres de bibliotecas"
-
-    # game/preferences.rpy:141
-    old "Launcher Options:"
-    new "Opciones del Launcher:"
-
-    # game/preferences.rpy:145
-    old "Hardware rendering"
-    new "Renderización por hardware"
-
-    # game/preferences.rpy:146
-    old "Show templates"
-    new "Mostrar plantillas"
-
-    # game/preferences.rpy:148
-    old "Console output"
-    new "Salida de la consola"
-
-    # game/preferences.rpy:169
-    old "Open launcher project"
-    new "Abrir el launcher"
-
-    # game/preferences.rpy:183
-    old "Language:"
-    new "Idioma:"
-
-    # game/preferences.rpy:89
-    old "Projects directory: [text]"
-    new "Directorio de proyectos: [text]"
-
-    # game/preferences.rpy:112
-    old "Text editor: [text]"
-    new "Editor de texto: [text]"
-
-    # game/preferences.rpy:169
-    old "Large fonts"
-    new "Fuentes grandes"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "Mostrar la sección Editar Archivo"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "Generar cadenas vacías para las traducciones"
-
diff --git a/launcher/game/tl/spanish/project.rpy b/launcher/game/tl/spanish/project.rpy
deleted file mode 100644
index caaff98..0000000
--- a/launcher/game/tl/spanish/project.rpy
+++ /dev/null
@@ -1,58 +0,0 @@
-translate spanish strings:
-
-    # game/project.rpy:201
-    old "Launching the project failed."
-    new "La ejecución del proyecto ha fallado."
-
-    # game/project.rpy:201
-    old "Please ensure that your project launches normally before running this command."
-    new "Por favor, asegurate de que tu proyecto se ejecuta normalmente antes de ejecutar este comando."
-
-    # game/project.rpy:204
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py está escaneando el proyecto..."
-
-    # game/project.rpy:503
-    old "PROJECTS DIRECTORY"
-    new "CARPETA DEL PROYECTO"
-
-    # game/project.rpy:503
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Por favor elige la carpeta del proyecto usando el selector de proyecto. \n{b}El selector de carpetas puede haberse abierto detrás de esta ventana."
-
-    # game/project.rpy:503
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "El launcher buscará proyectos en esta carpeta, creará nuevos proyectos en esta carpeta, y colocará los proyectos en este directorio."
-
-    # game/project.rpy:543
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory."
-    new "Ren'Py ha podido ejecutar python con tkinter para elegir el directorio de proyectos."
-
-    # game/project.rpy:547
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py ha establecido el directorio de proyectos:"
-
-    # game/project.rpy:30
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Despues de hacer cambios a un script, presiona shift+R para recargar tu juego."
-
-    # game/project.rpy:31
-    old "Press shift+O (the letter) to access the console."
-    new "Presiona shift+O (la letra) para acceder a la consola."
-
-    # game/project.rpy:32
-    old "Press shift+D to access the developer menu."
-    new "Presiona shift+D para acceder al menú de desarrollador."
-
-    # game/project.rpy:496
-    old "Launching"
-    new "Ejecutando"
-
-    # game/project.rpy:584
-    old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
-    new "Ren'Py no puede ejecutar python con tkinter para escoger el directorio de proyectos. Por favor, installa el paquete python-tk o tkinter."
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "¿Has respaldado tus proyectos recientemente?"
-
diff --git a/launcher/game/tl/spanish/screens.rpy b/launcher/game/tl/spanish/screens.rpy
new file mode 100644
index 0000000..dbabd90
--- /dev/null
+++ b/launcher/game/tl/spanish/screens.rpy
@@ -0,0 +1,662 @@
+
+translate spanish strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Atrás"
+
+    # screens.rpy:262
+    old "History"
+    new "Historial"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Saltar"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Guardar"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Guardar R."
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Cargar R."
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs."
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Comenzar"
+
+    # screens.rpy:316
+    old "Load"
+    new "Cargar"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Opciones"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "Fin repetición"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Menú principal"
+
+    # screens.rpy:328
+    old "About"
+    new "Acerca de"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Ayuda"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Salir"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Volver"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Versión [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Hecho con {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Página {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Grabación automática"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Grabación rápida"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "vacío"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}R"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Pantalla"
+
+    # screens.rpy:739
+    old "Window"
+    new "Ventana"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Pant. completa"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Lado de retroceso"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Desactivar"
+
+    # screens.rpy:746
+    old "Left"
+    new "Izquierda"
+
+    # screens.rpy:747
+    old "Right"
+    new "Derecha"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Texto no visto"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "Tras opciones"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transiciones"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Veloc. texto"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Veloc. auto-avance"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Volumen música"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Volumen sonido"
+
+    # screens.rpy:791
+    old "Test"
+    new "Prueba"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Volumen voz"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Silencia todo"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "El historial está vacío."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Teclado"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Ratón"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Mando"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Avanza el diálogo y activa la interfaz."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Espacio"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Avanza el dilogo sin seleccionar opciones."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Teclas de flecha"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navega la interfaz."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accede al menú del juego."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Salta el diálogo mientras se presiona."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tabulador"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Activa/desactiva el salto de diálogo."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Av. pág."
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Retrocede al diálogo anterior."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Re. pág."
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Avanza hacia el diálogo siguiente."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Oculta la interfaz."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Captura la pantalla."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Activa/desactiva la asistencia por {a=https://www.renpy.org/l/voicing}voz-automática{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Clic izquierdo"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Clic medio"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Clic derecho"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Rueda del ratón arriba\nClic en lado de retroceso"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Rueda del ratón abajo"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Comenzar, Guía"
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrar"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Sí"
+
+    # screens.rpy:1162
+    old "No"
+    new "No"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Saltando"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menú"
+
+    # screens.rpy:120
+    old "## If there's a side image, display it above the text. Do not display on the phone variant - there's no room."
+    new "## Si hay una imagen lateral, la muestra encima del texto. No la muestra en la variante de teléfono - no hay lugar."
+
+    # screens.rpy:252
+    old "## Ensure this appears on top of other screens."
+    new "## Asegúrese de que esto aparezca en la parte superior de otras pantallas."
+
+    # screens.rpy:291
+    old "## Main and Game Menu Screens"
+    new "## Principal y Pantalla de menu del juego."
+
+    # screens.rpy:361
+    old "## This ensures that any other menu screen is replaced."
+    new "## Esto asegura que cualquier otra pantalla de menu es remplazada."
+
+    # screens.rpy:368
+    old "## This empty frame darkens the main menu."
+    new "## Este marco vacío oscurece el menu principal."
+
+    # screens.rpy:439
+    old "## Reserve space for the navigation section."
+    new "## Reservar espacio para la sección de navegación."
+
+    # screens.rpy:619
+    old "## The page name, which can be edited by clicking on a button."
+    new "## El nombre de la pagina, se puede editar haciendo clic en el botón."
+
+    # screens.rpy:674
+    old "## range(1, 10) gives the numbers from 1 to 9."
+    new "## range(1, 10) da los numeros del 1 al 9."
+
+    # screens.rpy:1079
+    old "Left Trigger\nLeft Shoulder"
+    new "Left Trigger\nLeft Shoulder"
diff --git a/launcher/game/tl/spanish/script.rpym b/launcher/game/tl/spanish/script.rpym
new file mode 100644
index 0000000..b4819f6
--- /dev/null
+++ b/launcher/game/tl/spanish/script.rpym
@@ -0,0 +1,30 @@
+# Coloca el código de tu juego en este archivo.
+
+# Declara los personajes usados en el juego como en el ejemplo:
+
+define e = Character("Eileen")
+
+
+# El juego comienza aquí.
+
+label start:
+
+    # Muestra una imagen de fondo:
+
+    scene bg room
+
+    # Muestra un personaje:
+
+    show eileen happy
+
+    # Presenta las líneas del diálogo.
+
+    "¡Hola, mundo!"
+
+    e "Has creado un nuevo juego Ren'Py."
+
+    e "Añade una historia, imágenes y música, ¡y puedes presentarlo al mundo!"
+
+    # Finaliza el juego:
+
+    return
diff --git a/launcher/game/tl/spanish/translations.rpy b/launcher/game/tl/spanish/translations.rpy
deleted file mode 100644
index 179efc0..0000000
--- a/launcher/game/tl/spanish/translations.rpy
+++ /dev/null
@@ -1,33 +0,0 @@
-translate spanish strings:
-
-    # game/translations.rpy:10
-    old "Create or Update Translations"
-    new "Crear o Actualizar Traducciones"
-
-    # game/translations.rpy:10
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Por favor introduce el nombre del idioma para el que desea crear o actualizar una traducción."
-
-    # game/translations.rpy:15
-    old "The language name can not be the empty string."
-    new "El nombre del idioma no puede estar vacío."
-
-    # game/translations.rpy:26
-    old "Ren'Py is generating translations...."
-    new "Ren'Py está generando las traducciones..."
-
-    # game/translations.rpy:30
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py ha terminado de generar las traducciones [language]"
-
-    # game/translations.rpy:44
-    old "What format would you like for the extracted dialogue?"
-    new "¿Qué formato te gustaría para los diálogos extraidos?"
-
-    # game/translations.rpy:56
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py está extrayendo los diálogos..."
-
-    # game/translations.rpy:60
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py ha terminado de extraer los diálogos. Los diálogo extraídos se pueden encontrar en el dialogue.[format] en el directorio base."
diff --git a/launcher/game/tl/spanish/updater.rpy b/launcher/game/tl/spanish/updater.rpy
deleted file mode 100644
index 438c0e0..0000000
--- a/launcher/game/tl/spanish/updater.rpy
+++ /dev/null
@@ -1,94 +0,0 @@
-translate spanish strings:
-
-    # game/updater.rpy:54
-    old "Select Update Channel"
-    new "Selecciona el Canal de Actualización"
-
-    # game/updater.rpy:65
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "El canal de actualización controla la versión de Ren'Py que el actualizador descargará. Por favor selecciona un canal de actualización:"
-
-    # game/updater.rpy:70
-    old "Release"
-    new "Release"
-
-    # game/updater.rpy:76
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Recomendado.{/b} La versión the Ren'Py que se recomienda usar en todos los juegos recién liberados."
-
-    # game/updater.rpy:81
-    old "Prerelease"
-    new "Prerelease"
-
-    # game/updater.rpy:87
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Una vista previa de la próxima versión de Ren'Py que puede ser utilizada para probar y aprovechar las nuevas características, pero no para las versiones finales de los juegos."
-
-    # game/updater.rpy:93
-    old "Experimental"
-    new "Experimental"
-
-    # game/updater.rpy:99
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Versiones experimentales de Ren'Py. No debes seleccionar el canal a menos que te lo pida un desarrollador de Ren'Py."
-
-    # game/updater.rpy:106
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:112
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Versión de desarrollo de Ren'Py. Puede tener las últimas características o puede no funcionar."
-
-    # game/updater.rpy:119
-    old "An error has occured:"
-    new "Ha ocurrido un error:"
-
-    # game/updater.rpy:121
-    old "Checking for updates."
-    new "Comprobando actualizaciones."
-
-    # game/updater.rpy:123
-    old "Ren'Py is up to date."
-    new "Ren'Py está actualizado."
-
-    # game/updater.rpy:125
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] ahora está disponible. ¿Quieres instalarla?"
-
-    # game/updater.rpy:127
-    old "Preparing to download the update."
-    new "Preparando para descargar la actualización."
-
-    # game/updater.rpy:129
-    old "Downloading the update."
-    new "Descargando la actualización."
-
-    # game/updater.rpy:131
-    old "Unpacking the update."
-    new "Descomprimiendo la actualización."
-
-    # game/updater.rpy:133
-    old "Finishing up."
-    new "Finalizar."
-
-    # game/updater.rpy:135
-    old "The update has been installed. Ren'Py will restart."
-    new "La actualización se ha instalado. Ren'Py se reiniciará."
-
-    # game/updater.rpy:137
-    old "The update has been installed."
-    new "La actualización se ha instalado."
-
-    # game/updater.rpy:139
-    old "The update was cancelled."
-    new "Se ha cancelado la actualización."
-
-    # game/updater.rpy:156
-    old "Ren'Py Update"
-    new "Actualizar Ren'Py"
-
-    # game/updater.rpy:162
-    old "Proceed"
-    new "Seguir"
-
diff --git a/launcher/game/tl/traditional_chinese/DroidSansFallback-LICENSE b/launcher/game/tl/traditional_chinese/DroidSansFallback-LICENSE
deleted file mode 100644
index 9968855..0000000
--- a/launcher/game/tl/traditional_chinese/DroidSansFallback-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-DroidSansFallback.ttf is destributed under Apache License 2.0.
---------------------------------
-Copyright (C) 2008 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-  
-     http://www.apache.org/licenses/LICENSE-2.0
-  
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-##########
-
-This directory contains the fonts for the platform. They are licensed
-under the Apache 2 license.
\ No newline at end of file
diff --git a/launcher/game/tl/traditional_chinese/about.rpy b/launcher/game/tl/traditional_chinese/about.rpy
deleted file mode 100644
index 5cef02f..0000000
--- a/launcher/game/tl/traditional_chinese/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/about.rpy:39
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:43
-    old "View license"
-    new "檢視許可證"
-
-    # game/about.rpy:45
-    old "Back"
-    new "返回"
-
diff --git a/launcher/game/tl/traditional_chinese/add_file.rpy b/launcher/game/tl/traditional_chinese/add_file.rpy
deleted file mode 100644
index 653df8b..0000000
--- a/launcher/game/tl/traditional_chinese/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "檔案名稱"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "請輸入需要建立的腳本名稱。"
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "檔案名稱必須以 .rpy 為副檔名。"
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "該檔已存在。"
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "# Ren'Py 將自動載入以 .rpy 結尾的腳本。若要使用\n# 檔案,從其它檔案中定義一個標籤跳轉到該檔案。\n"
-
diff --git a/launcher/game/tl/traditional_chinese/android.rpy b/launcher/game/tl/traditional_chinese/android.rpy
deleted file mode 100644
index 6c564f1..0000000
--- a/launcher/game/tl/traditional_chinese/android.rpy
+++ /dev/null
@@ -1,155 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "要建立 Android 套件,請下載 RAPT,並解壓縮到 Ren'Py 目錄下。然後重新啟動 Ren'Py 啟動器。"
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "需要一個 32 位元的 Java 開發套件(JDK)來在 Windows 中建立 Android 套件。JDK 不同於 JRE,所以您可能有 Java 但不包含 JDK。\n\n請 {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}下載并安裝 JDK{/a},然後重新啟動 Ren'Py 啟動器。"
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT 已經安裝了,但是您還需要安裝 Android SDK 才可以建立 Android 套件。選擇安裝 SDK 來實現它。"
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT 已經安裝了,但是 KEY 尚未設定。請建立一個新的 KEY,或者恢複 android.keystore。"
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "當前專案尚未配置。使用「設定」,在建設之前配置它。"
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "選擇「建立」來建立當前專案,或者選擇「建立 & 安裝」來添加到一個 Android 裝置中建立並安裝。"
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "模擬一臺 Android 手機。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。Esc 按鍵映射為手機的選單鍵,PageUp 鍵映射為手機的返回鍵。"
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "模擬一個 Android 平板。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。Esc 按鍵映射為平板的選單鍵,PageUp 鍵映射為平板的返回鍵。"
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "模擬一臺基於 Android 電視,像 OUYA 或者 TV。\n\n控制器的輸入按鍵會映射為方向鍵,Enter 按鍵映射為 select 按鍵,Esc 按鍵映射為選單鍵,PageUp 按鍵被映射為返回鍵。"
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "下載和安裝 Android SDK 以及支援套件。可選擇性地設定產生的 keys 來簽署套件。"
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "設定套件名稱,版本以及其它關於專案的資訊。"
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "在編輯器中開啟包含 Google Play keys 的檔案。\n\n這是在應用程式需要一個擴展的 APK 套件時才需要。閱讀檔案來瞭解更多細節。"
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "建立 Android 套件。"
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "建立 Android 套件,並安裝到已連線到電腦的 Android 裝置中。"
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "建立 Android 套件,並安裝到已連線到電腦的 Android 裝置中,然後啟動您的裝置上的應用程式。"
-
-    # game/android.rpy:48
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "在 TCP/IP 模式下運行 ADB Android 裝置。"
-
-    # game/android.rpy:49
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "在 TCP/IP 模式下運行 ADB Android 裝置,並斷開連接。"
-
-    # game/android.rpy:253
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:273
-    old "Emulation:"
-    new "模擬:"
-
-    # game/android.rpy:282
-    old "Phone"
-    new "手機"
-
-    # game/android.rpy:286
-    old "Tablet"
-    new "平板"
-
-    # game/android.rpy:290
-    old "Television"
-    new "電視"
-
-    # game/android.rpy:302
-    old "Build:"
-    new "建立:"
-
-    # game/android.rpy:310
-    old "Install SDK & Create Keys"
-    new "安裝 SDK & 創建 Keys"
-
-    # game/android.rpy:314
-    old "Configure"
-    new "設定"
-
-    # game/android.rpy:318
-    old "Build Package"
-    new "建立套件"
-
-    # game/android.rpy:322
-    old "Build & Install"
-    new "建立 & 安裝"
-
-    # game/android.rpy:326
-    old "Build, Install & Launch"
-    new "建立,安裝 & 啟動"
-
-    # game/android.rpy:337
-    old "Other:"
-    new "其他:"
-
-    # game/android.rpy:345
-    old "Remote ADB Connect"
-    new "遠端 ADB 連接"
-
-    # game/android.rpy:349
-    old "Remote ADB Disconnect"
-    new "斷開遠端 ADB 連接"
-
-    # game/android.rpy:382
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "在包裝 Android 應用程式前,您須下載 RAPT(Ren'Py Android Packaging Tool),Ren'Py 的 Android 包裝程式。您要現在下載 RAPT 嗎?"
-
-    # game/android.rpy:435
-    old "Remote ADB Address"
-    new "遠端 ADB 位址"
-
-    # game/android.rpy:435
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "「192.168.1.143:5555」是連接裝置的 IP 位址和埠的輸入形式。請鍵入裝置的 IP 位址和埠來連接。注意,確保裝置支援遠端 ADB,然後鍵入位址和埠來使用。"
-
-    # game/android.rpy:447
-    old "Invalid remote ADB address"
-    new "遠端 ADB 位址無效"
-
-    # game/android.rpy:447
-    old "The address must contain one exactly one ':'."
-    new "位址必須包含一個精確的 ':'。"
-
-    # game/android.rpy:451
-    old "The host may not contain whitespace."
-    new "主機位址不能包含空格。"
-
-    # game/android.rpy:457
-    old "The port must be a number."
-    new "埠必須是數位。"
-
diff --git a/launcher/game/tl/traditional_chinese/choose_directory.rpy b/launcher/game/tl/traditional_chinese/choose_directory.rpy
deleted file mode 100644
index 13b5f0f..0000000
--- a/launcher/game/tl/traditional_chinese/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py 無法運行 python 的 tkinter 來選擇專案目錄。請安裝 python-tk 或 tkinter。"
-
diff --git a/launcher/game/tl/traditional_chinese/choose_theme.rpy b/launcher/game/tl/traditional_chinese/choose_theme.rpy
deleted file mode 100644
index 6b34379..0000000
--- a/launcher/game/tl/traditional_chinese/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/choose_theme.rpy:303
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "無法變更介面主題。Options.rpy 也許改變了太多。"
-
-    # game/choose_theme.rpy:368
-    old "Display"
-    new "Display"
-
-    # game/choose_theme.rpy:369
-    old "Window"
-    new "Window"
-
-    # game/choose_theme.rpy:370
-    old "Fullscreen"
-    new "Fullscreen"
-
-    # game/choose_theme.rpy:371
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:378
-    old "Sound Volume"
-    new "Sound Volume"
-
-    # game/choose_theme.rpy:412
-    old "Choose Theme"
-    new "Choose Theme"
-
-    # game/choose_theme.rpy:425
-    old "Theme"
-    new "介面主題"
-
-    # game/choose_theme.rpy:449
-    old "Color Scheme"
-    new "色彩配置"
-
-    # game/choose_theme.rpy:480
-    old "Continue"
-    new "繼續"
-
diff --git a/launcher/game/tl/traditional_chinese/common.rpy b/launcher/game/tl/traditional_chinese/common.rpy
index a191e3d..cd0dad2 100644
--- a/launcher/game/tl/traditional_chinese/common.rpy
+++ b/launcher/game/tl/traditional_chinese/common.rpy
@@ -1,545 +1,335 @@
 
 translate traditional_chinese strings:
 
-    # renpy/common/00action_file.rpy:142
-    old "%b %d, %H:%M"
-    new "%m月%d日, %H:%M"
-
-    # renpy/common/00action_file.rpy:621
-    old "Quick save complete."
-    new "快速儲存。"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/00console.rpy:179
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "%(version)s 控制臺, 作者: Shiz, C, delta\n"
-
-    # renpy/common/00console.rpy:180
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "按 <esc> 來退出控制臺。輸入 help 來檢視說明。\n"
-
-    # renpy/common/00console.rpy:184
-    old "Ren'Py script enabled."
-    new "使用 Ren'Py 腳本。"
-
-    # renpy/common/00console.rpy:186
-    old "Ren'Py script disabled."
-    new "禁用 Ren'Py 腳本。"
-
-    # renpy/common/00console.rpy:392
-    old "help: show this help"
-    new "help: 顯示說明資訊"
-
-    # renpy/common/00console.rpy:397
-    old "commands:\n"
-    new "命令列:\n"
-
-    # renpy/common/00console.rpy:407
-    old " <renpy script statement>: run the statement\n"
-    new "<Ren'py 腳本語句>: 運行語句\n"
-
-    # renpy/common/00console.rpy:409
-    old " <python expression or statement>: run the expression or statement"
-    new " <Python 運算式或語句>: 運行運算式或語句"
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00console.rpy:417
-    old "clear: clear the console history"
-    new "clear: 清除控制臺歷史記錄"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-    # renpy/common/00console.rpy:421
-    old "exit: exit the console"
-    new "exit: 離開控制臺"
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00console.rpy:429
-    old "load <slot>: loads the game from slot"
-    new "load <檔位>: 從檔位載入遊戲"
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00console.rpy:442
-    old "save <slot>: saves the game in slot"
-    new "save <檔位>: 保存遊戲到檔位"
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00console.rpy:453
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: 重新載入遊戲,並重新整理腳本"
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00console.rpy:461
-    old "watch <expression>: watch a python expression"
-    new "watch <運算式>: 監視一個 python 運算式"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00console.rpy:470
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <運算式>: 停止監視某個運算式"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
-    # renpy/common/00console.rpy:478
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: 停止監視索引運算式"
-
-    # renpy/common/00console.rpy:484
-    old "jump <label>: jumps to label"
-    new "jump <標籤>: 跳移至標籤"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/00gallery.rpy:561
-    old "Image [index] of [count] locked."
-    new "[count] 個圖片中的第 [index] 個圖片被鎖定。"
-
-    # renpy/common/00gallery.rpy:581
-    old "prev"
-    new "上一頁"
-
-    # renpy/common/00gallery.rpy:582
-    old "next"
-    new "下一頁"
-
-    # renpy/common/00gallery.rpy:583
-    old "slideshow"
-    new "幻燈片"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-    # renpy/common/00gallery.rpy:584
-    old "return"
-    new "返回"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-translate traditional_chinese strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00gltest.rpy:68
-    old "Graphics Acceleration"
-    new "圖形加速"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00gltest.rpy:72
-    old "Automatically Choose"
-    new "自動選擇"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00gltest.rpy:77
-    old "Force Angle/DirectX Renderer"
-    new "強制 Angle/DirectX 渲染"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gltest.rpy:81
-    old "Force OpenGL Renderer"
-    new "強制 OpenGL 渲染"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gltest.rpy:85
-    old "Force Software Renderer"
-    new "強制軟體渲染"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gltest.rpy:91
-    old "Changes will take effect the next time this program is run."
-    new "變更將會在下次啟動程式時生效。"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gltest.rpy:95
-    old "Quit"
-    new "離開"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gltest.rpy:100
-    old "Return"
-    new "返回"
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
-    # renpy/common/00gltest.rpy:130
-    old "Performance Warning"
-    new "效能警告"
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-    # renpy/common/00gltest.rpy:135
-    old "This computer is using software rendering."
-    new "該電腦正在使用軟體渲染。"
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:137
-    old "This computer is not using shaders."
-    new "該電腦沒有使用著色器"
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:139
-    old "This computer is displaying graphics slowly."
-    new "該電腦圖形顯示緩慢。"
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:141
-    old "This computer has a problem displaying graphics: [problem]."
-    new "該電腦圖形顯示出錯:[problem]。"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:146
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "目前的圖形驅動程式版本可能過舊或者運作不正確。這樣會導致圖形顯示緩慢或者錯誤。更新 DirectX 可能會解決該問題。"
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-    # renpy/common/00gltest.rpy:148
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "目前圖形驅動程式版本可能過舊或者運作不正確。這樣會導致圖形顯示緩慢或者錯誤。"
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-    # renpy/common/00gltest.rpy:153
-    old "Update DirectX"
-    new "更新 DirectX"
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00gltest.rpy:159
-    old "Continue, Show this warning again"
-    new "繼續,下次再顯示此警告"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-    # renpy/common/00gltest.rpy:163
-    old "Continue, Don't show warning again"
-    new "繼續,不再顯示此警告"
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00gltest.rpy:189
-    old "Updating DirectX."
-    new "正在更新 DirectX。"
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
 
-    # renpy/common/00gltest.rpy:193
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "DirectX 線上安裝已啟動。將會最小化到狀態列中。請按照說明安裝 DirectX。"
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
 
-    # renpy/common/00gltest.rpy:197
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b}警告:{/b} Microsoft's DirectX 線上安裝程式會預設安裝 Bing 瀏覽器工具列。如果您不需要安裝這個工具列,請取消勾選對應選項。"
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-    # renpy/common/00gltest.rpy:201
-    old "When setup finishes, please click below to restart this program."
-    new "當安裝完成後請點選下方來重新啟動應用程式。"
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
 
-    # renpy/common/00gltest.rpy:203
-    old "Restart"
-    new "重新啟動"
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
 
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
 
-translate traditional_chinese strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
-    # renpy/common/00keymap.rpy:206
-    old "Saved screenshot as %s."
-    new "儲存螢幕截圖為 %s。"
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%m月%d日, %H:%M"
 
-translate traditional_chinese strings:
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "快速儲存。"
 
-    # renpy/common/00layout.rpy:444
+    # 00gui.rpy:227
     old "Are you sure?"
     new "是否確認?"
 
-    # renpy/common/00layout.rpy:445
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "您確定您要刪掉這份存檔嗎?"
 
-    # renpy/common/00layout.rpy:446
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
-    new "您確定您要覆寫您的存檔嗎?"
+    new "您確定您要覆寫您的存檔?"
 
-    # renpy/common/00layout.rpy:447
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "載入將會失去所有未儲存的進度。\n您確定您要這麼做嗎?"
 
-    # renpy/common/00layout.rpy:448
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "您確定您要離開嗎?"
 
-    # renpy/common/00layout.rpy:449
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "您確定您想回到標題畫面嗎?\n這將使您失去所有未儲存的進度。"
 
-    # renpy/common/00layout.rpy:450
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "是否確定開始略過?"
 
-    # renpy/common/00layout.rpy:451
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "是否確定跳到下一個選項?"
 
-    # renpy/common/00layout.rpy:452
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "是否確定略過未看過的訊息或下一選項?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "儲存螢幕截圖為 %s。"
 
-translate traditional_chinese strings:
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-    # renpy/common/00library.rpy:149
-    old "Skip Mode"
-    new "略過對話模式"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
-    # renpy/common/00library.rpy:152
-    old "Fast Skip Mode"
-    new "快速略過對話模式"
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "略過對話模式"
 
-translate traditional_chinese strings:
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:387
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "Clipboard voicing 已啟用。按 'shift+C' 禁用"
 
-    # renpy/common/00preferences.rpy:389
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "Self-voicing 已啟用。按 'v' 禁用"
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate traditional_chinese strings:
-
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "Ren'Py 的更新不支援在行動裝置上使用。"
 
-    # renpy/common/00updater.rpy:478
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "正在類比錯誤。"
 
-    # renpy/common/00updater.rpy:654
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "此專案不支援更新,或者更新狀態檔已被刪除。"
 
-    # renpy/common/00updater.rpy:668
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "此帳戶不具有執行更新的權限。"
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "此帳戶沒有更新日誌的寫入權限。"
 
-    # renpy/common/00updater.rpy:696
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "無法驗證更新簽名。"
 
-    # renpy/common/00updater.rpy:956
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "不下載更新檔。"
 
-    # renpy/common/00updater.rpy:974
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "無法驗證更新檔案 — 它可能已損壞。"
 
-    # renpy/common/00updater.rpy:1030
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "正在解壓缩 {},未知類型 {}。"
 
-    # renpy/common/00updater.rpy:1380
+    # 00updater.rpy:1393
     old "Updater"
     new "更新"
 
-    # renpy/common/00updater.rpy:1389
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "該程式已是最新版本。"
 
-    # renpy/common/00updater.rpy:1391
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] 已釋出。是否確認安裝?"
 
-    # renpy/common/00updater.rpy:1393
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "正在準備下載更新。"
 
-    # renpy/common/00updater.rpy:1395
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "正在下載更新。"
 
-    # renpy/common/00updater.rpy:1397
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "解壓縮更新檔案。"
 
-    # renpy/common/00updater.rpy:1401
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "該更新檔案已安裝,程式將會重新啟動。"
 
-    # renpy/common/00updater.rpy:1403
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "已完成更新。"
 
-    # renpy/common/00updater.rpy:1405
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "已取消更新。"
 
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "[count] 個圖片中的第 [index] 個圖片被鎖定。"
 
-translate traditional_chinese strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "空白檔位"
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
+    # 00gallery.rpy:583
+    old "prev"
     new "上一頁"
 
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
+    # 00gallery.rpy:584
+    old "next"
     new "下一頁"
 
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "幻燈片"
 
-translate traditional_chinese strings:
-
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "遊戲桿映射"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "開發者選單"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "重新載入遊戲 (Shift+R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "控制臺 (Shift+O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "變數觀察器"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "介面主題測試"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "圖片座標撿選器"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "檔案清單"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "顯示圖片載入記錄"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "隱藏圖片載入記錄"
-
-    # renpy/common/_developer/developer.rpym:150
-    old "No variables have changed since the game started."
-    new "遊戲開始至此沒有任何變數被改變。"
-
-    # renpy/common/_developer/developer.rpym:153
-    old "Return to the developer menu"
-    new "回到開發者選單"
-
-    # renpy/common/_developer/developer.rpym:398
-    old "Rectangle: %r"
-    new "矩形區域: %r"
-
-    # renpy/common/_developer/developer.rpym:403
-    old "Mouse position: %r"
-    new "滑鼠位置: %r"
-
-    # renpy/common/_developer/developer.rpym:408
-    old "Right-click or escape to quit."
-    new "點選滑鼠右鍵或者按 Esc 鍵來退出。"
-
-    # renpy/common/_developer/developer.rpym:437
-    old "Rectangle copied to clipboard."
-    new "選擇區域複製到剪貼簿。"
-
-    # renpy/common/_developer/developer.rpym:440
-    old "Position copied to clipboard."
-    new "選擇位置複製到剪貼簿。"
-
-    # renpy/common/_developer/developer.rpym:471
-    old "Done"
-    new "完成"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/_developer/inspector.rpym:46
-    old "Displayable Inspector"
-    new "Displayable 檢閱器"
-
-    # renpy/common/_developer/inspector.rpym:52
-    old "Nothing to inspect."
-    new "沒有東西被檢閱"
-
-    # renpy/common/_developer/inspector.rpym:70
-    old "Size"
-    new "大小"
-
-    # renpy/common/_developer/inspector.rpym:74
-    old "Style"
-    new "風格"
-
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "位置"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "Inspecting Styles of [displayable_name!q]"
-    new "檢閱 [displayable_name!q] 的風格"
-
-    # renpy/common/_developer/inspector.rpym:155
-    old "displayable:"
-    new "Displayable:"
-
-    # renpy/common/_developer/inspector.rpym:162
-    old "        (no properties affect the displayable)"
-    new "        (沒有偏好的可顯示屬性)"
-
-    # renpy/common/_developer/inspector.rpym:164
-    old "        (default properties omitted)"
-    new "        (省略預設屬性)"
-
-    # renpy/common/_developer/inspector.rpym:206
-    old "<repr() failed>"
-    new "<repr() 失敗>"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/_errorhandling.rpym:450
-    old "An exception has occurred."
-    new "發生一個異常狀況。"
-
-    # renpy/common/_errorhandling.rpym:476
-    old "Rollback"
-    new "回滾"
-
-    # renpy/common/_errorhandling.rpym:478
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "嘗試回滾到先前的狀態,使您可以存檔或者選擇不同選項。"
-
-    # renpy/common/_errorhandling.rpym:481
-    old "Ignore"
-    new "忽略"
-
-    # renpy/common/_errorhandling.rpym:483
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "忽略異常,讓您可以繼續。這通常會產生額外的錯誤。"
-
-    # renpy/common/_errorhandling.rpym:486
-    old "Reload"
-    new "重新載入"
-
-    # renpy/common/_errorhandling.rpym:488
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "從硬碟重新載入遊戲,請您儲存遊戲狀態。"
-
-    # renpy/common/_errorhandling.rpym:490
-    old "Open Traceback"
-    new "開啟回溯"
-
-    # renpy/common/_errorhandling.rpym:492
-    old "Opens the traceback.txt file in a text editor."
-    new "在編輯器中開啟回溯檔案。"
-
-    # renpy/common/_errorhandling.rpym:498
-    old "Quits the game."
-    new "離開遊戲。"
-
-    # renpy/common/_errorhandling.rpym:525
-    old "Parsing the script failed."
-    new "解析腳本失敗。"
-
-    # renpy/common/_errorhandling.rpym:552
-    old "Open Parse Errors"
-    new "開啟解析錯誤"
-
-    # renpy/common/_errorhandling.rpym:554
-    old "Opens the errors.txt file in a text editor."
-    new "在編輯器中開啟解析錯誤檔案。"
-
-
-translate traditional_chinese strings:
-
-    # renpy/common/_layout/classic_load_save.rpym:170
-    old "a"
-    new "a"
-
-    # renpy/common/_layout/classic_load_save.rpym:179
-    old "q"
-    new "q"
+    # 00gallery.rpy:586
+    old "return"
+    new "返回"
 
diff --git a/launcher/game/tl/traditional_chinese/developer.rpy b/launcher/game/tl/traditional_chinese/developer.rpy
new file mode 100644
index 0000000..fbad097
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/developer.rpy
@@ -0,0 +1,179 @@
+
+translate traditional_chinese strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "開發者選單"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "重新載入遊戲 (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "控制臺 (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "變數觀察器"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "介面主題測試"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "圖片座標撿選器"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "檔案清單"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "顯示圖片載入記錄"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "隱藏圖片載入記錄"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "沒有東西被檢閱"
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "回到開發者選單"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "矩形區域: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "滑鼠位置: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "點選滑鼠右鍵或者按 Esc 鍵來退出。"
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "選擇區域複製到剪貼簿。"
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "選擇位置複製到剪貼簿。"
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable 檢閱器"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "大小"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "風格"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "位置"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "檢閱 [displayable_name!q] 的風格"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "Displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (沒有偏好的可顯示屬性)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (省略預設屬性)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() 失敗>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "按 <esc> 來退出控制臺。輸入 help 來檢視說明。\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "使用 Ren'Py 腳本。"
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "禁用 Ren'Py 腳本。"
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: 顯示說明資訊"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "命令列:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new "<Ren'py 腳本語句>: 運行語句\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <Python 運算式或語句>: 運行運算式或語句"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: 清除控制臺歷史記錄"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: 離開控制臺"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <檔位>: 從檔位載入遊戲"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <檔位>: 保存遊戲到檔位"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: 重新載入遊戲,並重新整理腳本"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <運算式>: 監視一個 python 運算式"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <運算式>: 停止監視某個運算式"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: 停止監視索引運算式"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <標籤>: 跳移至標籤"
+
diff --git a/launcher/game/tl/traditional_chinese/distribute.rpy b/launcher/game/tl/traditional_chinese/distribute.rpy
deleted file mode 100644
index be653af..0000000
--- a/launcher/game/tl/traditional_chinese/distribute.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/distribute.rpy:335
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new "建立釋出版失敗:\n\n build.directory_name 變數可能包含空格,冒號或分號。"
-
-    # game/distribute.rpy:381
-    old "No packages are selected, so there's nothing to do."
-    new "沒有選擇套件,沒有可以處理的事情。"
-
-    # game/distribute.rpy:386
-    old "Scanning project files..."
-    new "掃描專案檔案..."
-
-    # game/distribute.rpy:396
-    old "Scanning Ren'Py files..."
-    new "掃描 Ren'Py 檔案..."
-
-    # game/distribute.rpy:444
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new "所有套件已被建立。\n\n由於含有授權資訊存在,因此在 Windows 中不支援解開和重新包裝 Linux 及 Mac 的套件。"
-
-    # game/distribute.rpy:568
-    old "Archiving files..."
-    new "壓縮檔案..."
-
-    # game/distribute.rpy:845
-    old "Writing the [variant] [format] package."
-    new "寫入 [variant] [format] 套件。"
-
-    # game/distribute.rpy:858
-    old "Making the [variant] update zsync file."
-    new "新增 [variant] 更新 zsync 檔案。"
-
-    # game/distribute.rpy:957
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new "完成處理 {b}[complete]{/b} ,共 {b}[total]{/b}個檔案。"
-
diff --git a/launcher/game/tl/traditional_chinese/distribute_gui.rpy b/launcher/game/tl/traditional_chinese/distribute_gui.rpy
deleted file mode 100644
index aaac2ef..0000000
--- a/launcher/game/tl/traditional_chinese/distribute_gui.rpy
+++ /dev/null
@@ -1,63 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "建立釋出版:[project.current.name!q]"
-
-    # game/distribute_gui.rpy:171
-    old "Directory Name:"
-    new "目錄名稱:"
-
-    # game/distribute_gui.rpy:175
-    old "Executable Name:"
-    new "執行檔案名稱:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "動作:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "編輯 options.rpy"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "向 call 語句添加 from 從句, 一次"
-
-    # game/distribute_gui.rpy:195
-    old "Refresh"
-    new "重新整理"
-
-    # game/distribute_gui.rpy:212
-    old "Build Packages:"
-    new "建立套件:"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "選項:"
-
-    # game/distribute_gui.rpy:236
-    old "Build Updates"
-    new "建立更新檔"
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "向 call 語句添加 from 從句"
-
-    # game/distribute_gui.rpy:242
-    old "Build"
-    new "建立"
-
-    # game/distribute_gui.rpy:246
-    old "Adding from clauses to call statements that do not have them."
-    new "正在向 call 語句添加缺失的 from 從句"
-
-    # game/distribute_gui.rpy:267
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "當運行專案時發生了錯誤。在開始釋出前請確保專案運行無誤。"
-
-    # game/distribute_gui.rpy:284
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "您的專案不包含建置資訊。是否加入建置資訊到 options.rpy?"
-
diff --git a/launcher/game/tl/traditional_chinese/editor.rpy b/launcher/game/tl/traditional_chinese/editor.rpy
deleted file mode 100644
index efa38cb..0000000
--- a/launcher/game/tl/traditional_chinese/editor.rpy
+++ /dev/null
@@ -1,55 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}推薦{/b} 一個有簡單易用介面和功能的測試版編輯器能夠幫助開發,例如拼字的校對功能。Editra 目前缺乏中文、日文,韓文的輸入的 IME 支援。"
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}推薦{/b} 一個有簡單易用的介面和功能的測試版編輯器能夠幫助開發,例如拼字的校對功能。Editra 現在沒有中文,日文,韓文的輸入功能。在 linux 中 Editra 需要 wxPython(模組支援)。"
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "這可能是因為 wxPython 沒有被安裝在當前系統中而發生的。"
-
-    # game/editor.rpy:169
-    old "Up to 22 MB download required."
-    new "22 MB 需要下載。"
-
-    # game/editor.rpy:182
-    old "A mature editor that requires Java."
-    new "一個成熟的編輯器,它需要 Java。"
-
-    # game/editor.rpy:182
-    old "1.8 MB download required."
-    new "1.8 MB 需要下載。"
-
-    # game/editor.rpy:182
-    old "This may have occured because Java is not installed on this system."
-    new "這可能是因為 Java 沒有被安裝在當前系統中而發生的。"
-
-    # game/editor.rpy:191
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "調用作業系統已與 .rpy 檔案關聯的編輯器。"
-
-    # game/editor.rpy:207
-    old "Prevents Ren'Py from opening a text editor."
-    new "防止 Ren'Py 開啟文字編輯器。"
-
-    # game/editor.rpy:359
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "啟動以下編輯器出現異常:\n[exception!q]"
-
-    # game/editor.rpy:457
-    old "Select Editor"
-    new "選擇編輯器"
-
-    # game/editor.rpy:472
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "文字編輯器是您用於編輯 Ren'py 腳本的程式。在這裡您可以選擇 Ren'py 會使用到編輯器。如果選定則編輯器將會自動下載並安裝。"
-
-    # game/editor.rpy:494
-    old "Cancel"
-    new "取消"
-
diff --git a/launcher/game/tl/traditional_chinese/error.rpy b/launcher/game/tl/traditional_chinese/error.rpy
new file mode 100644
index 0000000..c1ecec6
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/error.rpy
@@ -0,0 +1,179 @@
+
+translate traditional_chinese strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "圖形加速"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "自動選擇"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "強制 Angle/DirectX 渲染"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "強制 OpenGL 渲染"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "強制軟體渲染"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "變更將會在下次啟動程式時生效。"
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "效能警告"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "該電腦正在使用軟體渲染。"
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "該電腦沒有使用著色器"
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "該電腦圖形顯示緩慢。"
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "該電腦圖形顯示出錯:[problem]。"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "目前的圖形驅動程式版本可能過舊或者運作不正確。這樣會導致圖形顯示緩慢或者錯誤。更新 DirectX 可能會解決該問題。"
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "目前圖形驅動程式版本可能過舊或者運作不正確。這樣會導致圖形顯示緩慢或者錯誤。"
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "更新 DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "繼續,下次再顯示此警告"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "繼續,不再顯示此警告"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "正在更新 DirectX。"
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX 線上安裝已啟動。將會最小化到狀態列中。請按照說明安裝 DirectX。"
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}警告:{/b} Microsoft's DirectX 線上安裝程式會預設安裝 Bing 瀏覽器工具列。如果您不需要安裝這個工具列,請取消勾選對應選項。"
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "當安裝完成後請點選下方來重新啟動應用程式。"
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "重新啟動"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "開啟回溯"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "在編輯器中開啟回溯檔案。"
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "發生一個異常狀況。"
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "回滾"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "嘗試回滾到先前的狀態,使您可以存檔或者選擇不同選項。"
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "忽略"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "忽略異常,讓您可以繼續。這通常會產生額外的錯誤。"
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "重新載入"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "從硬碟重新載入遊戲,請您儲存遊戲狀態。"
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "離開遊戲。"
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "解析腳本失敗。"
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "開啟解析錯誤"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "在編輯器中開啟解析錯誤檔案。"
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
diff --git a/launcher/game/tl/traditional_chinese/front_page.rpy b/launcher/game/tl/traditional_chinese/front_page.rpy
deleted file mode 100644
index 88c2cb1..0000000
--- a/launcher/game/tl/traditional_chinese/front_page.rpy
+++ /dev/null
@@ -1,115 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "開啟 [text] 目錄。"
-
-    # game/front_page.rpy:91
-    old "PROJECTS:"
-    new "專案列表:"
-
-    # game/front_page.rpy:93
-    old "refresh"
-    new "重新整理"
-
-    # game/front_page.rpy:120
-    old "+ Create New Project"
-    new "+ 新建專案"
-
-    # game/front_page.rpy:132
-    old "Launch Project"
-    new "啟動專案"
-
-    # game/front_page.rpy:148
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-    # game/front_page.rpy:150
-    old "Select project [text]."
-    new "選擇專案 [text]。"
-
-    # game/front_page.rpy:166
-    old "Tutorial"
-    new "Tutorial"
-
-    # game/front_page.rpy:167
-    old "The Question"
-    new "The Question"
-
-    # game/front_page.rpy:183
-    old "Active Project"
-    new "活動專案"
-
-    # game/front_page.rpy:191
-    old "Open Directory"
-    new "開啟目錄"
-
-    # game/front_page.rpy:196
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:197
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:204
-    old "Edit File"
-    new "編輯檔案"
-
-    # game/front_page.rpy:212
-    old "All script files"
-    new "開啟所有檔案"
-
-    # game/front_page.rpy:221
-    old "Navigate Script"
-    new "腳本導航"
-
-    # game/front_page.rpy:232
-    old "Check Script (Lint)"
-    new "檢查腳本 (Lint)"
-
-    # game/front_page.rpy:233
-    old "Change Theme"
-    new "變更介面主題"
-
-    # game/front_page.rpy:234
-    old "Delete Persistent"
-    new "刪除持久性資料"
-
-    # game/front_page.rpy:235
-    old "Force Recompile"
-    new "強制重新編譯"
-
-    # game/front_page.rpy:243
-    old "Build Distributions"
-    new "建立釋出版"
-
-    # game/front_page.rpy:245
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:246
-    old "iOS"
-    new "iOS"
-
-    # game/front_page.rpy:247
-    old "Generate Translations"
-    new "產生翻譯檔"
-
-    # game/front_page.rpy:248
-    old "Extract Dialogue"
-    new "提取對話"
-
-    # game/front_page.rpy:264
-    old "Checking script for potential problems..."
-    new "檢查腳本中的潛在錯誤..."
-
-    # game/front_page.rpy:279
-    old "Deleting persistent data..."
-    new "正在刪除持久性資料..."
-
-    # game/front_page.rpy:287
-    old "Recompiling all rpy files into rpyc files..."
-    new "重編譯所有 rpy 檔案為 rpyc 檔案……"
-
diff --git a/launcher/game/tl/traditional_chinese/gui.rpy b/launcher/game/tl/traditional_chinese/gui.rpy
new file mode 100644
index 0000000..ae40528
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/gui.rpy
@@ -0,0 +1,411 @@
+
+translate traditional_chinese strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/traditional_chinese/interface.rpy b/launcher/game/tl/traditional_chinese/interface.rpy
deleted file mode 100644
index 8446ca5..0000000
--- a/launcher/game/tl/traditional_chinese/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "文件"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "Ren'Py網站"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "Ren'Py遊戲列表"
-
-    # game/interface.rpy:110
-    old "About"
-    new "關於"
-
-    # game/interface.rpy:117
-    old "update"
-    new "更新"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "設定"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "離開"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "確定"
-
-    # game/interface.rpy:194
-    old "No"
-    new "取消"
-
-    # game/interface.rpy:229
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "由於套件格式的限制,非 ASCII 編碼的檔案和目錄將不被支援。"
-
-    # game/interface.rpy:321
-    old "ERROR"
-    new "錯誤"
-
-    # game/interface.rpy:350
-    old "While [what!q], an error occured:"
-    new "[what!q]時,出現錯誤:"
-
-    # game/interface.rpy:350
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:369
-    old "Text input may not contain the {{ or [[ characters."
-    new "文字輸入可能不包含{{ 或 [[ 字元。"
-
-    # game/interface.rpy:374
-    old "File and directory names may not contain / or \\."
-    new "檔案或目錄不包含/或\\。"
-
-    # game/interface.rpy:380
-    old "File and directory names must consist of ASCII characters."
-    new "檔案名稱和目錄名稱必須是 ASCII 字元。"
-
-    # game/interface.rpy:401
-    old "INFORMATION"
-    new "資訊"
-
-    # game/interface.rpy:448
-    old "PROCESSING"
-    new "正在處理"
-
-    # game/interface.rpy:465
-    old "QUESTION"
-    new "問題"
-
-    # game/interface.rpy:478
-    old "CHOICE"
-    new "選擇"
-
diff --git a/launcher/game/tl/traditional_chinese/ios.rpy b/launcher/game/tl/traditional_chinese/ios.rpy
deleted file mode 100644
index cdeeb79..0000000
--- a/launcher/game/tl/traditional_chinese/ios.rpy
+++ /dev/null
@@ -1,99 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "要建立 iOS 套件,請下載 renios,並解壓縮到 Ren'Py 目錄下。然後重新啟動 Ren'Py 啟動器。"
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "從 '選擇目錄' ,請選擇 Xcode 專案所在的目錄。"
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "沒有對應於當前的 Ren'Py 專案 Xcode 專案。請從 '創建 Xcode 專案' 中創建。"
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Xcode 專案已存在。'更新 Xcode 專案' 通過選擇更新到最新的遊戲檔,但要使用 Xcode 構建它,請安裝。"
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "模擬一臺 iPhone。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。"
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "模擬一個 iPad。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。"
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "選擇放置 Xcode 專案的目錄。"
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "創建對應于當前的 Ren'Py 專案 Xcode 專案。"
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "更新 Xcode 專案和最新的遊戲檔案。每次進行時 Ren'py 專案將會變更。"
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "在 Xcode 中開啟 Xcode 專案。"
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "開啟包含 Xcode 專案的目錄。"
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Xcode 專案已存在。你想要重命名舊的專案,並將它替換一個新的嗎?"
-
-    # game/ios.rpy:200
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:229
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:233
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:253
-    old "Select Xcode Projects Directory"
-    new "選擇 Xcode 專案目錄"
-
-    # game/ios.rpy:257
-    old "Create Xcode Project"
-    new "創建 Xcode 專案"
-
-    # game/ios.rpy:261
-    old "Update Xcode Project"
-    new "更新 Xcode 專案"
-
-    # game/ios.rpy:266
-    old "Launch Xcode"
-    new "啟動 Xcode"
-
-    # game/ios.rpy:301
-    old "Open Xcode Projects Directory"
-    new "開啟 Xcode 專案目錄"
-
-    # game/ios.rpy:334
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "在包裝 iOS 應用程式前,您須下載 renios,Ren'Py 的 iOS 包裝程式。您要現在下載 renios 嗎?"
-
-    # game/ios.rpy:343
-    old "XCODE PROJECTS DIRECTORY"
-    new "XCODE PROJECTS DIRECTORY"
-
-    # game/ios.rpy:343
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "請使用 Xcode 的目錄選擇器來選擇專案目錄。\n{b}目錄選擇視窗可能會開啟在本視窗後面。{/b}"
-
-    # game/ios.rpy:348
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py 已經將 Xcode 專案目錄設定為:"
-
diff --git a/launcher/game/tl/traditional_chinese/launcher.rpy b/launcher/game/tl/traditional_chinese/launcher.rpy
new file mode 100644
index 0000000..5171bfe
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate traditional_chinese strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "檢視許可證"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "檔案名稱"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "請輸入需要建立的腳本名稱。"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "檔案名稱必須以 .rpy 為副檔名。"
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "該檔已存在。"
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "# Ren'Py 將自動載入以 .rpy 結尾的腳本。若要使用\n# 檔案,從其它檔案中定義一個標籤跳轉到該檔案。\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "要建立 Android 套件,請下載 RAPT,並解壓縮到 Ren'Py 目錄下。然後重新啟動 Ren'Py 啟動器。"
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "需要一個 32 位元的 Java 開發套件(JDK)來在 Windows 中建立 Android 套件。JDK 不同於 JRE,所以您可能有 Java 但不包含 JDK。\n\n請 {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}下載并安裝 JDK{/a},然後重新啟動 Ren'Py 啟動器。"
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT 已經安裝了,但是您還需要安裝 Android SDK 才可以建立 Android 套件。選擇安裝 SDK 來實現它。"
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT 已經安裝了,但是 KEY 尚未設定。請建立一個新的 KEY,或者恢複 android.keystore。"
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "當前專案尚未配置。使用「設定」,在建設之前配置它。"
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "選擇「建立」來建立當前專案,或者選擇「建立 & 安裝」來添加到一個 Android 裝置中建立並安裝。"
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "模擬一臺 Android 手機。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。Esc 按鍵映射為手機的選單鍵,PageUp 鍵映射為手機的返回鍵。"
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "模擬一個 Android 平板。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。Esc 按鍵映射為平板的選單鍵,PageUp 鍵映射為平板的返回鍵。"
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "模擬一臺基於 Android 電視,像 OUYA 或者 TV。\n\n控制器的輸入按鍵會映射為方向鍵,Enter 按鍵映射為 select 按鍵,Esc 按鍵映射為選單鍵,PageUp 按鍵被映射為返回鍵。"
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "下載和安裝 Android SDK 以及支援套件。可選擇性地設定產生的 keys 來簽署套件。"
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "設定套件名稱,版本以及其它關於專案的資訊。"
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "在編輯器中開啟包含 Google Play keys 的檔案。\n\n這是在應用程式需要一個擴展的 APK 套件時才需要。閱讀檔案來瞭解更多細節。"
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "建立 Android 套件。"
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "建立 Android 套件,並安裝到已連線到電腦的 Android 裝置中。"
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "建立 Android 套件,並安裝到已連線到電腦的 Android 裝置中,然後啟動您的裝置上的應用程式。"
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "在 TCP/IP 模式下運行 ADB Android 裝置。"
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "在 TCP/IP 模式下運行 ADB Android 裝置,並斷開連接。"
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Retrieves the log from the Android device and writes it to a file."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Copying Android files to distributions directory."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "模擬:"
+
+    # android.rpy:333
+    old "Phone"
+    new "手機"
+
+    # android.rpy:337
+    old "Tablet"
+    new "平板"
+
+    # android.rpy:341
+    old "Television"
+    new "電視"
+
+    # android.rpy:353
+    old "Build:"
+    new "建立:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "安裝 SDK & 創建 Keys"
+
+    # android.rpy:365
+    old "Configure"
+    new "設定"
+
+    # android.rpy:369
+    old "Build Package"
+    new "建立套件"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "建立 & 安裝"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "建立,安裝 & 啟動"
+
+    # android.rpy:388
+    old "Other:"
+    new "其他:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "遠端 ADB 連接"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "斷開遠端 ADB 連接"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "在包裝 Android 應用程式前,您須下載 RAPT(Ren'Py Android Packaging Tool),Ren'Py 的 Android 包裝程式。您要現在下載 RAPT 嗎?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "遠端 ADB 位址"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "「192.168.1.143:5555」是連接裝置的 IP 位址和埠的輸入形式。請鍵入裝置的 IP 位址和埠來連接。注意,確保裝置支援遠端 ADB,然後鍵入位址和埠來使用。"
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "遠端 ADB 位址無效"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "位址必須包含一個精確的 ':'。"
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "主機位址不能包含空格。"
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "埠必須是數位。"
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Retrieving logcat information from device."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py 無法運行 python 的 tkinter 來選擇專案目錄。請安裝 python-tk 或 tkinter。"
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "無法變更介面主題。Options.rpy 也許改變了太多。"
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Choose Theme"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "介面主題"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "色彩配置"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "繼續"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "資訊"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "掃描專案檔案..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "建立釋出版失敗:\n\n build.directory_name 變數可能包含空格,冒號或分號。"
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "沒有選擇套件,沒有可以處理的事情。"
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "掃描 Ren'Py 檔案..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "所有套件已被建立。\n\n由於含有授權資訊存在,因此在 Windows 中不支援解開和重新包裝 Linux 及 Mac 的套件。"
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "壓縮檔案..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "寫入 [variant] [format] 套件。"
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "新增 [variant] 更新 zsync 檔案。"
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "完成處理 {b}[complete]{/b} ,共 {b}[total]{/b}個檔案。"
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "建立釋出版:[project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "目錄名稱:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "執行檔案名稱:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "動作:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "編輯 options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "向 call 語句添加 from 從句, 一次"
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "重新整理"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "建立套件:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "選項:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "建立更新檔"
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "向 call 語句添加 from 從句"
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "強制重新編譯"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "建立"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "正在向 call 語句添加缺失的 from 從句"
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "當運行專案時發生了錯誤。在開始釋出前請確保專案運行無誤。"
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "您的專案不包含建置資訊。是否加入建置資訊到 options.rpy?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}推薦{/b} 一個有簡單易用介面和功能的測試版編輯器能夠幫助開發,例如拼字的校對功能。Editra 目前缺乏中文、日文,韓文的輸入的 IME 支援。"
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}推薦{/b} 一個有簡單易用的介面和功能的測試版編輯器能夠幫助開發,例如拼字的校對功能。Editra 現在沒有中文,日文,韓文的輸入功能。在 linux 中 Editra 需要 wxPython(模組支援)。"
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "這可能是因為 wxPython 沒有被安裝在當前系統中而發生的。"
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "22 MB 需要下載。"
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "一個成熟的編輯器,它需要 Java。"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "1.8 MB 需要下載。"
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "這可能是因為 Java 沒有被安裝在當前系統中而發生的。"
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "調用作業系統已與 .rpy 檔案關聯的編輯器。"
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "防止 Ren'Py 開啟文字編輯器。"
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "啟動以下編輯器出現異常:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "選擇編輯器"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "文字編輯器是您用於編輯 Ren'py 腳本的程式。在這裡您可以選擇 Ren'py 會使用到編輯器。如果選定則編輯器將會自動下載並安裝。"
+
+    # editor.rpy:494
+    old "Cancel"
+    new "取消"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "開啟 [text] 目錄。"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "重新整理"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ 新建專案"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "啟動專案"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "選擇專案 [text]。"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Tutorial"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "The Question"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "活動專案"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "開啟目錄"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "編輯檔案"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "開啟所有檔案"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "腳本導航"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "檢查腳本 (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "變更介面主題"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "刪除持久性資料"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "建立釋出版"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "產生翻譯檔"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "提取對話"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "檢查腳本中的潛在錯誤..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "正在刪除持久性資料..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "重編譯所有 rpy 檔案為 rpyc 檔案……"
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "專案名稱"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "請輸入專案名稱:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "專案名稱不能為空。"
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] 已存在。請選擇不同的名稱。"
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_dir!q] 已存在。請選擇不同的名稱。"
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "文件"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren'Py網站"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Ren'Py遊戲列表"
+
+    # interface.rpy:117
+    old "update"
+    new "更新"
+
+    # interface.rpy:119
+    old "preferences"
+    new "設定"
+
+    # interface.rpy:120
+    old "quit"
+    new "離開"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "由於套件格式的限制,非 ASCII 編碼的檔案和目錄將不被支援。"
+
+    # interface.rpy:327
+    old "ERROR"
+    new "錯誤"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "[what!q]時,出現錯誤:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "文字輸入可能不包含{{ 或 [[ 字元。"
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "檔案或目錄不包含/或\\。"
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "檔案名稱和目錄名稱必須是 ASCII 字元。"
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "正在處理"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "問題"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "選擇"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "要建立 iOS 套件,請下載 renios,並解壓縮到 Ren'Py 目錄下。然後重新啟動 Ren'Py 啟動器。"
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "從 '選擇目錄' ,請選擇 Xcode 專案所在的目錄。"
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "沒有對應於當前的 Ren'Py 專案 Xcode 專案。請從 '創建 Xcode 專案' 中創建。"
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Xcode 專案已存在。'更新 Xcode 專案' 通過選擇更新到最新的遊戲檔,但要使用 Xcode 構建它,請安裝。"
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "模擬一臺 iPhone。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。"
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "模擬一個 iPad。\n\n當按鈕被按下時,觸控輸入會模擬為滑鼠。"
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "選擇放置 Xcode 專案的目錄。"
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "創建對應于當前的 Ren'Py 專案 Xcode 專案。"
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "更新 Xcode 專案和最新的遊戲檔案。每次進行時 Ren'py 專案將會變更。"
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "在 Xcode 中開啟 Xcode 專案。"
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "開啟包含 Xcode 專案的目錄。"
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Xcode 專案已存在。你想要重命名舊的專案,並將它替換一個新的嗎?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "選擇 Xcode 專案目錄"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "創建 Xcode 專案"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "更新 Xcode 專案"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "啟動 Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "開啟 Xcode 專案目錄"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "在包裝 iOS 應用程式前,您須下載 renios,Ren'Py 的 iOS 包裝程式。您要現在下載 renios 嗎?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "XCODE PROJECTS DIRECTORY"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "請使用 Xcode 的目錄選擇器來選擇專案目錄。\n{b}目錄選擇視窗可能會開啟在本視窗後面。{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py 已經將 Xcode 專案目錄設定為:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "導航:[project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "排序:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "按字母順序"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "按檔案"
+
+    # navigation.rpy:182
+    old "natural"
+    new "natural"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "類別:"
+
+    # navigation.rpy:196
+    old "files"
+    new "檔案"
+
+    # navigation.rpy:197
+    old "labels"
+    new "標籤"
+
+    # navigation.rpy:198
+    old "defines"
+    new "定義"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "轉換"
+
+    # navigation.rpy:200
+    old "screens"
+    new "螢幕"
+
+    # navigation.rpy:201
+    old "callables"
+    new "可呼叫"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "待辦事項"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ 加入腳本檔案"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "沒有待辦的事項被發現。\n\n要建立一個包含「# TODO」到您的腳本中。"
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "名稱清單為空。"
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "無法設定專案目錄。放棄。"
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "選擇專案模版"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "請為您新建的專案選擇一個模版。該模版將設定為預設的字型和語言。如果您的所使用的語言沒有被支援,那麼請選擇「english」。"
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "啟動器偏好"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "專案目錄:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "專案資料夾: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "未設定"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "文字編輯器:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "文字編輯器: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "更新頻道:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "導航選項:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "包含私有名稱"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "包含資料庫名稱"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "啟動器選項:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "硬體渲染"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "顯示模板"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "顯示編輯檔節"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "大字體"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "控制臺輸出"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "開啟啟動器專案"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "語言:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "改變腳本後,請按 shift+R 來重新載入您的遊戲。"
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "按 shift+O (the letter) 來進入控制臺。"
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "按 shift+D 來進入開發者選單。"
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "您最近有備份您的專案嗎?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "啟動專案失敗。"
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "請確保您的專案能正常啟動再執行本指令。"
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py 正在掃描專案.."
+
+    # project.rpy:568
+    old "Launching"
+    new "啟動"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "專案目錄"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "請使用目錄選擇器選擇專案目錄。\n{b}目錄選擇視窗可能會開啟在本視窗後面。{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "啟動器會掃描該目錄下的專案,新增的專案也將在該目錄下建置。專案也在該目錄下建立。"
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py 已將專案目錄設定為"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "產生空字串翻譯"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py 正在產生翻譯..."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py 已經完成 [language] 檔案的翻譯。"
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Extract Dialogue: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Format:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Tab-delimited Spreadsheet (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Dialogue Text Only (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Strip text tags from the dialogue."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Escape quotes and other special characters."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Extract all translatable strings, not just dialogue."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py 正在提取對話..."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "選擇更新頻道"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "更新頻道控制 Ren'Py 更新將會下載的版本。請選擇一個更新頻道。"
+
+    # updater.rpy:91
+    old "Release"
+    new "Release"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}推薦{/b} Ren'py 的版本應在所有新釋出的遊戲中使用。"
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Prerelease"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "預覽 Ren'py 的下一個版本,適合用於測試和體驗新功能,但不適合遊戲的最終版本。"
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Experimental"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Ren'py 的實驗版本,除非您被 Ren'py 的開發者要求,否則您不應該選擇此頻道。"
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Nightly"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Ren'Py 最新的開發版本。這可能會擁有最新的功能,或可能根本無法運作。"
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "一個錯誤發生:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "正在檢查更新。"
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py 已是最新版本。"
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "[u.version] 已經可以更新。您要下載它嗎?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "準備下載更新"
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "正在下載更新。"
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "正在解壓縮更新檔案。"
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "即將完成。"
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "已安裝更新。Ren'Py 將會重新啟動。"
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "已安裝更新。"
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "已取消更新。"
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Ren'Py 更新"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "繼續"
+
diff --git a/launcher/game/tl/traditional_chinese/navigation.rpy b/launcher/game/tl/traditional_chinese/navigation.rpy
deleted file mode 100644
index a2e2e4e..0000000
--- a/launcher/game/tl/traditional_chinese/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "導航:[project.current.name]"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "排序:"
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "按字母順序"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "按檔案"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "natural"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "類別:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "檔案"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "標籤"
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "定義"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "轉換"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "螢幕"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "可呼叫"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "待辦事項"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ 加入腳本檔案"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "沒有待辦的事項被發現。\n\n要建立一個包含「# TODO」到您的腳本中。"
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "名稱清單為空。"
-
diff --git a/launcher/game/tl/traditional_chinese/new_project.rpy b/launcher/game/tl/traditional_chinese/new_project.rpy
deleted file mode 100644
index 0007190..0000000
--- a/launcher/game/tl/traditional_chinese/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "選擇專案模版"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "請為您新建的專案選擇一個模版。該模版將設定為預設的字型和語言。如果您的所使用的語言沒有被支援,那麼請選擇「english」。"
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "無法設定專案目錄。放棄。"
-
-    # game/new_project.rpy:75
-    old "PROJECT NAME"
-    new "專案名稱"
-
-    # game/new_project.rpy:75
-    old "Please enter the name of your project:"
-    new "請輸入專案名稱:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "專案名稱不能為空。"
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] 已存在。請選擇不同的名稱。"
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_dir!q] 已存在。請選擇不同的名稱。"
-
diff --git a/launcher/game/tl/traditional_chinese/obsolete.rpy b/launcher/game/tl/traditional_chinese/obsolete.rpy
new file mode 100644
index 0000000..9aa3f98
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate traditional_chinese strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "遊戲桿映射"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "空白檔位"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "上一頁"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "下一頁"
+
diff --git a/launcher/game/tl/traditional_chinese/options.rpy b/launcher/game/tl/traditional_chinese/options.rpy
new file mode 100644
index 0000000..23741c7
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/options.rpy
@@ -0,0 +1,195 @@
+
+translate traditional_chinese strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/traditional_chinese/preferences.rpy b/launcher/game/tl/traditional_chinese/preferences.rpy
deleted file mode 100644
index 2c1c3c3..0000000
--- a/launcher/game/tl/traditional_chinese/preferences.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/preferences.rpy:64
-    old "Launcher Preferences"
-    new "啟動器偏好"
-
-    # game/preferences.rpy:85
-    old "Projects Directory:"
-    new "專案目錄:"
-
-    # game/preferences.rpy:92
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:94
-    old "Projects directory: [text]"
-    new "專案資料夾: [text]"
-
-    # game/preferences.rpy:96
-    old "Not Set"
-    new "未設定"
-
-    # game/preferences.rpy:111
-    old "Text Editor:"
-    new "文字編輯器:"
-
-    # game/preferences.rpy:117
-    old "Text editor: [text]"
-    new "文字編輯器: [text]"
-
-    # game/preferences.rpy:133
-    old "Update Channel:"
-    new "更新頻道:"
-
-    # game/preferences.rpy:153
-    old "Navigation Options:"
-    new "導航選項:"
-
-    # game/preferences.rpy:157
-    old "Include private names"
-    new "包含私有名稱"
-
-    # game/preferences.rpy:158
-    old "Include library names"
-    new "包含資料庫名稱"
-
-    # game/preferences.rpy:168
-    old "Launcher Options:"
-    new "啟動器選項:"
-
-    # game/preferences.rpy:172
-    old "Hardware rendering"
-    new "硬體渲染"
-
-    # game/preferences.rpy:173
-    old "Show templates"
-    new "顯示模板"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "顯示編輯檔節"
-
-    # game/preferences.rpy:175
-    old "Large fonts"
-    new "大字體"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "產生空字串翻譯"
-
-    # game/preferences.rpy:179
-    old "Console output"
-    new "控制臺輸出"
-
-    # game/preferences.rpy:200
-    old "Open launcher project"
-    new "開啟啟動器專案"
-
-    # game/preferences.rpy:214
-    old "Language:"
-    new "語言:"
-
diff --git a/launcher/game/tl/traditional_chinese/project.rpy b/launcher/game/tl/traditional_chinese/project.rpy
deleted file mode 100644
index ad75a5c..0000000
--- a/launcher/game/tl/traditional_chinese/project.rpy
+++ /dev/null
@@ -1,51 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/project.rpy:47
-    old "After making changes to the script, press shift+R to reload your game."
-    new "改變腳本後,請按 shift+R 來重新載入您的遊戲。"
-
-    # game/project.rpy:47
-    old "Press shift+O (the letter) to access the console."
-    new "按 shift+O (the letter) 來進入控制臺。"
-
-    # game/project.rpy:47
-    old "Press shift+D to access the developer menu."
-    new "按 shift+D 來進入開發者選單。"
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "您最近有備份您的專案嗎?"
-
-    # game/project.rpy:224
-    old "Launching the project failed."
-    new "啟動專案失敗。"
-
-    # game/project.rpy:224
-    old "Please ensure that your project launches normally before running this command."
-    new "請確保您的專案能正常啟動再執行本指令。"
-
-    # game/project.rpy:237
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py 正在掃描專案.."
-
-    # game/project.rpy:526
-    old "Launching"
-    new "啟動"
-
-    # game/project.rpy:555
-    old "PROJECTS DIRECTORY"
-    new "專案目錄"
-
-    # game/project.rpy:555
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "請使用目錄選擇器選擇專案目錄。\n{b}目錄選擇視窗可能會開啟在本視窗後面。{/b}"
-
-    # game/project.rpy:555
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "啟動器會掃描該目錄下的專案,新增的專案也將在該目錄下建置。專案也在該目錄下建立。"
-
-    # game/project.rpy:560
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py 已將專案目錄設定為"
-
diff --git a/launcher/game/tl/traditional_chinese/screens.rpy b/launcher/game/tl/traditional_chinese/screens.rpy
new file mode 100644
index 0000000..220882d
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/screens.rpy
@@ -0,0 +1,643 @@
+
+translate traditional_chinese strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "返回"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "略過"
+
+    # screens.rpy:264
+    old "Auto"
+    new "自動"
+
+    # screens.rpy:265
+    old "Save"
+    new "儲存"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.儲存"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.讀取"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "設定"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "設定"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "標題畫面"
+
+    # screens.rpy:328
+    old "About"
+    new "關於"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "説明"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "離開"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "返回"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "顯示"
+
+    # screens.rpy:739
+    old "Window"
+    new "視窗"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "全螢幕"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Disable"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "選擇後"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "過渡"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "文字顯示速度"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "自動前進時間"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "音樂音量"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "音效音量"
+
+    # screens.rpy:791
+    old "Test"
+    new "測試"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "語音音量"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Gamepad"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Calibrate"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "是"
+
+    # screens.rpy:1162
+    old "No"
+    new "否"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/traditional_chinese/script.rpym b/launcher/game/tl/traditional_chinese/script.rpym
new file mode 100644
index 0000000..de89dc7
--- /dev/null
+++ b/launcher/game/tl/traditional_chinese/script.rpym
@@ -0,0 +1,17 @@
+# 您可以在此編寫遊戲的腳本。
+
+# image命令可用於定義一個圖像。
+# eg. image eileen happy = "eileen_happy.png"
+
+# define命令可定義遊戲中出現的角色名稱與對應文本顏色。
+define e = Character('Eileen', color="#c8ffc8")
+
+
+# 遊戲從這裡開始。
+label start:
+
+    e "您已經創建了一個新的 Ren'Py 遊戲。"
+
+    e "當您添加一段故事, 圖片和音樂, 您就可以將它發佈給全世界!"
+
+    return
diff --git a/launcher/game/tl/traditional_chinese/style.rpy b/launcher/game/tl/traditional_chinese/style.rpy
index 213479c..73a9d2c 100644
--- a/launcher/game/tl/traditional_chinese/style.rpy
+++ b/launcher/game/tl/traditional_chinese/style.rpy
@@ -1,31 +1,5 @@
-translate traditional_chinese python:
-
-    DSF = "tl/traditional_chinese/DroidSansFallback.ttf"
-
-    style.l_default.font = DSF
-    style.l_default.size = 16
-    style.l_default.selected_font = DSF
-    style.l_default.selected_bold = 1
-
-    style.l_button_text.font = DSF
-    style.l_button_text.selected_bold = True
-    style.l_checkbox_text.font = DSF
-    style.l_link_text.font = DSF
-
-    style.l_button_text.selected_font = DSF
-    style.l_button_text.selected_bold = 1
-
-    style.l_checkbox_text.selected_font = DSF
-    style.l_checkbox_text.selected_bold = 1
-
-    style.l_navigation_button_text.font = DSF
-    style.l_navigation_text.font = DSF
-    style.l_navigation_text.bold = True
-
-    style.l_link_text.selected_font = DSF
-    style.l_link_text.selected_bold = 1
-
-    style.l_alternate_text.font = DSF
-    style.l_nonbox_text.font = DSF
-    style.hyperlink_text.font = DSF
+init python:
+    translate_font("traditional_chinese", "DroidSansFallback.ttf")
 
+translate traditional_chinese python:
+    gui.FONT_SCALE = .9
diff --git a/launcher/game/tl/traditional_chinese/translations.rpy b/launcher/game/tl/traditional_chinese/translations.rpy
deleted file mode 100644
index 3adcde4..0000000
--- a/launcher/game/tl/traditional_chinese/translations.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/translations.rpy:34
-    old "Create or Update Translations"
-    new "新增或更新翻譯"
-
-    # game/translations.rpy:34
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "請輸入您要新增或者更新語言的名稱。"
-
-    # game/translations.rpy:39
-    old "The language name can not be the empty string."
-    new "語言名稱不能為空字串。"
-
-    # game/translations.rpy:50
-    old "Ren'Py is generating translations...."
-    new "Ren'Py 正在產生翻譯..."
-
-    # game/translations.rpy:54
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py 已經完成 [language] 檔案的翻譯。"
-
-    # game/translations.rpy:67
-    old "What format would you like for the extracted dialogue?"
-    new "您要使用什麼格式來提取對話?"
-
-    # game/translations.rpy:80
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py 正在提取對話..."
-
-    # game/translations.rpy:84
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
-    new "Ren'Py 已經完成對話提取。提取的對話可以在底層目錄下 dialogue.[format] 中找到。"
-
diff --git a/launcher/game/tl/traditional_chinese/updater.rpy b/launcher/game/tl/traditional_chinese/updater.rpy
deleted file mode 100644
index 7d57d44..0000000
--- a/launcher/game/tl/traditional_chinese/updater.rpy
+++ /dev/null
@@ -1,95 +0,0 @@
-
-translate traditional_chinese strings:
-
-    # game/updater.rpy:78
-    old "Select Update Channel"
-    new "選擇更新頻道"
-
-    # game/updater.rpy:89
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "更新頻道控制 Ren'Py 更新將會下載的版本。請選擇一個更新頻道。"
-
-    # game/updater.rpy:94
-    old "Release"
-    new "Release"
-
-    # game/updater.rpy:100
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}推薦{/b} Ren'py 的版本應在所有新釋出的遊戲中使用。"
-
-    # game/updater.rpy:105
-    old "Prerelease"
-    new "Prerelease"
-
-    # game/updater.rpy:111
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "預覽 Ren'py 的下一個版本,適合用於測試和體驗新功能,但不適合遊戲的最終版本。"
-
-    # game/updater.rpy:117
-    old "Experimental"
-    new "Experimental"
-
-    # game/updater.rpy:123
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Ren'py 的實驗版本,除非您被 Ren'py 的開發者要求,否則您不應該選擇此頻道。"
-
-    # game/updater.rpy:129
-    old "Nightly"
-    new "Nightly"
-
-    # game/updater.rpy:135
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Ren'Py 最新的開發版本。這可能會擁有最新的功能,或可能根本無法運作。"
-
-    # game/updater.rpy:155
-    old "An error has occured:"
-    new "一個錯誤發生:"
-
-    # game/updater.rpy:157
-    old "Checking for updates."
-    new "正在檢查更新。"
-
-    # game/updater.rpy:159
-    old "Ren'Py is up to date."
-    new "Ren'Py 已是最新版本。"
-
-    # game/updater.rpy:161
-    old "[u.version] is now available. Do you want to install it?"
-    new "[u.version] 已經可以更新。您要下載它嗎?"
-
-    # game/updater.rpy:163
-    old "Preparing to download the update."
-    new "準備下載更新"
-
-    # game/updater.rpy:165
-    old "Downloading the update."
-    new "正在下載更新。"
-
-    # game/updater.rpy:167
-    old "Unpacking the update."
-    new "正在解壓縮更新檔案。"
-
-    # game/updater.rpy:169
-    old "Finishing up."
-    new "即將完成。"
-
-    # game/updater.rpy:171
-    old "The update has been installed. Ren'Py will restart."
-    new "已安裝更新。Ren'Py 將會重新啟動。"
-
-    # game/updater.rpy:173
-    old "The update has been installed."
-    new "已安裝更新。"
-
-    # game/updater.rpy:175
-    old "The update was cancelled."
-    new "已取消更新。"
-
-    # game/updater.rpy:192
-    old "Ren'Py Update"
-    new "Ren'Py 更新"
-
-    # game/updater.rpy:198
-    old "Proceed"
-    new "繼續"
-
diff --git a/launcher/game/tl/vietnamese/about.rpy b/launcher/game/tl/vietnamese/about.rpy
deleted file mode 100644
index 0bebe31..0000000
--- a/launcher/game/tl/vietnamese/about.rpy
+++ /dev/null
@@ -1,15 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/about.rpy:39
-    old "[version!q]"
-    new "[version!q]"
-
-    # game/about.rpy:43
-    old "View license"
-    new "Xem giấy phép"
-
-    # game/about.rpy:45
-    old "Back"
-    new "Trở lại"
-
diff --git a/launcher/game/tl/vietnamese/add_file.rpy b/launcher/game/tl/vietnamese/add_file.rpy
deleted file mode 100644
index af5cde4..0000000
--- a/launcher/game/tl/vietnamese/add_file.rpy
+++ /dev/null
@@ -1,23 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/add_file.rpy:28
-    old "FILENAME"
-    new "TÊN FILE"
-
-    # game/add_file.rpy:28
-    old "Enter the name of the script file to create."
-    new "Nhập tên để tạo ra tập tin kịch bản"
-
-    # game/add_file.rpy:31
-    old "The filename must have the .rpy extension."
-    new "Tên tập tin phải có phần mở rộng .rpy."
-
-    # game/add_file.rpy:39
-    old "The file already exists."
-    new "Các tập tin đã tồn tại."
-
-    # game/add_file.rpy:42
-    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
-    new "Ren'Py tự động tải tất cả các tập tin kịch bản kết thúc với .rpy. Để sử dụng \n# tập tin này, xác định một nhãn và nhảy vào nó từ tập tin khác.\n"
-
diff --git a/launcher/game/tl/vietnamese/android.rpy b/launcher/game/tl/vietnamese/android.rpy
deleted file mode 100644
index ecefbd0..0000000
--- a/launcher/game/tl/vietnamese/android.rpy
+++ /dev/null
@@ -1,171 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/android.rpy:30
-    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Để xây dựng các gói Android, hãy tải về RAPT, giải nén nó và đặt nó vào thư mục Ren'Py. Sau đó khởi động lại Ren'Py."
-
-    # game/android.rpy:31
-    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
-    new "Cần một bản 32-bit Java Development Kit để xây dựng gói Android trên Windows. JDK khác với JRE, vì vậy có thể là bạn có Java nhưng ko có JDK.\n\n Hãy vào {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download và cài đặt JDK{/a}, rồi khởi động lại Renpy. "
-
-    # game/android.rpy:32
-    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
-    new "RAPT đã được cài đặt, nhưng bạn sẽ cần phải cài đặt Android SDK trước khi bạn có thể xây dựng các gói Android. Chọn Cài đặt SDK để làm điều này."
-
-    # game/android.rpy:33
-    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
-    new "RAPT đã được cài đặt, nhưng một chính chưa được cấu hình. Hãy tạo một khóa mới, hoặc khôi phục lại android.keystore."
-
-    # game/android.rpy:34
-    old "The current project has not been configured. Use \"Configure\" to configure it before building."
-    new "Các dự án hiện tại chưa được cấu hình. Sử dụng \"Configure\" để cấu hình nó trước khi xây dựng."
-
-    # game/android.rpy:35
-    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
-    new "Chọn \"Build\" để xây dựng các dự án hiện tại, hoặc đính kèm một thiết bị Android và chọn \"Build & Install\" để xây dựng và cài đặt nó trên thiết bị."
-
-    # game/android.rpy:37
-    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Để giả lập điện thoại Android. \n\n Cảm ứng được mô phỏng thông qua chuột, nhưng chỉ khi nút được thiết lập. Thoát ra được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
-
-    # game/android.rpy:38
-    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Để giả lập máy tính bảng Android. \n\n Cảm ứng được mô phỏng thông qua chuột, nhưng chỉ khi nút được thiết lập. Thoát ra được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
-
-    # game/android.rpy:39
-    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
-    new "Để giả lập bộ điều khiển tivi android, như OUYA hay Fire TV. \n\n Đầu vào bộ điều khiển gắn với phím mũi tên, Enter được gắn với nút select, và Thoát ra được được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
-
-    # game/android.rpy:41
-    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
-    new "Tải về và cài đặt Android SDK và các gói hỗ trợ. Tùy chọn, tạo ra các phím cần thiết để đăng ký gói."
-
-    # game/android.rpy:42
-    old "Configures the package name, version, and other information about this project."
-    new "Cấu hình tên gói, phiên bản, và các thông tin khác về dự án này."
-
-    # game/android.rpy:43
-    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
-    new "Mở tập tin có chứa key Google Play trong trình soạn thảo. \n\nChỉ cần thiết nếu các ứng dụng đang sử dụng một gói ứng mở rộng. Đọc tài liệu để biết thêm chi tiết."
-
-    # game/android.rpy:44
-    old "Builds the Android package."
-    new "Xây dựng các gói Android."
-
-    # game/android.rpy:45
-    old "Builds the Android package, and installs it on an Android device connected to your computer."
-    new "Xây dựng các gói Android và cài đặt nó trên một thiết bị Android kết nối với máy tính của bạn."
-
-    # game/android.rpy:46
-    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
-    new "Xây dựng các gói Android, cài đặt nó trên một thiết bị Android kết nối với máy tính của bạn, sau đó khởi chạy ứng dụng trên thiết bị của bạn."
-
-    # game/android.rpy:48
-    old "Connects to an Android device running ADB in TCP/IP mode."
-    new "Kết nối đến một thiết bị Android đang chạy trong chế độ ADB TCP / IP."
-
-    # game/android.rpy:49
-    old "Disconnects from an Android device running ADB in TCP/IP mode."
-    new "Ngắt kết nối từ một thiết bị Android đang chạy trong chế độ ADB TCP / IP."
-
-    # game/android.rpy:50
-    old "Retrieves the log from the Android device and writes it to a file."
-    new "Lấy các bản ghi từ các thiết bị Android và viết nó vào một tập tin."
-
-    # game/android.rpy:240
-    old "Copying Android files to distributions directory."
-    new "Sao chép tệp tin Android đến thư mục phân phối."
-
-    # game/android.rpy:304
-    old "Android: [project.current.name!q]"
-    new "Android: [project.current.name!q]"
-
-    # game/android.rpy:324
-    old "Emulation:"
-    new "Giả lập:"
-
-    # game/android.rpy:333
-    old "Phone"
-    new "Điện thoại"
-
-    # game/android.rpy:337
-    old "Tablet"
-    new "Máy tính bảng"
-
-    # game/android.rpy:341
-    old "Television"
-    new "Tivi"
-
-    # game/android.rpy:353
-    old "Build:"
-    new "Xây dựng:"
-
-    # game/android.rpy:361
-    old "Install SDK & Create Keys"
-    new "Cài đặt SDK & Tạo Keys"
-
-    # game/android.rpy:365
-    old "Configure"
-    new "Cấu hình"
-
-    # game/android.rpy:369
-    old "Build Package"
-    new "Xây dựng gói"
-
-    # game/android.rpy:373
-    old "Build & Install"
-    new "Xây dựng & Cài đặt"
-
-    # game/android.rpy:377
-    old "Build, Install & Launch"
-    new "Xây dựng, cài đặt và triển khai"
-
-    # game/android.rpy:388
-    old "Other:"
-    new "Khác:"
-
-    # game/android.rpy:396
-    old "Remote ADB Connect"
-    new "Kết nối ADB  từ xa"
-
-    # game/android.rpy:400
-    old "Remote ADB Disconnect"
-    new "Ngắt kết nối ADB  từ xa"
-
-    # game/android.rpy:404
-    old "Logcat"
-    new "Logcat"
-
-    # game/android.rpy:437
-    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
-    new "Trước khi đóng gói ứng dụng Android, bạn sẽ cần phải tải về RAPT, Công cụ đóng gói Ren'Py Android. Bạn có muốn tải về RAPT bây giờ?"
-
-    # game/android.rpy:490
-    old "Remote ADB Address"
-    new "Địa chỉ ADB từ xa"
-
-    # game/android.rpy:490
-    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
-    new "Hãy nhập địa chỉ IP và số cổng để kết nối, ở dạng \"192.168.1.143:. 5555\"Tham khảo tài liệu của thiết bị của bạn để xác định xem nó hỗ trợ ADB từ xa, và nếu như vậy, cần có địa chỉ và cổng để kết nối."
-
-    # game/android.rpy:502
-    old "Invalid remote ADB address"
-    new "Địa chỉ ADB từ xa không hợp lệ"
-
-    # game/android.rpy:502
-    old "The address must contain one exactly one ':'."
-    new "Các địa chỉ phải chính xác từng cái một ':'."
-
-    # game/android.rpy:506
-    old "The host may not contain whitespace."
-    new "Các máy chủ có thể không chứa khoảng trắng."
-
-    # game/android.rpy:512
-    old "The port must be a number."
-    new "Cổng port phải là một số."
-
-    # game/android.rpy:538
-    old "Retrieving logcat information from device."
-    new "Lấy logcat thông tin từ thiết bị."
-
diff --git a/launcher/game/tl/vietnamese/choose_directory.rpy b/launcher/game/tl/vietnamese/choose_directory.rpy
deleted file mode 100644
index 3a7bdc0..0000000
--- a/launcher/game/tl/vietnamese/choose_directory.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/choose_directory.rpy:73
-    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
-    new "Ren'Py đã không thể chạy python với Tkinter để chọn thư mục. Vui lòng cài đặt python-tk hoặc gói Tkinter ."
-
diff --git a/launcher/game/tl/vietnamese/choose_theme.rpy b/launcher/game/tl/vietnamese/choose_theme.rpy
deleted file mode 100644
index 1f70324..0000000
--- a/launcher/game/tl/vietnamese/choose_theme.rpy
+++ /dev/null
@@ -1,43 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/choose_theme.rpy:303
-    old "Could not change the theme. Perhaps options.rpy was changed too much."
-    new "Không thể thay đổi chủ đề. Có lẽ options.rpy đã thay đổi quá nhiều."
-
-    # game/choose_theme.rpy:368
-    old "Display"
-    new "Hiển thị"
-
-    # game/choose_theme.rpy:369
-    old "Window"
-    new "Cửa sổ"
-
-    # game/choose_theme.rpy:370
-    old "Fullscreen"
-    new "Toàn màn hình"
-
-    # game/choose_theme.rpy:371
-    old "Planetarium"
-    new "Planetarium"
-
-    # game/choose_theme.rpy:378
-    old "Sound Volume"
-    new "Âm lượng"
-
-    # game/choose_theme.rpy:426
-    old "Choose Theme"
-    new "Chọn chủ đề"
-
-    # game/choose_theme.rpy:439
-    old "Theme"
-    new "Chủ đề"
-
-    # game/choose_theme.rpy:464
-    old "Color Scheme"
-    new "Màu chủ đạo"
-
-    # game/choose_theme.rpy:496
-    old "Continue"
-    new "Tiếp tục"
-
diff --git a/launcher/game/tl/vietnamese/common.rpy b/launcher/game/tl/vietnamese/common.rpy
index 33ec9ec..8d2b0d3 100644
--- a/launcher/game/tl/vietnamese/common.rpy
+++ b/launcher/game/tl/vietnamese/common.rpy
@@ -1,611 +1,335 @@
 
 translate vietnamese strings:
 
-    # renpy/common/00action_file.rpy:155
-    old "%b %d, %H:%M"
-    new "%b %d, %H:%M"
-
-    # renpy/common/00action_file.rpy:643
-    old "Quick save complete."
-    new "Đã lưu nhanh."
-
-
-translate vietnamese strings:
-
-    # renpy/common/00console.rpy:180
-    old "%(version)s console, originally by Shiz, C, and delta.\n"
-    new "Phiên bản %(version)s, tạo bởi Shiz, C, và delta.\n"
-
-    # renpy/common/00console.rpy:181
-    old "Press <esc> to exit console. Type help for help.\n"
-    new "Nhấn <esc> để thoát khỏi giao diện điều khiển. Gõ help để được giúp đỡ. \n"
-
-    # renpy/common/00console.rpy:185
-    old "Ren'Py script enabled."
-    new "Mã Ren'Py đã được kích hoạt."
-
-    # renpy/common/00console.rpy:187
-    old "Ren'Py script disabled."
-    new "Mã Ren'Py đã được vô hiệu hóa."
-
-    # renpy/common/00console.rpy:393
-    old "help: show this help"
-    new "help: hiển thị trợ giúp"
-
-    # renpy/common/00console.rpy:398
-    old "commands:\n"
-    new "câu lệnh:\n"
-
-    # renpy/common/00console.rpy:408
-    old " <renpy script statement>: run the statement\n"
-    new "<renpy script statement>: chạy các câu lệnh \ n"
-
-    # renpy/common/00console.rpy:410
-    old " <python expression or statement>: run the expression or statement"
-    new "<python expression or statement>: chạy các biểu hiện hay trạng thái"
-
-    # renpy/common/00console.rpy:418
-    old "clear: clear the console history"
-    new "clear: xóa lịch sử giao diện điều khiển"
-
-    # renpy/common/00console.rpy:422
-    old "exit: exit the console"
-    new "exit: thoát khỏi giao diện điều khiển"
-
-    # renpy/common/00console.rpy:430
-    old "load <slot>: loads the game from slot"
-    new "load <slot>: tiếp tục game tại slot"
-
-    # renpy/common/00console.rpy:443
-    old "save <slot>: saves the game in slot"
-    new "save <slot>: lưu game tại slot"
-
-    # renpy/common/00console.rpy:454
-    old "reload: reloads the game, refreshing the scripts"
-    new "reload: tải lại game, làm mới các mã kịch bản"
-
-    # renpy/common/00console.rpy:462
-    old "watch <expression>: watch a python expression"
-    new "watch <expression>: xem một biểu hiện python"
-
-    # renpy/common/00console.rpy:488
-    old "unwatch <expression>: stop watching an expression"
-    new "unwatch <expression>: dừng xem một biểu hiện python"
-
-    # renpy/common/00console.rpy:514
-    old "unwatchall: stop watching all expressions"
-    new "unwatchall: dừng xem tất cả các biểu hiện"
-
-    # renpy/common/00console.rpy:531
-    old "jump <label>: jumps to label"
-    new "jump <label>: nhảy đến nhãn"
-
-
-translate vietnamese strings:
-
-    # renpy/common/00gallery.rpy:561
-    old "Image [index] of [count] locked."
-    new "ình ảnh [index] của [count] bị khóa."
-
-    # renpy/common/00gallery.rpy:581
-    old "prev"
-    new "về trước"
-
-    # renpy/common/00gallery.rpy:582
-    old "next"
-    new "về sau"
-
-    # renpy/common/00gallery.rpy:583
-    old "slideshow"
-    new "trình chiếu"
-
-    # renpy/common/00gallery.rpy:584
-    old "return"
-    new "trở lại"
-
-
-translate vietnamese strings:
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
 
-    # renpy/common/00gamepad.rpy:32
-    old "Select Gamepad to Calibrate"
-    new "Chọn tay cầm để cân chỉnh"
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
 
-    # renpy/common/00gamepad.rpy:35
-    old "Không có tay cầm sẵn"
-    new ""
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
 
-    # renpy/common/00gamepad.rpy:42
-    old "Cancel"
-    new "Hủy"
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
 
-    # renpy/common/00gamepad.rpy:54
-    old "Calibrating [name] ([i]/[total])"
-    new "Đo đạc [name] ([i]/[total])"
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
 
-    # renpy/common/00gamepad.rpy:58
-    old "Press or move the [control!r] [kind]."
-    new "Nhấn hoặc di chuyển [control!r] [kind]."
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
 
-    # renpy/common/00gamepad.rpy:66
-    old "Skip (A)"
-    new "Lướt qua (A)"
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
 
-    # renpy/common/00gamepad.rpy:69
-    old "Back (B)"
-    new "Trở về (B)"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
 
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
 
-translate vietnamese strings:
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
 
-    # renpy/common/00gltest.rpy:68
-    old "Graphics Acceleration"
-    new "Tăng tốc độ đồ họa"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
 
-    # renpy/common/00gltest.rpy:72
-    old "Automatically Choose"
-    new "Tự động chọn"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
 
-    # renpy/common/00gltest.rpy:77
-    old "Force Angle/DirectX Renderer"
-    new "Bắt buộc chạy Angle/DirectX Renderer"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
 
-    # renpy/common/00gltest.rpy:81
-    old "Force OpenGL Renderer"
-    new "Bắt buộc chạy OpenGL Renderer"
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
 
-    # renpy/common/00gltest.rpy:85
-    old "Force Software Renderer"
-    new "Bắt buộc chạy chương trình Renderer"
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
 
-    # renpy/common/00gltest.rpy:91
-    old "Gamepad"
-    new "Tay cầm"
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
 
-    # renpy/common/00gltest.rpy:95
-    old "Enable"
-    new "Bật"
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
 
-    # renpy/common/00gltest.rpy:99
-    old "Disable"
-    new "Tắt"
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
 
-    # renpy/common/00gltest.rpy:105
-    old "Calibrate"
-    new "Tinh chỉnh"
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
 
-    # renpy/common/00gltest.rpy:111
-    old "Changes will take effect the next time this program is run."
-    new "Thay đổi sẽ có hiệu lực vào lần tiếp theo chương trình này được chạy."
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
 
-    # renpy/common/00gltest.rpy:150
-    old "Performance Warning"
-    new "Cảnh báo hiệu suất"
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
 
-    # renpy/common/00gltest.rpy:155
-    old "This computer is using software rendering."
-    new "Máy tính này đang sử dụng phần mềm rendering."
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
 
-    # renpy/common/00gltest.rpy:157
-    old "This computer is not using shaders."
-    new "Máy tính này không sử dụng đổ bóng."
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
 
-    # renpy/common/00gltest.rpy:159
-    old "This computer is displaying graphics slowly."
-    new "Máy tính này hiển thị đồ họa chậm."
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
 
-    # renpy/common/00gltest.rpy:161
-    old "This computer has a problem displaying graphics: [problem]."
-    new "Máy tính này có một vấn đề hiển thị đồ họa: [problem]"
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
 
-    # renpy/common/00gltest.rpy:166
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
-    new "Trình điều khiển đồ họa của nó có thể đã quá cũ hoặc vận hành lỗi. Điều này có thể dẫn đến làm chậm hoặc hiển thị đồ họa không chính xác. Cập nhật DirectX có thể khắc phục vấn đề này."
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
 
-    # renpy/common/00gltest.rpy:168
-    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
-    new "Trình điều khiển đồ họa của nó có thể đã quá cũ hoặc vận hành lỗi. Điều này có thể dẫn đến làm chậm hoặc hiển thị đồ họa không chính xác."
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
 
-    # renpy/common/00gltest.rpy:173
-    old "Update DirectX"
-    new "Cập nhật DirectX"
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
 
-    # renpy/common/00gltest.rpy:179
-    old "Continue, Show this warning again"
-    new "Tiếp tục, hiển thị cảnh báo lần sau"
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
 
-    # renpy/common/00gltest.rpy:183
-    old "Continue, Don't show warning again"
-    new "Tiếp tục, không hiển thị cảnh báo nữa"
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
 
-    # renpy/common/00gltest.rpy:209
-    old "Updating DirectX."
-    new "Cập nhật DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
 
-    # renpy/common/00gltest.rpy:213
-    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
-    new "Đang cài đặt DirectX web. Nó có thể bắt đầu thu nhỏ ở thanh tác vụ. Hãy làm theo các hướng dẫn để cài đặt DirectX."
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
 
-    # renpy/common/00gltest.rpy:217
-    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
-    new "{b} Lưu ý:.. {/b} Chương trình cài đặt DirectX  web của Microsof theo mặc định sẽ cài đặt thanh công cụ Bing. Nếu bạn không muốn thanh công cụ này, bỏ chọn tại ô."
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
 
-    # renpy/common/00gltest.rpy:221
-    old "When setup finishes, please click below to restart this program."
-    new "Khi cài đặt kết thúc, xin vui lòng bấm vào dưới đây để khởi động lại chương trình này."
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
 
-    # renpy/common/00gltest.rpy:223
-    old "Restart"
-    new "Khởi động lại"
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
 
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
 
-translate vietnamese strings:
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
 
-    # renpy/common/00keymap.rpy:241
-    old "Saved screenshot as %s."
-    new "Đã lưu ảnh chụp màn hình là %s."
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
 
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d, %H:%M"
 
-translate vietnamese strings:
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Đã lưu nhanh."
 
-    # renpy/common/00layout.rpy:444
+    # 00gui.rpy:227
     old "Are you sure?"
     new "Bạn có chắc chắn?"
 
-    # renpy/common/00layout.rpy:445
+    # 00gui.rpy:228
     old "Are you sure you want to delete this save?"
     new "Bạn có chắc chắn muốn xóa file lưu này?"
 
-    # renpy/common/00layout.rpy:446
+    # 00gui.rpy:229
     old "Are you sure you want to overwrite your save?"
     new "Bạn có chắc muốn ghi đè file lưu này?"
 
-    # renpy/common/00layout.rpy:447
+    # 00gui.rpy:230
     old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
     new "Tải file load sẽ làm mất tiến trình chưa được lưu này. \nBạn có chắc muốn làm điều này?"
 
-    # renpy/common/00layout.rpy:448
+    # 00gui.rpy:231
     old "Are you sure you want to quit?"
     new "Bạn có chắc chắn bạn muốn thoát ra?"
 
-    # renpy/common/00layout.rpy:449
+    # 00gui.rpy:232
     old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
     new "Bạn có chắc chắn bạn muốn quay trở lại menu chính? \n Nó sẽ làm mất tiến trình chưa được lưu này."
 
-    # renpy/common/00layout.rpy:450
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
     old "Are you sure you want to begin skipping?"
     new "Bạn có chắc chắn muốn lướt bỏ qua không?"
 
-    # renpy/common/00layout.rpy:451
+    # 00gui.rpy:235
     old "Are you sure you want to skip to the next choice?"
     new "Bạn có chắc chắn muốn lướt bỏ qua tới lựa chọn tiếp theo không?"
 
-    # renpy/common/00layout.rpy:452
-    old "Are you sure you want to skip to unseen dialogue or the next choice?"
-    new "Bạn có chắc chắn muốn lướt bỏ qua tới đoạn hội thoại hoặc lựa chọn tiếp theo không?"
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
 
-translate vietnamese strings:
+    # 00keymap.rpy:250
+    old "Saved screenshot as %s."
+    new "Đã lưu ảnh chụp màn hình là %s."
 
-    # renpy/common/00library.rpy:157
-    old "Skip Mode"
-    new "Chế độ lướt"
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
 
-    # renpy/common/00library.rpy:160
-    old "Fast Skip Mode"
-    new "Chế độ lướt nhanh"
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
 
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
 
-translate vietnamese strings:
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Chế độ lướt"
+
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
 
-    # renpy/common/00preferences.rpy:384
+    # 00preferences.rpy:422
     old "Clipboard voicing enabled. Press 'shift+C' to disable."
     new "Bản ghi lồng tiếng được kích hoạt. Nhấn 'shift + C' để vô hiệu hóa."
 
-    # renpy/common/00preferences.rpy:386
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
     old "Self-voicing enabled. Press 'v' to disable."
     new "Tự lồng tiếng được kích hoạt. Nhấn 'v' để vô hiệu hóa."
 
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
 
-translate vietnamese strings:
-
-    # renpy/common/00updater.rpy:362
+    # 00updater.rpy:367
     old "The Ren'Py Updater is not supported on mobile devices."
     new "Ren'Py Updater không được hỗ trợ trên các thiết bị di động."
 
-    # renpy/common/00updater.rpy:481
+    # 00updater.rpy:486
     old "An error is being simulated."
     new "Một lỗi đã được mô phỏng."
 
-    # renpy/common/00updater.rpy:657
+    # 00updater.rpy:662
     old "Either this project does not support updating, or the update status file was deleted."
     new "Hoặc là dự án này không hỗ trợ cập nhật, hoặc các tập tin cập nhật tình trạng đã bị xóa."
 
-    # renpy/common/00updater.rpy:671
+    # 00updater.rpy:676
     old "This account does not have permission to perform an update."
     new "Tài khoản này không có sự cho phép để thực hiện một bản cập nhật."
 
-    # renpy/common/00updater.rpy:674
+    # 00updater.rpy:679
     old "This account does not have permission to write the update log."
     new "Tài khoản này không có sự cho phép để viết nhật ký cập nhật"
 
-    # renpy/common/00updater.rpy:699
+    # 00updater.rpy:704
     old "Could not verify update signature."
     new "Không thể xác minh cập nhật chữ ký."
 
-    # renpy/common/00updater.rpy:970
+    # 00updater.rpy:975
     old "The update file was not downloaded."
     new "Các tập tin cập nhật không được tải xuống."
 
-    # renpy/common/00updater.rpy:988
+    # 00updater.rpy:993
     old "The update file does not have the correct digest - it may have been corrupted."
     new "Các tập tin cập nhật không có tiêu hóa đúng - nó có thể đã bị hỏng."
 
-    # renpy/common/00updater.rpy:1044
+    # 00updater.rpy:1049
     old "While unpacking {}, unknown type {}."
     new "Trong khi giải nén {}, loại không rõ {}."
 
-    # renpy/common/00updater.rpy:1395
+    # 00updater.rpy:1393
     old "Updater"
     new "Trình update"
 
-    # renpy/common/00updater.rpy:1400
-    old "An error has occured:"
-    new "Một lỗi đã xảy ra:"
-
-    # renpy/common/00updater.rpy:1402
-    old "Checking for updates."
-    new "Kiểm tra các bản cập nhật."
-
-    # renpy/common/00updater.rpy:1404
+    # 00updater.rpy:1404
     old "This program is up to date."
     new "Chương trình đã được cập nhật"
 
-    # renpy/common/00updater.rpy:1406
+    # 00updater.rpy:1406
     old "[u.version] is available. Do you want to install it?"
     new "[u.version] đã sẵn sàng. Bạn có muốn cài đặt nó?"
 
-    # renpy/common/00updater.rpy:1408
+    # 00updater.rpy:1408
     old "Preparing to download the updates."
     new "Chuẩn bị để tải về các bản cập nhật."
 
-    # renpy/common/00updater.rpy:1410
+    # 00updater.rpy:1410
     old "Downloading the updates."
     new "Tải các bản cập nhật."
 
-    # renpy/common/00updater.rpy:1412
+    # 00updater.rpy:1412
     old "Unpacking the updates."
     new "Bung cập nhật."
 
-    # renpy/common/00updater.rpy:1414
-    old "Finishing up."
-    new "Kết thúc"
-
-    # renpy/common/00updater.rpy:1416
+    # 00updater.rpy:1416
     old "The updates have been installed. The program will restart."
     new "Các cập nhật đã được cài đặt. Chương trình sẽ khởi động lại."
 
-    # renpy/common/00updater.rpy:1418
+    # 00updater.rpy:1418
     old "The updates have been installed."
     new "Các cập nhật đã được cài đặt."
 
-    # renpy/common/00updater.rpy:1420
+    # 00updater.rpy:1420
     old "The updates were cancelled."
     new "Các cập nhật đã bị hủy bỏ."
 
-    # renpy/common/00updater.rpy:1434
-    old "Proceed"
-    new "Tiếp tục"
-
-
-translate vietnamese strings:
-
-    # renpy/common/_compat/gamemenu.rpym:198
-    old "Empty Slot."
-    new "Ô còn trống"
-
-    # renpy/common/_compat/gamemenu.rpym:355
-    old "Previous"
-    new "Về trước"
-
-    # renpy/common/_compat/gamemenu.rpym:362
-    old "Next"
-    new "Về sau"
-
-
-translate vietnamese strings:
-
-    # renpy/common/_compat/preferences.rpym:428
-    old "Joystick Mapping"
-    new "Hệ thống nút tay cầm"
-
-
-translate vietnamese strings:
-
-    # renpy/common/_developer/developer.rpym:65
-    old "Developer Menu"
-    new "Menu nhà phát triển"
-
-    # renpy/common/_developer/developer.rpym:67
-    old "Reload Game (Shift+R)"
-    new "Khởi động lại trò chơi (Shift + R)"
-
-    # renpy/common/_developer/developer.rpym:69
-    old "Console (Shift+O)"
-    new "Bảng điều khiển (Shift + O)"
-
-    # renpy/common/_developer/developer.rpym:71
-    old "Variable Viewer"
-    new "Bảng Biến"
-
-    # renpy/common/_developer/developer.rpym:73
-    old "Theme Test"
-    new "Thử nghiệm theme"
-
-    # renpy/common/_developer/developer.rpym:75
-    old "Image Location Picker"
-    new "Vị trí hình ảnh"
-
-    # renpy/common/_developer/developer.rpym:77
-    old "Filename List"
-    new "Danh sách tên file"
-
-    # renpy/common/_developer/developer.rpym:81
-    old "Show Image Load Log"
-    new "Hiện bản ghi những hình ảnh đã tải"
-
-    # renpy/common/_developer/developer.rpym:84
-    old "Hide Image Load Log"
-    new "Ẩn bản ghi những hình ảnh đã tải"
-
-    # renpy/common/_developer/developer.rpym:150
-    old "No variables have changed since the game started."
-    new "Không có biến đã thay đổi kể từ khi game bắt đầu."
-
-    # renpy/common/_developer/developer.rpym:153
-    old "Return to the developer menu"
-    new "Return để các nhà phát triển trình đơn"
-
-    # renpy/common/_developer/developer.rpym:386
-    old "Rectangle: %r"
-    new "Hình chữ nhật: %r"
-
-    # renpy/common/_developer/developer.rpym:391
-    old "Mouse position: %r"
-    new "Vi trí chuột: %r "
-
-    # renpy/common/_developer/developer.rpym:396
-    old "Right-click or escape to quit."
-    new "Chuột phải hoặc bấm escape để thoát"
-
-    # renpy/common/_developer/developer.rpym:425
-    old "Rectangle copied to clipboard."
-    new "Hình chữ nhật đã được sao chép vào bản ghi"
-
-    # renpy/common/_developer/developer.rpym:428
-    old "Position copied to clipboard."
-    new "Vị trí đã được sao chép vào bản ghi"
-
-    # renpy/common/_developer/developer.rpym:459
-    old "Done"
-    new "Hoàn tất"
-
-
-translate vietnamese strings:
-
-    # renpy/common/_developer/inspector.rpym:46
-    old "Displayable Inspector"
-    new "Bản tra hiển thị"
-
-    # renpy/common/_developer/inspector.rpym:52
-    old "Nothing to inspect."
-    new "Không có gì để kiểm tra."
-
-    # renpy/common/_developer/inspector.rpym:70
-    old "Size"
-    new "Kích thước"
-
-    # renpy/common/_developer/inspector.rpym:74
-    old "Style"
-    new "Phong cách"
-
-    # renpy/common/_developer/inspector.rpym:80
-    old "Location"
-    new "Vị trí"
-
-    # renpy/common/_developer/inspector.rpym:142
-    old "Inspecting Styles of [displayable_name!q]"
-    new "Kiểm tra Styles của [displayable_name!q]"
-
-    # renpy/common/_developer/inspector.rpym:155
-    old "displayable:"
-    new "Thể hiển thị:"
-
-    # renpy/common/_developer/inspector.rpym:162
-    old "        (no properties affect the displayable)"
-    new "        (không có thuộc tính ảnh hưởng đến thể hiển thị)"
-
-    # renpy/common/_developer/inspector.rpym:164
-    old "        (default properties omitted)"
-    new "        (các thuộc tính mặc định bỏ qua)"
-
-    # renpy/common/_developer/inspector.rpym:206
-    old "<repr() failed>"
-    new "<repr() failed>"
-
-
-translate vietnamese strings:
-
-    # renpy/common/_errorhandling.rpym:500
-    old "An exception has occurred."
-    new "Một ngoại lệ đã xảy ra."
-
-    # renpy/common/_errorhandling.rpym:526
-    old "Rollback"
-    new "Quay lại"
-
-    # renpy/common/_errorhandling.rpym:528
-    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
-    new "Cho phép cuộn lại về trước, cho phép bạn lưu hoặc chọn một lựa chọn khác."
-
-    # renpy/common/_errorhandling.rpym:531
-    old "Ignore"
-    new "Bỏ qua"
-
-    # renpy/common/_errorhandling.rpym:533
-    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
-    new "Bỏ qua những ngoại lệ, cho phép bạn tiếp tục. Điều này thường gây thêm lỗi."
-
-    # renpy/common/_errorhandling.rpym:536
-    old "Reload"
-    new "Tải lại"
-
-    # renpy/common/_errorhandling.rpym:538
-    old "Reloads the game from disk, saving and restoring game state if possible."
-    new "Tải lại trò chơi từ đĩa, sao lưu và khôi phục lại trạng thái trò chơi nếu có thể."
-
-    # renpy/common/_errorhandling.rpym:540
-    old "Open Traceback"
-    new "Mở Traceback"
-
-    # renpy/common/_errorhandling.rpym:542
-    old "Opens the traceback.txt file in a text editor."
-    new "Mở tập tin traceback.txt trong một trình soạn thảo văn bản."
-
-    # renpy/common/_errorhandling.rpym:545
-    old "Copy to Clipboard"
-    new "Sao chép vào bản ghi"
-
-    # renpy/common/_errorhandling.rpym:547
-    old "Copies the traceback.txt file to the clipboard."
-    new "Lưu tập tin traceback.txt vào bản ghi."
-
-    # renpy/common/_errorhandling.rpym:553
-    old "Quits the game."
-    new "Thoát trò chơi"
-
-    # renpy/common/_errorhandling.rpym:580
-    old "Parsing the script failed."
-    new "Phân tích các mã kịch bản thất bại."
-
-    # renpy/common/_errorhandling.rpym:607
-    old "Open Parse Errors"
-    new "Mở những lỗi phân tích"
-
-    # renpy/common/_errorhandling.rpym:609
-    old "Opens the errors.txt file in a text editor."
-    new "Mở tập tin ERRORS.TXT vào một trình soạn thảo văn bản."
-
-    # renpy/common/_errorhandling.rpym:614
-    old "Copies the errors.txt file to the clipboard."
-    new "Lưu các tập tin ERRORS.TXT vào bản ghi."
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "ình ảnh [index] của [count] bị khóa."
 
+    # 00gallery.rpy:583
+    old "prev"
+    new "về trước"
 
-translate vietnamese strings:
+    # 00gallery.rpy:584
+    old "next"
+    new "về sau"
 
-    # renpy/common/_layout/classic_load_save.rpym:170
-    old "a"
-    new "a"
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "trình chiếu"
 
-    # renpy/common/_layout/classic_load_save.rpym:179
-    old "q"
-    new "q"
+    # 00gallery.rpy:586
+    old "return"
+    new "trở lại"
 
diff --git a/launcher/game/tl/vietnamese/developer.rpy b/launcher/game/tl/vietnamese/developer.rpy
new file mode 100644
index 0000000..a2283c5
--- /dev/null
+++ b/launcher/game/tl/vietnamese/developer.rpy
@@ -0,0 +1,179 @@
+
+translate vietnamese strings:
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Menu nhà phát triển"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Khởi động lại trò chơi (Shift + R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Bảng điều khiển (Shift + O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Bảng Biến"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Thử nghiệm theme"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Vị trí hình ảnh"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Danh sách tên file"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Hiện bản ghi những hình ảnh đã tải"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Ẩn bản ghi những hình ảnh đã tải"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Không có gì để kiểm tra."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Return để các nhà phát triển trình đơn"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Hình chữ nhật: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Vi trí chuột: %r "
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Chuột phải hoặc bấm escape để thoát"
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Hình chữ nhật đã được sao chép vào bản ghi"
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Vị trí đã được sao chép vào bản ghi"
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Bản tra hiển thị"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Kích thước"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Phong cách"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Vị trí"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Kiểm tra Styles của [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "Thể hiển thị:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (không có thuộc tính ảnh hưởng đến thể hiển thị)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (các thuộc tính mặc định bỏ qua)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Nhấn <esc> để thoát khỏi giao diện điều khiển. Gõ help để được giúp đỡ. \n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Mã Ren'Py đã được kích hoạt."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Mã Ren'Py đã được vô hiệu hóa."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: hiển thị trợ giúp"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "câu lệnh:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new "<renpy script statement>: chạy các câu lệnh \\ n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new "<python expression or statement>: chạy các biểu hiện hay trạng thái"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: xóa lịch sử giao diện điều khiển"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: thoát khỏi giao diện điều khiển"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: tiếp tục game tại slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: lưu game tại slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: tải lại game, làm mới các mã kịch bản"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: xem một biểu hiện python"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: dừng xem một biểu hiện python"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: dừng xem tất cả các biểu hiện"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: nhảy đến nhãn"
+
diff --git a/launcher/game/tl/vietnamese/distribute.rpy b/launcher/game/tl/vietnamese/distribute.rpy
deleted file mode 100644
index 0bc8842..0000000
--- a/launcher/game/tl/vietnamese/distribute.rpy
+++ /dev/null
@@ -1,39 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/distribute.rpy:384
-    old "Scanning project files..."
-    new ""
-
-    # game/distribute.rpy:400
-    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
-    new ""
-
-    # game/distribute.rpy:445
-    old "No packages are selected, so there's nothing to do."
-    new ""
-
-    # game/distribute.rpy:457
-    old "Scanning Ren'Py files..."
-    new ""
-
-    # game/distribute.rpy:509
-    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
-    new ""
-
-    # game/distribute.rpy:633
-    old "Archiving files..."
-    new ""
-
-    # game/distribute.rpy:951
-    old "Writing the [variant] [format] package."
-    new ""
-
-    # game/distribute.rpy:964
-    old "Making the [variant] update zsync file."
-    new ""
-
-    # game/distribute.rpy:1106
-    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
-    new ""
-
diff --git a/launcher/game/tl/vietnamese/distribute_gui.rpy b/launcher/game/tl/vietnamese/distribute_gui.rpy
deleted file mode 100644
index c72fcb3..0000000
--- a/launcher/game/tl/vietnamese/distribute_gui.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/distribute_gui.rpy:157
-    old "Build Distributions: [project.current.name!q]"
-    new "Xây dựng: [project.current.name!q]"
-
-    # game/distribute_gui.rpy:171
-    old "Directory Name:"
-    new "Tên thư mục:"
-
-    # game/distribute_gui.rpy:175
-    old "Executable Name:"
-    new "Tên file thực thi:"
-
-    # game/distribute_gui.rpy:185
-    old "Actions:"
-    new "Hành động:"
-
-    # game/distribute_gui.rpy:193
-    old "Edit options.rpy"
-    new "Edit options.rpy"
-
-    # game/distribute_gui.rpy:194
-    old "Add from clauses to calls, once"
-    new "Thêm một lần mệnh đề from vào lệnh call."
-
-    # game/distribute_gui.rpy:195
-    old "Refresh"
-    new "Làm mới"
-
-    # game/distribute_gui.rpy:212
-    old "Build Packages:"
-    new "Xây dựng gói:"
-
-    # game/distribute_gui.rpy:231
-    old "Options:"
-    new "Tùy chọn:"
-
-    # game/distribute_gui.rpy:236
-    old "Build Updates"
-    new "Xây dựng bản cập nhật."
-
-    # game/distribute_gui.rpy:238
-    old "Add from clauses to calls"
-    new "Thêm mệnh đề from vào lệnh call."
-
-    # game/distribute_gui.rpy:239
-    old "Force Recompile"
-    new "Bắt buộc biên dịch lại"
-
-    # game/distribute_gui.rpy:243
-    old "Build"
-    new "Xây dựng"
-
-    # game/distribute_gui.rpy:247
-    old "Adding from clauses to call statements that do not have them."
-    new "Thêm mệnh đề from vào những lệnh call chưa có chúng."
-
-    # game/distribute_gui.rpy:268
-    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
-    new "Lỗi được phát hiện khi chạy dự án. Hãy đảm bảo dự án chạy mà không có lỗi trước khi xây dựng các bản phân phối"
-
-    # game/distribute_gui.rpy:285
-    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
-    new "Dự án của bạn không có thông tin xây dựng. Bạn có muốn thêm thông tin xây dựng ở cuối options.rpy không?"
-
diff --git a/launcher/game/tl/vietnamese/editor.rpy b/launcher/game/tl/vietnamese/editor.rpy
deleted file mode 100644
index 05eba74..0000000
--- a/launcher/game/tl/vietnamese/editor.rpy
+++ /dev/null
@@ -1,52 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/editor.rpy:150
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
-    new "{b}Khuyến khích{/ b} Một trình biên tập có giao diện thân thiện và chức năng hỗ trợ phát triển, chẳng hạn như kiểm tra lỗi chính tả. Editra hiện đang thiếu sự hỗ trợ IME cần thiết để nhập văn bản Trung Quốc, Nhật Bản, và Hàn Quốc."
-
-    # game/editor.rpy:151
-    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
-    new "{b}Khuyến khích{/ b} Một trình biên tập có giao diện thân thiện và chức năng hỗ trợ phát triển, chẳng hạn như kiểm tra lỗi chính tả. Editra hiện đang thiếu sự hỗ trợ IME cần thiết để nhập văn bản Trung Quốc, Nhật Bản, và Hàn Quốc. Với Linux Editra cần thêm wxPython."
-
-    # game/editor.rpy:167
-    old "This may have occured because wxPython is not installed on this system."
-    new "Lỗi xảy ra có thể là do wxPython chưa được cài đặt vào hệ thống."
-
-    # game/editor.rpy:169
-    old "Up to 22 MB download required."
-    new "Cần tải về 22 MB tập tin."
-
-    # game/editor.rpy:182
-    old "A mature editor that requires Java."
-    new "Một trình biên tập chuyên dụng cần Java"
-
-    # game/editor.rpy:182
-    old "1.8 MB download required."
-    new "Cần tải về 1.8 MB tập tin"
-
-    # game/editor.rpy:182
-    old "This may have occured because Java is not installed on this system."
-    new "Lỗi xảy ra có thể là do Java chưa được cài đặt vào hệ thống."
-
-    # game/editor.rpy:191
-    old "Invokes the editor your operating system has associated with .rpy files."
-    new "Gọi trình biên tập mà máy của bạn đã làm việc trên các tập tin .rpy."
-
-    # game/editor.rpy:207
-    old "Prevents Ren'Py from opening a text editor."
-    new "Chặn Ren'py mở một trình biên tập văn bản"
-
-    # game/editor.rpy:359
-    old "An exception occured while launching the text editor:\n[exception!q]"
-    new "Một lỗi xuất hiện khi đang mở trình biên tập văn bản:\n[exception!q]"
-
-    # game/editor.rpy:457
-    old "Select Editor"
-    new "Lựa chọn trình biên tập"
-
-    # game/editor.rpy:472
-    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
-    new "Một trình biên tập văn bản là chương trình mà bạn sẽ sử dụng để chỉnh sửa các tập tin kịch bản Ren'Py. Ở đây, bạn có thể chọn trình biên tập mà Ren'Py sẽ sử dụng. Nếu chưa có, trình biên tập sẽ được tự động tải về và cài đặt."
-
-
diff --git a/launcher/game/tl/vietnamese/error.rpy b/launcher/game/tl/vietnamese/error.rpy
new file mode 100644
index 0000000..dd643c3
--- /dev/null
+++ b/launcher/game/tl/vietnamese/error.rpy
@@ -0,0 +1,179 @@
+
+translate vietnamese strings:
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Tăng tốc độ đồ họa"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Tự động chọn"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Bắt buộc chạy Angle/DirectX Renderer"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Bắt buộc chạy OpenGL Renderer"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Bắt buộc chạy chương trình Renderer"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Bật"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Thay đổi sẽ có hiệu lực vào lần tiếp theo chương trình này được chạy."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Cảnh báo hiệu suất"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Máy tính này đang sử dụng phần mềm rendering."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Máy tính này không sử dụng đổ bóng."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Máy tính này hiển thị đồ họa chậm."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Máy tính này có một vấn đề hiển thị đồ họa: [problem]"
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Trình điều khiển đồ họa của nó có thể đã quá cũ hoặc vận hành lỗi. Điều này có thể dẫn đến làm chậm hoặc hiển thị đồ họa không chính xác. Cập nhật DirectX có thể khắc phục vấn đề này."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Trình điều khiển đồ họa của nó có thể đã quá cũ hoặc vận hành lỗi. Điều này có thể dẫn đến làm chậm hoặc hiển thị đồ họa không chính xác."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Cập nhật DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Tiếp tục, hiển thị cảnh báo lần sau"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Tiếp tục, không hiển thị cảnh báo nữa"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Cập nhật DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Đang cài đặt DirectX web. Nó có thể bắt đầu thu nhỏ ở thanh tác vụ. Hãy làm theo các hướng dẫn để cài đặt DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b} Lưu ý:.. {/b} Chương trình cài đặt DirectX  web của Microsof theo mặc định sẽ cài đặt thanh công cụ Bing. Nếu bạn không muốn thanh công cụ này, bỏ chọn tại ô."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Khi cài đặt kết thúc, xin vui lòng bấm vào dưới đây để khởi động lại chương trình này."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Khởi động lại"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Chọn tay cầm để cân chỉnh"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Đo đạc [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Nhấn hoặc di chuyển [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Lướt qua (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Trở về (B)"
+
+    # _errorhandling.rpym:495
+    old "Open Traceback"
+    new "Mở Traceback"
+
+    # _errorhandling.rpym:497
+    old "Opens the traceback.txt file in a text editor."
+    new "Mở tập tin traceback.txt trong một trình soạn thảo văn bản."
+
+    # _errorhandling.rpym:499
+    old "Copy to Clipboard"
+    new "Sao chép vào bản ghi"
+
+    # _errorhandling.rpym:501
+    old "Copies the traceback.txt file to the clipboard."
+    new "Lưu tập tin traceback.txt vào bản ghi."
+
+    # _errorhandling.rpym:519
+    old "An exception has occurred."
+    new "Một ngoại lệ đã xảy ra."
+
+    # _errorhandling.rpym:538
+    old "Rollback"
+    new "Quay lại"
+
+    # _errorhandling.rpym:540
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Cho phép cuộn lại về trước, cho phép bạn lưu hoặc chọn một lựa chọn khác."
+
+    # _errorhandling.rpym:543
+    old "Ignore"
+    new "Bỏ qua"
+
+    # _errorhandling.rpym:545
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Bỏ qua những ngoại lệ, cho phép bạn tiếp tục. Điều này thường gây thêm lỗi."
+
+    # _errorhandling.rpym:548
+    old "Reload"
+    new "Tải lại"
+
+    # _errorhandling.rpym:550
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Tải lại trò chơi từ đĩa, sao lưu và khôi phục lại trạng thái trò chơi nếu có thể."
+
+    # _errorhandling.rpym:560
+    old "Quits the game."
+    new "Thoát trò chơi"
+
+    # _errorhandling.rpym:582
+    old "Parsing the script failed."
+    new "Phân tích các mã kịch bản thất bại."
+
+    # _errorhandling.rpym:606
+    old "Open Parse Errors"
+    new "Mở những lỗi phân tích"
+
+    # _errorhandling.rpym:608
+    old "Opens the errors.txt file in a text editor."
+    new "Mở tập tin ERRORS.TXT vào một trình soạn thảo văn bản."
+
+    # _errorhandling.rpym:612
+    old "Copies the errors.txt file to the clipboard."
+    new "Lưu các tập tin ERRORS.TXT vào bản ghi."
+
diff --git a/launcher/game/tl/vietnamese/front_page.rpy b/launcher/game/tl/vietnamese/front_page.rpy
deleted file mode 100644
index cc15f00..0000000
--- a/launcher/game/tl/vietnamese/front_page.rpy
+++ /dev/null
@@ -1,111 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/front_page.rpy:35
-    old "Open [text] directory."
-    new "Mở thư mục [text]"
-
-    # game/front_page.rpy:93
-    old "refresh"
-    new "làm mới"
-
-    # game/front_page.rpy:120
-    old "+ Create New Project"
-    new "+ Tạo dự án mới"
-
-    # game/front_page.rpy:132
-    old "Launch Project"
-    new "Chạy dự án"
-
-    # game/front_page.rpy:149
-    old "[p.name!q] (template)"
-    new "[p.name!q] (template)"
-
-    # game/front_page.rpy:151
-    old "Select project [text]."
-    new "Chọn dự án [text]"
-
-    # game/front_page.rpy:167
-    old "Tutorial"
-    new "Hướng dẫn"
-
-    # game/front_page.rpy:168
-    old "The Question"
-    new "Câu hỏi"
-
-    # game/front_page.rpy:184
-    old "Active Project"
-    new "Dự án đang có"
-
-    # game/front_page.rpy:192
-    old "Open Directory"
-    new "Mở nguồn thư mục"
-
-    # game/front_page.rpy:197
-    old "game"
-    new "game"
-
-    # game/front_page.rpy:198
-    old "base"
-    new "base"
-
-    # game/front_page.rpy:199
-    old "images"
-    new "images"
-
-    # game/front_page.rpy:205
-    old "Edit File"
-    new "Chỉnh File"
-
-    # game/front_page.rpy:213
-    old "All script files"
-    new "Tất cả các file kịch bản"
-
-    # game/front_page.rpy:222
-    old "Navigate Script"
-    new "Điều hướng kịch bản"
-
-    # game/front_page.rpy:233
-    old "Check Script (Lint)"
-    new "Kiểm tra Script (Lint)"
-
-    # game/front_page.rpy:234
-    old "Change Theme"
-    new "Thay đổi Theme"
-
-    # game/front_page.rpy:235
-    old "Delete Persistent"
-    new "Xóa biến"
-
-    # game/front_page.rpy:244
-    old "Build Distributions"
-    new "Xuất bản"
-
-    # game/front_page.rpy:246
-    old "Android"
-    new "Android"
-
-    # game/front_page.rpy:247
-    old "iOS"
-    new "iOS"
-
-    # game/front_page.rpy:248
-    old "Generate Translations"
-    new "Tạo file dịch thuật"
-
-    # game/front_page.rpy:249
-    old "Extract Dialogue"
-    new "Trích xuất hội thoại"
-
-    # game/front_page.rpy:265
-    old "Checking script for potential problems..."
-    new "Kiểm tra các lỗi tiềm năng trong kịch bản..."
-
-    # game/front_page.rpy:280
-    old "Deleting persistent data..."
-    new "Đang xóa dữ liệu biến..."
-
-    # game/front_page.rpy:288
-    old "Recompiling all rpy files into rpyc files..."
-    new "Đang biên tập lại toàn bộ file rpy thành rpyc..."
-
diff --git a/launcher/game/tl/vietnamese/gui.rpy b/launcher/game/tl/vietnamese/gui.rpy
new file mode 100644
index 0000000..d4588ce
--- /dev/null
+++ b/launcher/game/tl/vietnamese/gui.rpy
@@ -0,0 +1,411 @@
+
+translate vietnamese strings:
+
+    # gui.rpy:2
+    old "## Initialization"
+    new "## Initialization"
+
+    # gui.rpy:5
+    old "## The init offset statement causes the init code in this file to run before init code in any other file."
+    new "## The init offset statement causes the init code in this file to run before init code in any other file."
+
+    # gui.rpy:9
+    old "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+    new "## Calling gui.init resets the styles to sensible default values, and sets the width and height of the game."
+
+    # gui.rpy:21
+    old "## Colors"
+    new "## Colors"
+
+    # gui.rpy:23
+    old "## The colors of text in the interface."
+    new "## The colors of text in the interface."
+
+    # gui.rpy:25
+    old "## An accent color used throughout the interface to label and highlight text."
+    new "## An accent color used throughout the interface to label and highlight text."
+
+    # gui.rpy:29
+    old "## The color used for a text button when it is neither selected nor hovered."
+    new "## The color used for a text button when it is neither selected nor hovered."
+
+    # gui.rpy:32
+    old "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+    new "## The small color is used for small text, which needs to be brighter/darker to achieve the same effect."
+
+    # gui.rpy:36
+    old "## The color that is used for buttons and bars that are hovered."
+    new "## The color that is used for buttons and bars that are hovered."
+
+    # gui.rpy:39
+    old "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+    new "## The color used for a text button when it is selected but not focused. A button is selected if it is the current screen or preference value."
+
+    # gui.rpy:43
+    old "## The color used for a text button when it cannot be selected."
+    new "## The color used for a text button when it cannot be selected."
+
+    # gui.rpy:46
+    old "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+    new "## Colors used for the portions of bars that are not filled in. These are not used directly, but are used when re-generating bar image files."
+
+    # gui.rpy:51
+    old "## The colors used for dialogue and menu choice text."
+    new "## The colors used for dialogue and menu choice text."
+
+    # gui.rpy:56
+    old "## Fonts and Font Sizes"
+    new "## Fonts and Font Sizes"
+
+    # gui.rpy:58
+    old "## The font used for in-game text."
+    new "## The font used for in-game text."
+
+    # gui.rpy:61
+    old "## The font used for character names."
+    new "## The font used for character names."
+
+    # gui.rpy:64
+    old "## The font used for out-of-game text."
+    new "## The font used for out-of-game text."
+
+    # gui.rpy:67
+    old "## The size of normal dialogue text."
+    new "## The size of normal dialogue text."
+
+    # gui.rpy:70
+    old "## The size of character names."
+    new "## The size of character names."
+
+    # gui.rpy:73
+    old "## The size of text in the game's user interface."
+    new "## The size of text in the game's user interface."
+
+    # gui.rpy:76
+    old "## The size of labels in the game's user interface."
+    new "## The size of labels in the game's user interface."
+
+    # gui.rpy:79
+    old "## The size of text on the notify screen."
+    new "## The size of text on the notify screen."
+
+    # gui.rpy:82
+    old "## The size of the game's title."
+    new "## The size of the game's title."
+
+    # gui.rpy:86
+    old "## Main and Game Menus"
+    new "## Main and Game Menus"
+
+    # gui.rpy:88
+    old "## The images used for the main and game menus."
+    new "## The images used for the main and game menus."
+
+    # gui.rpy:92
+    old "## Should we show the name and version of the game?"
+    new "## Should we show the name and version of the game?"
+
+    # gui.rpy:96
+    old "## Dialogue"
+    new "## Dialogue"
+
+    # gui.rpy:98
+    old "## These variables control how dialogue is displayed on the screen one line at a time."
+    new "## These variables control how dialogue is displayed on the screen one line at a time."
+
+    # gui.rpy:101
+    old "## The height of the textbox containing dialogue."
+    new "## The height of the textbox containing dialogue."
+
+    # gui.rpy:104
+    old "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+    new "## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is center, and 1.0 is the bottom."
+
+    # gui.rpy:109
+    old "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+    new "## The placement of the speaking character's name, relative to the textbox. These can be a whole number of pixels from the left or top, or 0.5 to center."
+
+    # gui.rpy:114
+    old "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the character's name. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:118
+    old "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+    new "## The width, height, and borders of the box containing the character's name, or None to automatically size it."
+
+    # gui.rpy:123
+    old "## The borders of the box containing the character's name, in left, top, right, bottom order."
+    new "## The borders of the box containing the character's name, in left, top, right, bottom order."
+
+    # gui.rpy:127
+    old "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+    new "## If True, the background of the namebox will be tiled, if False, the background if the namebox will be scaled."
+
+    # gui.rpy:132
+    old "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+    new "## The placement of dialogue relative to the textbox. These can be a whole number of pixels relative to the left or top side of the textbox, or 0.5 to center."
+
+    # gui.rpy:138
+    old "## The maximum width of dialogue text, in pixels."
+    new "## The maximum width of dialogue text, in pixels."
+
+    # gui.rpy:141
+    old "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+    new "## The horizontal alignment of the dialogue text. This can be 0.0 for left-aligned, 0.5 for centered, and 1.0 for right-aligned."
+
+    # gui.rpy:146
+    old "## Buttons"
+    new "## Buttons"
+
+    # gui.rpy:148
+    old "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+    new "## These variables, along with the image files in gui/button, control aspects of how buttons are displayed."
+
+    # gui.rpy:151
+    old "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+    new "## The width and height of a button, in pixels. If None, Ren'Py computes a size."
+
+    # gui.rpy:155
+    old "## The borders on each side of the button, in left, top, right, bottom order."
+    new "## The borders on each side of the button, in left, top, right, bottom order."
+
+    # gui.rpy:158
+    old "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+    new "## If True, the background image will be tiled. If False, the background image will be linearly scaled."
+
+    # gui.rpy:162
+    old "## The font used by the button."
+    new "## The font used by the button."
+
+    # gui.rpy:165
+    old "## The size of the text used by the button."
+    new "## The size of the text used by the button."
+
+    # gui.rpy:179
+    old "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+    new "## These variables override settings for different kinds of buttons. Please see the gui documentation for the kinds of buttons available, and what each is used for."
+
+    # gui.rpy:183
+    old "## These customizations are used by the default interface:"
+    new "## These customizations are used by the default interface:"
+
+    # gui.rpy:198
+    old "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+    new "## You can also add your own customizations, by adding properly-named variables. For example, you can uncomment the following line to set the width of a navigation button."
+
+    # gui.rpy:205
+    old "## Choice Buttons"
+    new "## Choice Buttons"
+
+    # gui.rpy:207
+    old "## Choice buttons are used in the in-game menus."
+    new "## Choice buttons are used in the in-game menus."
+
+    # gui.rpy:220
+    old "## File Slot Buttons"
+    new "## File Slot Buttons"
+
+    # gui.rpy:222
+    old "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+    new "## A file slot button is a special kind of button. It contains a thumbnail image, and text describing the contents of the save slot. A save slot uses image files in gui/button, like the other kinds of buttons."
+
+    # gui.rpy:226
+    old "## The save slot button."
+    new "## The save slot button."
+
+    # gui.rpy:234
+    old "## The width and height of thumbnails used by the save slots."
+    new "## The width and height of thumbnails used by the save slots."
+
+    # gui.rpy:238
+    old "## The number of columns and rows in the grid of save slots."
+    new "## The number of columns and rows in the grid of save slots."
+
+    # gui.rpy:243
+    old "## Positioning and Spacing"
+    new "## Positioning and Spacing"
+
+    # gui.rpy:245
+    old "## These variables control the positioning and spacing of various user interface elements."
+    new "## These variables control the positioning and spacing of various user interface elements."
+
+    # gui.rpy:248
+    old "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+    new "## The position of the left side of the navigation buttons, relative to the left side of the screen."
+
+    # gui.rpy:252
+    old "## The vertical position of the skip indicator."
+    new "## The vertical position of the skip indicator."
+
+    # gui.rpy:255
+    old "## The vertical position of the notify screen."
+    new "## The vertical position of the notify screen."
+
+    # gui.rpy:258
+    old "## The spacing between menu choices."
+    new "## The spacing between menu choices."
+
+    # gui.rpy:261
+    old "## Buttons in the navigation section of the main and game menus."
+    new "## Buttons in the navigation section of the main and game menus."
+
+    # gui.rpy:264
+    old "## Controls the amount of spacing between preferences."
+    new "## Controls the amount of spacing between preferences."
+
+    # gui.rpy:267
+    old "## Controls the amount of spacing between preference buttons."
+    new "## Controls the amount of spacing between preference buttons."
+
+    # gui.rpy:270
+    old "## The spacing between file page buttons."
+    new "## The spacing between file page buttons."
+
+    # gui.rpy:273
+    old "## The spacing between file slots."
+    new "## The spacing between file slots."
+
+    # gui.rpy:277
+    old "## Frames"
+    new "## Frames"
+
+    # gui.rpy:279
+    old "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+    new "## These variables control the look of frames that can contain user interface components when an overlay or window is not present."
+
+    # gui.rpy:282
+    old "## Generic frames that are introduced by player code."
+    new "## Generic frames that are introduced by player code."
+
+    # gui.rpy:285
+    old "## The frame that is used as part of the confirm screen."
+    new "## The frame that is used as part of the confirm screen."
+
+    # gui.rpy:288
+    old "## The frame that is used as part of the skip screen."
+    new "## The frame that is used as part of the skip screen."
+
+    # gui.rpy:291
+    old "## The frame that is used as part of the notify screen."
+    new "## The frame that is used as part of the notify screen."
+
+    # gui.rpy:294
+    old "## Should frame backgrounds be tiled?"
+    new "## Should frame backgrounds be tiled?"
+
+    # gui.rpy:298
+    old "## Bars, Scrollbars, and Sliders"
+    new "## Bars, Scrollbars, and Sliders"
+
+    # gui.rpy:300
+    old "## These control the look and size of bars, scrollbars, and sliders."
+    new "## These control the look and size of bars, scrollbars, and sliders."
+
+    # gui.rpy:302
+    old "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+    new "## The default GUI only uses sliders and vertical scrollbars. All of the other bars are only used in creator-written code."
+
+    # gui.rpy:305
+    old "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+    new "## The height of horizontal bars, scrollbars, and sliders. The width of vertical bars, scrollbars, and sliders."
+
+    # gui.rpy:311
+    old "## True if bar images should be tiled. False if they should be linearly scaled."
+    new "## True if bar images should be tiled. False if they should be linearly scaled."
+
+    # gui.rpy:316
+    old "## Horizontal borders."
+    new "## Horizontal borders."
+
+    # gui.rpy:321
+    old "## Vertical borders."
+    new "## Vertical borders."
+
+    # gui.rpy:326
+    old "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+    new "## What to do with unscrollable scrollbars in the gui. \"hide\" hides them, while None shows them."
+
+    # gui.rpy:331
+    old "## History"
+    new "## History"
+
+    # gui.rpy:333
+    old "## The history screen displays dialogue that the player has already dismissed."
+    new "## The history screen displays dialogue that the player has already dismissed."
+
+    # gui.rpy:335
+    old "## The number of blocks of dialogue history Ren'Py will keep."
+    new "## The number of blocks of dialogue history Ren'Py will keep."
+
+    # gui.rpy:338
+    old "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+    new "## The height of a history screen entry, or None to make the height variable at the cost of performance."
+
+    # gui.rpy:342
+    old "## The position, width, and alignment of the label giving the name of the speaking character."
+    new "## The position, width, and alignment of the label giving the name of the speaking character."
+
+    # gui.rpy:349
+    old "## The position, width, and alignment of the dialogue text."
+    new "## The position, width, and alignment of the dialogue text."
+
+    # gui.rpy:356
+    old "## NVL-Mode"
+    new "## NVL-Mode"
+
+    # gui.rpy:358
+    old "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+    new "## The NVL-mode screen displays the dialogue spoken by NVL-mode characters."
+
+    # gui.rpy:360
+    old "## The borders of the background of the NVL-mode background window."
+    new "## The borders of the background of the NVL-mode background window."
+
+    # gui.rpy:363
+    old "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+    new "## The height of an NVL-mode entry. Set this to None to have the entries dynamically adjust height."
+
+    # gui.rpy:367
+    old "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+    new "## The spacing between NVL-mode entries when gui.nvl_height is None, and between NVL-mode entries and an NVL-mode menu."
+
+    # gui.rpy:384
+    old "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+    new "## The position, width, and alignment of nvl_thought text (the text said by the nvl_narrator character.)"
+
+    # gui.rpy:391
+    old "## The position of nvl menu_buttons."
+    new "## The position of nvl menu_buttons."
+
+    # gui.rpy:403
+    old "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+    new "## This increases the size of the quick buttons to make them easier to touch on tablets and phones."
+
+    # gui.rpy:409
+    old "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+    new "## This changes the size and spacing of various GUI elements to ensure they are easily visible on phones."
+
+    # gui.rpy:413
+    old "## Font sizes."
+    new "## Font sizes."
+
+    # gui.rpy:421
+    old "## Adjust the location of the textbox."
+    new "## Adjust the location of the textbox."
+
+    # gui.rpy:427
+    old "## Change the size and spacing of items in the game menu."
+    new "## Change the size and spacing of items in the game menu."
+
+    # gui.rpy:436
+    old "## File button layout."
+    new "## File button layout."
+
+    # gui.rpy:440
+    old "## NVL-mode."
+    new "## NVL-mode."
+
+    # gui.rpy:456
+    old "## Quick buttons."
+    new "## Quick buttons."
+
diff --git a/launcher/game/tl/vietnamese/interface.rpy b/launcher/game/tl/vietnamese/interface.rpy
deleted file mode 100644
index c1e4402..0000000
--- a/launcher/game/tl/vietnamese/interface.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/interface.rpy:107
-    old "Documentation"
-    new "Tài liệu"
-
-    # game/interface.rpy:108
-    old "Ren'Py Website"
-    new "Ren'Py Website"
-
-    # game/interface.rpy:109
-    old "Ren'Py Games List"
-    new "Danh sách trò chơi Ren'Py"
-
-    # game/interface.rpy:110
-    old "About"
-    new "Giới thiệu"
-
-    # game/interface.rpy:117
-    old "update"
-    new "cập nhật"
-
-    # game/interface.rpy:119
-    old "preferences"
-    new "thiết lập"
-
-    # game/interface.rpy:120
-    old "quit"
-    new "thoát"
-
-    # game/interface.rpy:192
-    old "Yes"
-    new "Có"
-
-    # game/interface.rpy:194
-    old "No"
-    new "Không"
-
-    # game/interface.rpy:230
-    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
-    new "Do hạn chế định dạng gói tập tin, tên tập tin và thư mục không phải ASCII không được phép sử dụng."
-
-    # game/interface.rpy:322
-    old "ERROR"
-    new "LỖI"
-
-    # game/interface.rpy:351
-    old "While [what!q], an error occured:"
-    new "Trong khi [what!q], một lỗi xảy ra:"
-
-    # game/interface.rpy:351
-    old "[exception!q]"
-    new "[exception!q]"
-
-    # game/interface.rpy:370
-    old "Text input may not contain the {{ or [[ characters."
-    new "Văn bản không được có dấu {{ hay [["
-
-    # game/interface.rpy:375
-    old "File and directory names may not contain / or \\."
-    new "Tên file và thư mục không được có / hay \\."
-
-    # game/interface.rpy:381
-    old "File and directory names must consist of ASCII characters."
-    new "Tên tập tin và thư mục phải là ASCII."
-
-    # game/interface.rpy:402
-    old "INFORMATION"
-    new "THÔNG TIN"
-
-    # game/interface.rpy:449
-    old "PROCESSING"
-    new "ĐANG XỬ LÍ"
-
-    # game/interface.rpy:466
-    old "QUESTION"
-    new "CÂU HỎI"
-
-    # game/interface.rpy:479
-    old "CHOICE"
-    new "LỰA CHỌN"
-
diff --git a/launcher/game/tl/vietnamese/ios.rpy b/launcher/game/tl/vietnamese/ios.rpy
deleted file mode 100644
index d5dff48..0000000
--- a/launcher/game/tl/vietnamese/ios.rpy
+++ /dev/null
@@ -1,99 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/ios.rpy:28
-    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
-    new "Để xây dụng gói tin IOS, cần phải tải về renios, giải nén và đặt nó vào thư mục Ren'Py. Rồi khởi động lại Ren'Py."
-
-    # game/ios.rpy:29
-    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
-    new "Thư mục để chứa dự án Xcode chưa được chọn. Nhấn 'Chọn thư mục'"
-
-    # game/ios.rpy:30
-    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
-    new "Chưa có dự án Xcode đó tại dòng dự án Ren'Py hiện tại. Nhấn 'Tạo dự án Xcode' để tạo dự án"
-
-    # game/ios.rpy:31
-    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
-    new "Một dự án Xcode tồn tại. Chọn 'Cập nhật Dự án Xcode' để cập nhật nó với các tập tin trò chơi mới nhất, hoặc sử dụng Xcode để xây dựng và cài đặt nó."
-
-    # game/ios.rpy:33
-    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new ""
-
-    # game/ios.rpy:34
-    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
-    new "Thử giả lập iPad.\n\n Cảm ứng được giả lập qua chuột, chạm bằng cách nhấn chuột vào."
-
-    # game/ios.rpy:36
-    old "Selects the directory where Xcode projects will be placed."
-    new "Chọn thư mục mà dự án Xcode sẽ được đặt."
-
-    # game/ios.rpy:37
-    old "Creates an Xcode project corresponding to the current Ren'Py project."
-    new "Tạo một dự án Xcode ứng với dự án Ren'Py hiện có."
-
-    # game/ios.rpy:38
-    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
-    new "Cập nhật dự án Xcode với tập tin trò chơi mới nhất. Điều này phải được làm mỗi khi dự án Ren'Py có thay đổi"
-
-    # game/ios.rpy:39
-    old "Opens the Xcode project in Xcode."
-    new "Mở dự án Xcode bằng Xcode"
-
-    # game/ios.rpy:41
-    old "Opens the directory containing Xcode projects."
-    new "Mở thư mục chứa dự án Xcode"
-
-    # game/ios.rpy:126
-    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
-    new "Dự án Xcode này đã tồn tại. Bạn có muốn thay tên dự án cũ và thay thế bằng cái mới?"
-
-    # game/ios.rpy:211
-    old "iOS: [project.current.name!q]"
-    new "iOS: [project.current.name!q]"
-
-    # game/ios.rpy:240
-    old "iPhone"
-    new "iPhone"
-
-    # game/ios.rpy:244
-    old "iPad"
-    new "iPad"
-
-    # game/ios.rpy:264
-    old "Select Xcode Projects Directory"
-    new "Chọn thư mục dự án Xcode"
-
-    # game/ios.rpy:268
-    old "Create Xcode Project"
-    new "Tạo dự án Xcode"
-
-    # game/ios.rpy:272
-    old "Update Xcode Project"
-    new "Cập nhật dự án Xcode"
-
-    # game/ios.rpy:277
-    old "Launch Xcode"
-    new "Chạy Xcode"
-
-    # game/ios.rpy:312
-    old "Open Xcode Projects Directory"
-    new "Mở thư mục dự án Xcode"
-
-    # game/ios.rpy:345
-    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
-    new "Trước khi đóng gói ứng dụng iOS, bạn sẽ cần phải tải renios, phần mềm hỗ trợ xây iOS của Ren'Py. Bạn có muốn tải về renios ngay bây giờ?"
-
-    # game/ios.rpy:354
-    old "XCODE PROJECTS DIRECTORY"
-    new "THƯ MỤC DỰ ÁN XCODE"
-
-    # game/ios.rpy:354
-    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Hãy chọn thư mục dự án Xcode. \n{b} Bảng chọn thư mục có thể hiện phía sau cửa sổ này.{/b}"
-
-    # game/ios.rpy:359
-    old "Ren'Py has set the Xcode Projects Directory to:"
-    new "Ren'Py đã đặt thư mục dự án Xcode tại:"
-
diff --git a/launcher/game/tl/vietnamese/launcher.rpy b/launcher/game/tl/vietnamese/launcher.rpy
new file mode 100644
index 0000000..872becf
--- /dev/null
+++ b/launcher/game/tl/vietnamese/launcher.rpy
@@ -0,0 +1,1187 @@
+
+translate vietnamese strings:
+
+    # about.rpy:39
+    old "[version!q]"
+    new "[version!q]"
+
+    # about.rpy:43
+    old "View license"
+    new "Xem giấy phép"
+
+    # add_file.rpy:28
+    old "FILENAME"
+    new "TÊN FILE"
+
+    # add_file.rpy:28
+    old "Enter the name of the script file to create."
+    new "Nhập tên để tạo ra tập tin kịch bản"
+
+    # add_file.rpy:31
+    old "The filename must have the .rpy extension."
+    new "Tên tập tin phải có phần mở rộng .rpy."
+
+    # add_file.rpy:39
+    old "The file already exists."
+    new "Các tập tin đã tồn tại."
+
+    # add_file.rpy:42
+    old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
+    new "Ren'Py tự động tải tất cả các tập tin kịch bản kết thúc với .rpy. Để sử dụng \n# tập tin này, xác định một nhãn và nhảy vào nó từ tập tin khác.\n"
+
+    # android.rpy:30
+    old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Để xây dựng các gói Android, hãy tải về RAPT, giải nén nó và đặt nó vào thư mục Ren'Py. Sau đó khởi động lại Ren'Py."
+
+    # android.rpy:31
+    old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
+    new "Cần một bản 32-bit Java Development Kit để xây dựng gói Android trên Windows. JDK khác với JRE, vì vậy có thể là bạn có Java nhưng ko có JDK.\n\n Hãy vào {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download và cài đặt JDK{/a}, rồi khởi động lại Renpy. "
+
+    # android.rpy:32
+    old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
+    new "RAPT đã được cài đặt, nhưng bạn sẽ cần phải cài đặt Android SDK trước khi bạn có thể xây dựng các gói Android. Chọn Cài đặt SDK để làm điều này."
+
+    # android.rpy:33
+    old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
+    new "RAPT đã được cài đặt, nhưng một chính chưa được cấu hình. Hãy tạo một khóa mới, hoặc khôi phục lại android.keystore."
+
+    # android.rpy:34
+    old "The current project has not been configured. Use \"Configure\" to configure it before building."
+    new "Các dự án hiện tại chưa được cấu hình. Sử dụng \"Configure\" để cấu hình nó trước khi xây dựng."
+
+    # android.rpy:35
+    old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
+    new "Chọn \"Build\" để xây dựng các dự án hiện tại, hoặc đính kèm một thiết bị Android và chọn \"Build & Install\" để xây dựng và cài đặt nó trên thiết bị."
+
+    # android.rpy:37
+    old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Để giả lập điện thoại Android. \n\n Cảm ứng được mô phỏng thông qua chuột, nhưng chỉ khi nút được thiết lập. Thoát ra được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
+
+    # android.rpy:38
+    old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Để giả lập máy tính bảng Android. \n\n Cảm ứng được mô phỏng thông qua chuột, nhưng chỉ khi nút được thiết lập. Thoát ra được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
+
+    # android.rpy:39
+    old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
+    new "Để giả lập bộ điều khiển tivi android, như OUYA hay Fire TV. \n\n Đầu vào bộ điều khiển gắn với phím mũi tên, Enter được gắn với nút select, và Thoát ra được được gắn với nút menu của máy, và PageUp được gắn với nút quay lại."
+
+    # android.rpy:41
+    old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
+    new "Tải về và cài đặt Android SDK và các gói hỗ trợ. Tùy chọn, tạo ra các phím cần thiết để đăng ký gói."
+
+    # android.rpy:42
+    old "Configures the package name, version, and other information about this project."
+    new "Cấu hình tên gói, phiên bản, và các thông tin khác về dự án này."
+
+    # android.rpy:43
+    old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
+    new "Mở tập tin có chứa key Google Play trong trình soạn thảo. \n\nChỉ cần thiết nếu các ứng dụng đang sử dụng một gói ứng mở rộng. Đọc tài liệu để biết thêm chi tiết."
+
+    # android.rpy:44
+    old "Builds the Android package."
+    new "Xây dựng các gói Android."
+
+    # android.rpy:45
+    old "Builds the Android package, and installs it on an Android device connected to your computer."
+    new "Xây dựng các gói Android và cài đặt nó trên một thiết bị Android kết nối với máy tính của bạn."
+
+    # android.rpy:46
+    old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
+    new "Xây dựng các gói Android, cài đặt nó trên một thiết bị Android kết nối với máy tính của bạn, sau đó khởi chạy ứng dụng trên thiết bị của bạn."
+
+    # android.rpy:48
+    old "Connects to an Android device running ADB in TCP/IP mode."
+    new "Kết nối đến một thiết bị Android đang chạy trong chế độ ADB TCP / IP."
+
+    # android.rpy:49
+    old "Disconnects from an Android device running ADB in TCP/IP mode."
+    new "Ngắt kết nối từ một thiết bị Android đang chạy trong chế độ ADB TCP / IP."
+
+    # android.rpy:50
+    old "Retrieves the log from the Android device and writes it to a file."
+    new "Lấy các bản ghi từ các thiết bị Android và viết nó vào một tập tin."
+
+    # android.rpy:240
+    old "Copying Android files to distributions directory."
+    new "Sao chép tệp tin Android đến thư mục phân phối."
+
+    # android.rpy:304
+    old "Android: [project.current.name!q]"
+    new "Android: [project.current.name!q]"
+
+    # android.rpy:324
+    old "Emulation:"
+    new "Giả lập:"
+
+    # android.rpy:333
+    old "Phone"
+    new "Điện thoại"
+
+    # android.rpy:337
+    old "Tablet"
+    new "Máy tính bảng"
+
+    # android.rpy:341
+    old "Television"
+    new "Tivi"
+
+    # android.rpy:353
+    old "Build:"
+    new "Xây dựng:"
+
+    # android.rpy:361
+    old "Install SDK & Create Keys"
+    new "Cài đặt SDK & Tạo Keys"
+
+    # android.rpy:365
+    old "Configure"
+    new "Cấu hình"
+
+    # android.rpy:369
+    old "Build Package"
+    new "Xây dựng gói"
+
+    # android.rpy:373
+    old "Build & Install"
+    new "Xây dựng & Cài đặt"
+
+    # android.rpy:377
+    old "Build, Install & Launch"
+    new "Xây dựng, cài đặt và triển khai"
+
+    # android.rpy:388
+    old "Other:"
+    new "Khác:"
+
+    # android.rpy:396
+    old "Remote ADB Connect"
+    new "Kết nối ADB  từ xa"
+
+    # android.rpy:400
+    old "Remote ADB Disconnect"
+    new "Ngắt kết nối ADB  từ xa"
+
+    # android.rpy:404
+    old "Logcat"
+    new "Logcat"
+
+    # android.rpy:437
+    old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
+    new "Trước khi đóng gói ứng dụng Android, bạn sẽ cần phải tải về RAPT, Công cụ đóng gói Ren'Py Android. Bạn có muốn tải về RAPT bây giờ?"
+
+    # android.rpy:496
+    old "Remote ADB Address"
+    new "Địa chỉ ADB từ xa"
+
+    # android.rpy:496
+    old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
+    new "Hãy nhập địa chỉ IP và số cổng để kết nối, ở dạng \"192.168.1.143:. 5555\"Tham khảo tài liệu của thiết bị của bạn để xác định xem nó hỗ trợ ADB từ xa, và nếu như vậy, cần có địa chỉ và cổng để kết nối."
+
+    # android.rpy:508
+    old "Invalid remote ADB address"
+    new "Địa chỉ ADB từ xa không hợp lệ"
+
+    # android.rpy:508
+    old "The address must contain one exactly one ':'."
+    new "Các địa chỉ phải chính xác từng cái một ':'."
+
+    # android.rpy:512
+    old "The host may not contain whitespace."
+    new "Các máy chủ có thể không chứa khoảng trắng."
+
+    # android.rpy:518
+    old "The port must be a number."
+    new "Cổng port phải là một số."
+
+    # android.rpy:544
+    old "Retrieving logcat information from device."
+    new "Lấy logcat thông tin từ thiết bị."
+
+    # choose_directory.rpy:73
+    old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
+    new "Ren'Py đã không thể chạy python với Tkinter để chọn thư mục. Vui lòng cài đặt python-tk hoặc gói Tkinter ."
+
+    # choose_theme.rpy:303
+    old "Could not change the theme. Perhaps options.rpy was changed too much."
+    new "Không thể thay đổi chủ đề. Có lẽ options.rpy đã thay đổi quá nhiều."
+
+    # choose_theme.rpy:370
+    old "Planetarium"
+    new "Planetarium"
+
+    # choose_theme.rpy:425
+    old "Choose Theme"
+    new "Chọn chủ đề"
+
+    # choose_theme.rpy:438
+    old "Theme"
+    new "Chủ đề"
+
+    # choose_theme.rpy:463
+    old "Color Scheme"
+    new "Màu chủ đạo"
+
+    # choose_theme.rpy:495
+    old "Continue"
+    new "Tiếp tục"
+
+    # consolecommand.rpy:84
+    old "INFORMATION"
+    new "THÔNG TIN"
+
+    # consolecommand.rpy:84
+    old "The command is being run in a new operating system console window."
+    new "The command is being run in a new operating system console window."
+
+    # distribute.rpy:443
+    old "Scanning project files..."
+    new "Scanning project files..."
+
+    # distribute.rpy:459
+    old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+    new "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
+
+    # distribute.rpy:504
+    old "No packages are selected, so there's nothing to do."
+    new "No packages are selected, so there's nothing to do."
+
+    # distribute.rpy:516
+    old "Scanning Ren'Py files..."
+    new "Scanning Ren'Py files..."
+
+    # distribute.rpy:569
+    old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+    new "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
+
+    # distribute.rpy:752
+    old "Archiving files..."
+    new "Archiving files..."
+
+    # distribute.rpy:1050
+    old "Unpacking the Macintosh application for signing..."
+    new "Unpacking the Macintosh application for signing..."
+
+    # distribute.rpy:1060
+    old "Signing the Macintosh application..."
+    new "Signing the Macintosh application..."
+
+    # distribute.rpy:1082
+    old "Creating the Macintosh DMG..."
+    new "Creating the Macintosh DMG..."
+
+    # distribute.rpy:1091
+    old "Signing the Macintosh DMG..."
+    new "Signing the Macintosh DMG..."
+
+    # distribute.rpy:1248
+    old "Writing the [variant] [format] package."
+    new "Writing the [variant] [format] package."
+
+    # distribute.rpy:1261
+    old "Making the [variant] update zsync file."
+    new "Making the [variant] update zsync file."
+
+    # distribute.rpy:1404
+    old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+    new "Processed {b}[complete]{/b} of {b}[total]{/b} files."
+
+    # distribute_gui.rpy:157
+    old "Build Distributions: [project.current.name!q]"
+    new "Xây dựng: [project.current.name!q]"
+
+    # distribute_gui.rpy:171
+    old "Directory Name:"
+    new "Tên thư mục:"
+
+    # distribute_gui.rpy:175
+    old "Executable Name:"
+    new "Tên file thực thi:"
+
+    # distribute_gui.rpy:185
+    old "Actions:"
+    new "Hành động:"
+
+    # distribute_gui.rpy:193
+    old "Edit options.rpy"
+    new "Edit options.rpy"
+
+    # distribute_gui.rpy:194
+    old "Add from clauses to calls, once"
+    new "Thêm một lần mệnh đề from vào lệnh call."
+
+    # distribute_gui.rpy:195
+    old "Refresh"
+    new "Làm mới"
+
+    # distribute_gui.rpy:199
+    old "Upload to itch.io"
+    new "Upload to itch.io"
+
+    # distribute_gui.rpy:215
+    old "Build Packages:"
+    new "Xây dựng gói:"
+
+    # distribute_gui.rpy:234
+    old "Options:"
+    new "Tùy chọn:"
+
+    # distribute_gui.rpy:239
+    old "Build Updates"
+    new "Xây dựng bản cập nhật."
+
+    # distribute_gui.rpy:241
+    old "Add from clauses to calls"
+    new "Thêm mệnh đề from vào lệnh call."
+
+    # distribute_gui.rpy:242
+    old "Force Recompile"
+    new "Bắt buộc biên dịch lại"
+
+    # distribute_gui.rpy:246
+    old "Build"
+    new "Xây dựng"
+
+    # distribute_gui.rpy:250
+    old "Adding from clauses to call statements that do not have them."
+    new "Thêm mệnh đề from vào những lệnh call chưa có chúng."
+
+    # distribute_gui.rpy:271
+    old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
+    new "Lỗi được phát hiện khi chạy dự án. Hãy đảm bảo dự án chạy mà không có lỗi trước khi xây dựng các bản phân phối"
+
+    # distribute_gui.rpy:288
+    old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
+    new "Dự án của bạn không có thông tin xây dựng. Bạn có muốn thêm thông tin xây dựng ở cuối options.rpy không?"
+
+    # editor.rpy:150
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
+    new "{b}Khuyến khích{/ b} Một trình biên tập có giao diện thân thiện và chức năng hỗ trợ phát triển, chẳng hạn như kiểm tra lỗi chính tả. Editra hiện đang thiếu sự hỗ trợ IME cần thiết để nhập văn bản Trung Quốc, Nhật Bản, và Hàn Quốc."
+
+    # editor.rpy:151
+    old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
+    new "{b}Khuyến khích{/ b} Một trình biên tập có giao diện thân thiện và chức năng hỗ trợ phát triển, chẳng hạn như kiểm tra lỗi chính tả. Editra hiện đang thiếu sự hỗ trợ IME cần thiết để nhập văn bản Trung Quốc, Nhật Bản, và Hàn Quốc. Với Linux Editra cần thêm wxPython."
+
+    # editor.rpy:167
+    old "This may have occured because wxPython is not installed on this system."
+    new "Lỗi xảy ra có thể là do wxPython chưa được cài đặt vào hệ thống."
+
+    # editor.rpy:169
+    old "Up to 22 MB download required."
+    new "Cần tải về 22 MB tập tin."
+
+    # editor.rpy:182
+    old "A mature editor that requires Java."
+    new "Một trình biên tập chuyên dụng cần Java"
+
+    # editor.rpy:182
+    old "1.8 MB download required."
+    new "Cần tải về 1.8 MB tập tin"
+
+    # editor.rpy:182
+    old "This may have occured because Java is not installed on this system."
+    new "Lỗi xảy ra có thể là do Java chưa được cài đặt vào hệ thống."
+
+    # editor.rpy:191
+    old "Invokes the editor your operating system has associated with .rpy files."
+    new "Gọi trình biên tập mà máy của bạn đã làm việc trên các tập tin .rpy."
+
+    # editor.rpy:207
+    old "Prevents Ren'Py from opening a text editor."
+    new "Chặn Ren'py mở một trình biên tập văn bản"
+
+    # editor.rpy:359
+    old "An exception occured while launching the text editor:\n[exception!q]"
+    new "Một lỗi xuất hiện khi đang mở trình biên tập văn bản:\n[exception!q]"
+
+    # editor.rpy:457
+    old "Select Editor"
+    new "Lựa chọn trình biên tập"
+
+    # editor.rpy:472
+    old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
+    new "Một trình biên tập văn bản là chương trình mà bạn sẽ sử dụng để chỉnh sửa các tập tin kịch bản Ren'Py. Ở đây, bạn có thể chọn trình biên tập mà Ren'Py sẽ sử dụng. Nếu chưa có, trình biên tập sẽ được tự động tải về và cài đặt."
+
+    # editor.rpy:494
+    old "Cancel"
+    new "Hủy"
+
+    # front_page.rpy:35
+    old "Open [text] directory."
+    new "Mở thư mục [text]"
+
+    # front_page.rpy:93
+    old "refresh"
+    new "làm mới"
+
+    # front_page.rpy:120
+    old "+ Create New Project"
+    new "+ Tạo dự án mới"
+
+    # front_page.rpy:130
+    old "Launch Project"
+    new "Chạy dự án"
+
+    # front_page.rpy:147
+    old "[p.name!q] (template)"
+    new "[p.name!q] (template)"
+
+    # front_page.rpy:149
+    old "Select project [text]."
+    new "Chọn dự án [text]"
+
+    # front_page.rpy:165
+    old "Tutorial"
+    new "Hướng dẫn"
+
+    # front_page.rpy:166
+    old "The Question"
+    new "Câu hỏi"
+
+    # front_page.rpy:182
+    old "Active Project"
+    new "Dự án đang có"
+
+    # front_page.rpy:190
+    old "Open Directory"
+    new "Mở nguồn thư mục"
+
+    # front_page.rpy:195
+    old "game"
+    new "game"
+
+    # front_page.rpy:196
+    old "base"
+    new "base"
+
+    # front_page.rpy:197
+    old "images"
+    new "images"
+
+    # front_page.rpy:198
+    old "gui"
+    new "gui"
+
+    # front_page.rpy:204
+    old "Edit File"
+    new "Chỉnh File"
+
+    # front_page.rpy:214
+    old "All script files"
+    new "Tất cả các file kịch bản"
+
+    # front_page.rpy:223
+    old "Navigate Script"
+    new "Điều hướng kịch bản"
+
+    # front_page.rpy:234
+    old "Check Script (Lint)"
+    new "Kiểm tra Script (Lint)"
+
+    # front_page.rpy:237
+    old "Change/Update GUI"
+    new "Change/Update GUI"
+
+    # front_page.rpy:239
+    old "Change Theme"
+    new "Thay đổi Theme"
+
+    # front_page.rpy:242
+    old "Delete Persistent"
+    new "Xóa biến"
+
+    # front_page.rpy:251
+    old "Build Distributions"
+    new "Xuất bản"
+
+    # front_page.rpy:253
+    old "Android"
+    new "Android"
+
+    # front_page.rpy:254
+    old "iOS"
+    new "iOS"
+
+    # front_page.rpy:255
+    old "Generate Translations"
+    new "Tạo file dịch thuật"
+
+    # front_page.rpy:256
+    old "Extract Dialogue"
+    new "Trích xuất hội thoại"
+
+    # front_page.rpy:272
+    old "Checking script for potential problems..."
+    new "Kiểm tra các lỗi tiềm năng trong kịch bản..."
+
+    # front_page.rpy:287
+    old "Deleting persistent data..."
+    new "Đang xóa dữ liệu biến..."
+
+    # front_page.rpy:295
+    old "Recompiling all rpy files into rpyc files..."
+    new "Đang biên tập lại toàn bộ file rpy thành rpyc..."
+
+    # gui7.rpy:236
+    old "Select Accent and Background Colors"
+    new "Select Accent and Background Colors"
+
+    # gui7.rpy:250
+    old "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+    new "Please click on the color scheme you wish to use, then click Continue. These colors can be changed and customized later."
+
+    # gui7.rpy:294
+    old "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+    new "{b}Warning{/b}\nContinuing will overwrite customized bar, button, save slot, scrollbar, and slider images.\n\nWhat would you like to do?"
+
+    # gui7.rpy:294
+    old "Choose new colors, then regenerate image files."
+    new "Choose new colors, then regenerate image files."
+
+    # gui7.rpy:294
+    old "Regenerate the image files using the colors in gui.rpy."
+    new "Regenerate the image files using the colors in gui.rpy."
+
+    # gui7.rpy:314
+    old "PROJECT NAME"
+    new "TÊN DỰ ÁN"
+
+    # gui7.rpy:314
+    old "Please enter the name of your project:"
+    new "Hãy điền tên dự án của bạn:"
+
+    # gui7.rpy:322
+    old "The project name may not be empty."
+    new "Tên dự án không được để trống."
+
+    # gui7.rpy:327
+    old "[project_name!q] already exists. Please choose a different project name."
+    new "[project_name!q] đã tồn tại. Hãy chọn tên dự án khác."
+
+    # gui7.rpy:330
+    old "[project_dir!q] already exists. Please choose a different project name."
+    new "[project_name!q] đã tồn tại. Hãy chọn tên dự án khác."
+
+    # gui7.rpy:341
+    old "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+    new "What resolution should the project use? Although Ren'Py can scale the window up and down, this is the initial size of the window, the size at which assets should be drawn, and the size at which the assets will be at their sharpest.\n\nThe default of 1280x720 is a reasonable compromise."
+
+    # gui7.rpy:389
+    old "Creating the new project..."
+    new "Creating the new project..."
+
+    # gui7.rpy:391
+    old "Updating the project..."
+    new "Updating the project..."
+
+    # interface.rpy:107
+    old "Documentation"
+    new "Tài liệu"
+
+    # interface.rpy:108
+    old "Ren'Py Website"
+    new "Ren'Py Website"
+
+    # interface.rpy:109
+    old "Ren'Py Games List"
+    new "Danh sách trò chơi Ren'Py"
+
+    # interface.rpy:117
+    old "update"
+    new "cập nhật"
+
+    # interface.rpy:119
+    old "preferences"
+    new "thiết lập"
+
+    # interface.rpy:120
+    old "quit"
+    new "thoát"
+
+    # interface.rpy:232
+    old "Due to package format limitations, non-ASCII file and directory names are not allowed."
+    new "Do hạn chế định dạng gói tập tin, tên tập tin và thư mục không phải ASCII không được phép sử dụng."
+
+    # interface.rpy:327
+    old "ERROR"
+    new "LỖI"
+
+    # interface.rpy:356
+    old "While [what!q], an error occured:"
+    new "Trong khi [what!q], một lỗi xảy ra:"
+
+    # interface.rpy:356
+    old "[exception!q]"
+    new "[exception!q]"
+
+    # interface.rpy:375
+    old "Text input may not contain the {{ or [[ characters."
+    new "Văn bản không được có dấu {{ hay [["
+
+    # interface.rpy:380
+    old "File and directory names may not contain / or \\."
+    new "Tên file và thư mục không được có / hay \\."
+
+    # interface.rpy:386
+    old "File and directory names must consist of ASCII characters."
+    new "Tên tập tin và thư mục phải là ASCII."
+
+    # interface.rpy:454
+    old "PROCESSING"
+    new "ĐANG XỬ LÍ"
+
+    # interface.rpy:471
+    old "QUESTION"
+    new "CÂU HỎI"
+
+    # interface.rpy:484
+    old "CHOICE"
+    new "LỰA CHỌN"
+
+    # ios.rpy:28
+    old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
+    new "Để xây dụng gói tin IOS, cần phải tải về renios, giải nén và đặt nó vào thư mục Ren'Py. Rồi khởi động lại Ren'Py."
+
+    # ios.rpy:29
+    old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
+    new "Thư mục để chứa dự án Xcode chưa được chọn. Nhấn 'Chọn thư mục'"
+
+    # ios.rpy:30
+    old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
+    new "Chưa có dự án Xcode đó tại dòng dự án Ren'Py hiện tại. Nhấn 'Tạo dự án Xcode' để tạo dự án"
+
+    # ios.rpy:31
+    old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
+    new "Một dự án Xcode tồn tại. Chọn 'Cập nhật Dự án Xcode' để cập nhật nó với các tập tin trò chơi mới nhất, hoặc sử dụng Xcode để xây dựng và cài đặt nó."
+
+    # ios.rpy:33
+    old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+
+    # ios.rpy:34
+    old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
+    new "Thử giả lập iPad.\n\n Cảm ứng được giả lập qua chuột, chạm bằng cách nhấn chuột vào."
+
+    # ios.rpy:36
+    old "Selects the directory where Xcode projects will be placed."
+    new "Chọn thư mục mà dự án Xcode sẽ được đặt."
+
+    # ios.rpy:37
+    old "Creates an Xcode project corresponding to the current Ren'Py project."
+    new "Tạo một dự án Xcode ứng với dự án Ren'Py hiện có."
+
+    # ios.rpy:38
+    old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
+    new "Cập nhật dự án Xcode với tập tin trò chơi mới nhất. Điều này phải được làm mỗi khi dự án Ren'Py có thay đổi"
+
+    # ios.rpy:39
+    old "Opens the Xcode project in Xcode."
+    new "Mở dự án Xcode bằng Xcode"
+
+    # ios.rpy:41
+    old "Opens the directory containing Xcode projects."
+    new "Mở thư mục chứa dự án Xcode"
+
+    # ios.rpy:126
+    old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
+    new "Dự án Xcode này đã tồn tại. Bạn có muốn thay tên dự án cũ và thay thế bằng cái mới?"
+
+    # ios.rpy:211
+    old "iOS: [project.current.name!q]"
+    new "iOS: [project.current.name!q]"
+
+    # ios.rpy:240
+    old "iPhone"
+    new "iPhone"
+
+    # ios.rpy:244
+    old "iPad"
+    new "iPad"
+
+    # ios.rpy:264
+    old "Select Xcode Projects Directory"
+    new "Chọn thư mục dự án Xcode"
+
+    # ios.rpy:268
+    old "Create Xcode Project"
+    new "Tạo dự án Xcode"
+
+    # ios.rpy:272
+    old "Update Xcode Project"
+    new "Cập nhật dự án Xcode"
+
+    # ios.rpy:277
+    old "Launch Xcode"
+    new "Chạy Xcode"
+
+    # ios.rpy:312
+    old "Open Xcode Projects Directory"
+    new "Mở thư mục dự án Xcode"
+
+    # ios.rpy:345
+    old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
+    new "Trước khi đóng gói ứng dụng iOS, bạn sẽ cần phải tải renios, phần mềm hỗ trợ xây iOS của Ren'Py. Bạn có muốn tải về renios ngay bây giờ?"
+
+    # ios.rpy:354
+    old "XCODE PROJECTS DIRECTORY"
+    new "THƯ MỤC DỰ ÁN XCODE"
+
+    # ios.rpy:354
+    old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Hãy chọn thư mục dự án Xcode. \n{b} Bảng chọn thư mục có thể hiện phía sau cửa sổ này.{/b}"
+
+    # ios.rpy:359
+    old "Ren'Py has set the Xcode Projects Directory to:"
+    new "Ren'Py đã đặt thư mục dự án Xcode tại:"
+
+    # itch.rpy:60
+    old "The built distributions could not be found. Please choose 'Build' and try again."
+    new "The built distributions could not be found. Please choose 'Build' and try again."
+
+    # itch.rpy:91
+    old "No uploadable files were found. Please choose 'Build' and try again."
+    new "No uploadable files were found. Please choose 'Build' and try again."
+
+    # itch.rpy:99
+    old "The butler program was not found."
+    new "The butler program was not found."
+
+    # itch.rpy:99
+    old "Please install the itch.io app, which includes butler, and try again."
+    new "Please install the itch.io app, which includes butler, and try again."
+
+    # itch.rpy:108
+    old "The name of the itch project has not been set."
+    new "The name of the itch project has not been set."
+
+    # itch.rpy:108
+    old "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+    new "Please {a=https://itch.io/game/new}create your project{/a}, then add a line like \n{vspace=5}define build.itch_project = \"user-name/game-name\"\n{vspace=5} to options.rpy."
+
+    # mobilebuild.rpy:109
+    old "{a=%s}%s{/a}"
+    new "{a=%s}%s{/a}"
+
+    # navigation.rpy:168
+    old "Navigate: [project.current.name]"
+    new "Điều hướng: [project.current.name]"
+
+    # navigation.rpy:177
+    old "Order: "
+    new "Thứ tự:"
+
+    # navigation.rpy:178
+    old "alphabetical"
+    new "bảng chữ cái"
+
+    # navigation.rpy:180
+    old "by-file"
+    new "bằng-file"
+
+    # navigation.rpy:182
+    old "natural"
+    new "tự nhiên"
+
+    # navigation.rpy:194
+    old "Category:"
+    new "Phân loại:"
+
+    # navigation.rpy:196
+    old "files"
+    new "tập tin"
+
+    # navigation.rpy:197
+    old "labels"
+    new "nhãn"
+
+    # navigation.rpy:198
+    old "defines"
+    new "gán"
+
+    # navigation.rpy:199
+    old "transforms"
+    new "chuyển động"
+
+    # navigation.rpy:200
+    old "screens"
+    new "màn hình"
+
+    # navigation.rpy:201
+    old "callables"
+    new "gọi"
+
+    # navigation.rpy:202
+    old "TODOs"
+    new "Ghi Chú"
+
+    # navigation.rpy:241
+    old "+ Add script file"
+    new "+ Thêm tập tin kịch bản"
+
+    # navigation.rpy:249
+    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
+    new "Không thấy ghi chú nào được tìm thấy.\n\nĐể tạo một thêm \"# TODO\" vào kịch bản của bạn"
+
+    # navigation.rpy:256
+    old "The list of names is empty."
+    new "Danh sách tên trống"
+
+    # new_project.rpy:38
+    old "New GUI Interface"
+    new "New GUI Interface"
+
+    # new_project.rpy:48
+    old "Both interfaces have been translated to your language."
+    new "Both interfaces have been translated to your language."
+
+    # new_project.rpy:50
+    old "Only the new GUI has been translated to your language."
+    new "Only the new GUI has been translated to your language."
+
+    # new_project.rpy:52
+    old "Only the legacy theme interface has been translated to your language."
+    new "Only the legacy theme interface has been translated to your language."
+
+    # new_project.rpy:54
+    old "Neither interface has been translated to your language."
+    new "Neither interface has been translated to your language."
+
+    # new_project.rpy:63
+    old "The projects directory could not be set. Giving up."
+    new "Thư mục dự án không thể thiết lập. Bỏ cuộc đi."
+
+    # new_project.rpy:69
+    old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+    new "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
+
+    # new_project.rpy:69
+    old "Legacy Theme Interface"
+    new "Legacy Theme Interface"
+
+    # new_project.rpy:90
+    old "Choose Project Template"
+    new "Chọn mẫu dự án"
+
+    # new_project.rpy:108
+    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
+    new "Hãy chọn mẫu cho dự án mới của bạn. Mẫu sẽ tự thiết lập font mặc định và giao diện ngôn ngữ. Nếu ngôn ngữ của bạn không được hỗ trợ, mặc định chọn 'english'."
+
+    # preferences.rpy:64
+    old "Launcher Preferences"
+    new "Điều chỉnh"
+
+    # preferences.rpy:85
+    old "Projects Directory:"
+    new "Thư mục Project:"
+
+    # preferences.rpy:92
+    old "[persistent.projects_directory!q]"
+    new "[persistent.projects_directory!q]"
+
+    # preferences.rpy:94
+    old "Projects directory: [text]"
+    new "Thư mục project: [text]"
+
+    # preferences.rpy:96
+    old "Not Set"
+    new "Chưa thiết lập"
+
+    # preferences.rpy:111
+    old "Text Editor:"
+    new "Trình sửa văn bản:"
+
+    # preferences.rpy:117
+    old "Text editor: [text]"
+    new "Trình sửa văn bản: [text]"
+
+    # preferences.rpy:133
+    old "Update Channel:"
+    new "Kênh cập nhật:"
+
+    # preferences.rpy:153
+    old "Navigation Options:"
+    new "Tùy chọn chuyển hướng:"
+
+    # preferences.rpy:157
+    old "Include private names"
+    new "Bao gồm tên cá nhân"
+
+    # preferences.rpy:158
+    old "Include library names"
+    new "Bao gồm thư viện tên"
+
+    # preferences.rpy:168
+    old "Launcher Options:"
+    new "Tùy chọn trình chạy:"
+
+    # preferences.rpy:172
+    old "Hardware rendering"
+    new "Trình ghi phần cứng"
+
+    # preferences.rpy:173
+    old "Show templates"
+    new "Hiện mẫu"
+
+    # preferences.rpy:174
+    old "Show edit file section"
+    new "Hiện mục file chỉnh sửa"
+
+    # preferences.rpy:175
+    old "Large fonts"
+    new "Font lớn"
+
+    # preferences.rpy:178
+    old "Console output"
+    new "Đầu ra bộ điều khiển"
+
+    # preferences.rpy:199
+    old "Open launcher project"
+    new "Mở dự án của trình chạy"
+
+    # preferences.rpy:213
+    old "Language:"
+    new "Ngôn ngữ:"
+
+    # project.rpy:47
+    old "After making changes to the script, press shift+R to reload your game."
+    new "Sau khi thay đổi nội dung kịch bản, nhấn shift+R để tải lại trò chơi."
+
+    # project.rpy:47
+    old "Press shift+O (the letter) to access the console."
+    new "Nhấn shift+O để truy cập đến bảng điều khiển."
+
+    # project.rpy:47
+    old "Press shift+D to access the developer menu."
+    new "Nhấn Shift+D để truy cập menu nhà phát triển."
+
+    # project.rpy:47
+    old "Have you backed up your projects recently?"
+    new "Bạn đã sao lưu dự án của bạn chưa?"
+
+    # project.rpy:229
+    old "Launching the project failed."
+    new "Chạy dự án thất bại."
+
+    # project.rpy:229
+    old "Please ensure that your project launches normally before running this command."
+    new "Hãy chắc chắn dự án của bạn vận hành bình thường trước khi chạy câu lệnh này."
+
+    # project.rpy:242
+    old "Ren'Py is scanning the project..."
+    new "Ren'Py đang quét dự án..."
+
+    # project.rpy:568
+    old "Launching"
+    new "Đang chạy"
+
+    # project.rpy:597
+    old "PROJECTS DIRECTORY"
+    new "THƯ MỤC DỰ ÁN"
+
+    # project.rpy:597
+    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
+    new "Hãy chọn thư mục dự án.\n{b} Bảng chọn thư mục có thể hiện ở phía sau cửa sổ này.{/b}"
+
+    # project.rpy:597
+    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
+    new "Ren'Py sẽ quét qua các dự án được chứa trong thư mục này, những dự án mới sẽ được tạo và đặt trong thư mục này."
+
+    # project.rpy:602
+    old "Ren'Py has set the projects directory to:"
+    new "Ren'Py đang thiết đặt thư mục dự án là:"
+
+    # translations.rpy:63
+    old "Translations: [project.current.name!q]"
+    new "Translations: [project.current.name!q]"
+
+    # translations.rpy:104
+    old "The language to work with. This should only contain lower-case ASCII characters and underscores."
+    new "The language to work with. This should only contain lower-case ASCII characters and underscores."
+
+    # translations.rpy:130
+    old "Generate empty strings for translations"
+    new "Tạo chuỗi rỗng cho bản dịch"
+
+    # translations.rpy:148
+    old "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+    new "Generates or updates translation files. The files will be placed in game/tl/[persistent.translate_language!q]."
+
+    # translations.rpy:168
+    old "Extract String Translations"
+    new "Extract String Translations"
+
+    # translations.rpy:170
+    old "Merge String Translations"
+    new "Merge String Translations"
+
+    # translations.rpy:175
+    old "Replace existing translations"
+    new "Replace existing translations"
+
+    # translations.rpy:176
+    old "Reverse languages"
+    new "Reverse languages"
+
+    # translations.rpy:180
+    old "Update Default Interface Translations"
+    new "Update Default Interface Translations"
+
+    # translations.rpy:200
+    old "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+    new "The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project."
+
+    # translations.rpy:224
+    old "Ren'Py is generating translations...."
+    new "Ren'Py đang tạo bản dịch ...."
+
+    # translations.rpy:235
+    old "Ren'Py has finished generating [language] translations."
+    new "Ren'Py đã hoàn tất việc tạo bản dịch [language]."
+
+    # translations.rpy:248
+    old "Ren'Py is extracting string translations..."
+    new "Ren'Py is extracting string translations..."
+
+    # translations.rpy:251
+    old "Ren'Py has finished extracting [language] string translations."
+    new "Ren'Py has finished extracting [language] string translations."
+
+    # translations.rpy:271
+    old "Ren'Py is merging string translations..."
+    new "Ren'Py is merging string translations..."
+
+    # translations.rpy:274
+    old "Ren'Py has finished merging [language] string translations."
+    new "Ren'Py has finished merging [language] string translations."
+
+    # translations.rpy:282
+    old "Updating default interface translations..."
+    new "Updating default interface translations..."
+
+    # translations.rpy:306
+    old "Extract Dialogue: [project.current.name!q]"
+    new "Trích xuất hội thoại: [project.current.name!q]"
+
+    # translations.rpy:322
+    old "Format:"
+    new "Định dạng:"
+
+    # translations.rpy:330
+    old "Tab-delimited Spreadsheet (dialogue.tab)"
+    new "Bảng phân loại hội thoại (dialogue.tab)"
+
+    # translations.rpy:331
+    old "Dialogue Text Only (dialogue.txt)"
+    new "Chỉ văn bản hội thoại (dialogue.txt)"
+
+    # translations.rpy:344
+    old "Strip text tags from the dialogue."
+    new "Bỏ tag của văn bản ra khỏi hội thoại."
+
+    # translations.rpy:345
+    old "Escape quotes and other special characters."
+    new "Bỏ trích dẫn và các kí tự đặc biệt."
+
+    # translations.rpy:346
+    old "Extract all translatable strings, not just dialogue."
+    new "Trích xuất mọi bản dịch, không chỉ mỗi phần hội thoại."
+
+    # translations.rpy:374
+    old "Ren'Py is extracting dialogue...."
+    new "Ren'Py đang trích xuất hội thoại...."
+
+    # translations.rpy:378
+    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
+    new "Ren'Py đã hoàn thành việc trích xuất hội thoại. File hội thoại được trích xuất có thể được tìm thất tại dialogue.[persistent.dialogue_format] trong thư mục gốc của dự án."
+
+    # updater.rpy:75
+    old "Select Update Channel"
+    new "Chọn kênh cập nhật"
+
+    # updater.rpy:86
+    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
+    new "Kênh cập nhật sẽ kiểm soát và tải về bản cập nhật của Ren'Py. Vui lòng chọn một kênh cập nhật:"
+
+    # updater.rpy:91
+    old "Release"
+    new "Bản phát hành"
+
+    # updater.rpy:97
+    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
+    new "{b}Khuyến khích{/b} sử dụng phiên bản này cho tất cả các trò chơi mới được phát hành."
+
+    # updater.rpy:102
+    old "Prerelease"
+    new "Bản gần hoàn thiện"
+
+    # updater.rpy:108
+    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
+    new "Phiên bản dùng để thử các tiện ích mới, công cụ mới nhất sẽ có trong phiên bản sau của Ren'Py, nhưng không nên sử dụng để phát hành game cuối cùng vì có thể còn lỗi."
+
+    # updater.rpy:114
+    old "Experimental"
+    new "Bản thử nghiệm"
+
+    # updater.rpy:120
+    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
+    new "Phiên bản thí nghiệm của Ren'Py. Bạn không nên chọn kênh này nếu chưa hỏi nhà phát triển Ren'py."
+
+    # updater.rpy:126
+    old "Nightly"
+    new "Bản tăm tối"
+
+    # updater.rpy:132
+    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
+    new "Rìa gần nhất tới sự phát triển của Ren'Py. Nó có thể chứa các tính năng mới nhất hoặc chẳng chạy được luôn."
+
+    # updater.rpy:152
+    old "An error has occured:"
+    new "Một lỗi đã xảy ra:"
+
+    # updater.rpy:154
+    old "Checking for updates."
+    new "Kiểm tra các bản cập nhật."
+
+    # updater.rpy:156
+    old "Ren'Py is up to date."
+    new "Ren'Py đã cập nhật phiên bản mới nhất."
+
+    # updater.rpy:158
+    old "[u.version] is now available. Do you want to install it?"
+    new "Có thể cập nhật bản [u.version]. Bạn có muốn cài đặt nó không?"
+
+    # updater.rpy:160
+    old "Preparing to download the update."
+    new "Chuẩn bị tải về bản cập nhật."
+
+    # updater.rpy:162
+    old "Downloading the update."
+    new "Đang tải bản cập nhật."
+
+    # updater.rpy:164
+    old "Unpacking the update."
+    new "Đang bung bản cập nhật."
+
+    # updater.rpy:166
+    old "Finishing up."
+    new "Kết thúc"
+
+    # updater.rpy:168
+    old "The update has been installed. Ren'Py will restart."
+    new "Bản cập nhật đã được cài đặt. Ren'Py sẽ tái khởi động."
+
+    # updater.rpy:170
+    old "The update has been installed."
+    new "Bản cập nhật đã cài xong."
+
+    # updater.rpy:172
+    old "The update was cancelled."
+    new "Bản cập nhật đã được hủy."
+
+    # updater.rpy:189
+    old "Ren'Py Update"
+    new "Cập nhật Ren'Py"
+
+    # updater.rpy:195
+    old "Proceed"
+    new "Tiếp tục"
+
diff --git a/launcher/game/tl/vietnamese/mobilebuild.rpy b/launcher/game/tl/vietnamese/mobilebuild.rpy
deleted file mode 100644
index 20042f9..0000000
--- a/launcher/game/tl/vietnamese/mobilebuild.rpy
+++ /dev/null
@@ -1,7 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/mobilebuild.rpy:109
-    old "{a=%s}%s{/a}"
-    new "{a=%s}%s{/a}"
-
diff --git a/launcher/game/tl/vietnamese/navigation.rpy b/launcher/game/tl/vietnamese/navigation.rpy
deleted file mode 100644
index 465ebf2..0000000
--- a/launcher/game/tl/vietnamese/navigation.rpy
+++ /dev/null
@@ -1,67 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/navigation.rpy:168
-    old "Navigate: [project.current.name]"
-    new "Điều hướng: [project.current.name]"
-
-    # game/navigation.rpy:177
-    old "Order: "
-    new "Thứ tự:"
-
-    # game/navigation.rpy:178
-    old "alphabetical"
-    new "bảng chữ cái"
-
-    # game/navigation.rpy:180
-    old "by-file"
-    new "bằng-file"
-
-    # game/navigation.rpy:182
-    old "natural"
-    new "tự nhiên"
-
-    # game/navigation.rpy:194
-    old "Category:"
-    new "Phân loại:"
-
-    # game/navigation.rpy:196
-    old "files"
-    new "tập tin"
-
-    # game/navigation.rpy:197
-    old "labels"
-    new "nhãn"
-
-    # game/navigation.rpy:198
-    old "defines"
-    new "gán"
-
-    # game/navigation.rpy:199
-    old "transforms"
-    new "chuyển động"
-
-    # game/navigation.rpy:200
-    old "screens"
-    new "màn hình"
-
-    # game/navigation.rpy:201
-    old "callables"
-    new "gọi"
-
-    # game/navigation.rpy:202
-    old "TODOs"
-    new "Ghi Chú"
-
-    # game/navigation.rpy:241
-    old "+ Add script file"
-    new "+ Thêm tập tin kịch bản"
-
-    # game/navigation.rpy:249
-    old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
-    new "Không thấy ghi chú nào được tìm thấy.\n\nĐể tạo một thêm \"# TODO\" vào kịch bản của bạn"
-
-    # game/navigation.rpy:256
-    old "The list of names is empty."
-    new "Danh sách tên trống"
-
diff --git a/launcher/game/tl/vietnamese/new_project.rpy b/launcher/game/tl/vietnamese/new_project.rpy
deleted file mode 100644
index bce4d16..0000000
--- a/launcher/game/tl/vietnamese/new_project.rpy
+++ /dev/null
@@ -1,35 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/new_project.rpy:40
-    old "Choose Project Template"
-    new "Chọn mẫu dự án"
-
-    # game/new_project.rpy:58
-    old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
-    new "Hãy chọn mẫu cho dự án mới của bạn. Mẫu sẽ tự thiết lập font mặc định và giao diện ngôn ngữ. Nếu ngôn ngữ của bạn không được hỗ trợ, mặc định chọn 'english'."
-
-    # game/new_project.rpy:71
-    old "The projects directory could not be set. Giving up."
-    new "Thư mục dự án không thể thiết lập. Bỏ cuộc đi."
-
-    # game/new_project.rpy:75
-    old "PROJECT NAME"
-    new "TÊN DỰ ÁN"
-
-    # game/new_project.rpy:75
-    old "Please enter the name of your project:"
-    new "Hãy điền tên dự án của bạn:"
-
-    # game/new_project.rpy:83
-    old "The project name may not be empty."
-    new "Tên dự án không được để trống."
-
-    # game/new_project.rpy:88
-    old "[project_name!q] already exists. Please choose a different project name."
-    new "[project_name!q] đã tồn tại. Hãy chọn tên dự án khác."
-
-    # game/new_project.rpy:91
-    old "[project_dir!q] already exists. Please choose a different project name."
-    new "[project_name!q] đã tồn tại. Hãy chọn tên dự án khác."
-
diff --git a/launcher/game/tl/vietnamese/obsolete.rpy b/launcher/game/tl/vietnamese/obsolete.rpy
new file mode 100644
index 0000000..173f0e5
--- /dev/null
+++ b/launcher/game/tl/vietnamese/obsolete.rpy
@@ -0,0 +1,27 @@
+
+translate vietnamese strings:
+
+    # _layout/classic_joystick_preferences.rpym:94
+    old "Joystick Mapping"
+    new "Hệ thống nút tay cầm"
+
+    # _layout/classic_load_save.rpym:138
+    old "Empty Slot."
+    new "Ô còn trống"
+
+    # _layout/classic_load_save.rpym:170
+    old "a"
+    new "a"
+
+    # _layout/classic_load_save.rpym:179
+    old "q"
+    new "q"
+
+    # _compat/gamemenu.rpym:355
+    old "Previous"
+    new "Về trước"
+
+    # _compat/gamemenu.rpym:362
+    old "Next"
+    new "Về sau"
+
diff --git a/launcher/game/tl/vietnamese/options.rpy b/launcher/game/tl/vietnamese/options.rpy
new file mode 100644
index 0000000..d58a714
--- /dev/null
+++ b/launcher/game/tl/vietnamese/options.rpy
@@ -0,0 +1,195 @@
+
+translate vietnamese strings:
+
+    # options.rpy:1
+    old "## This file contains options that can be changed to customize your game."
+    new "## This file contains options that can be changed to customize your game."
+
+    # options.rpy:4
+    old "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+    new "## Lines beginning with two '#' marks are comments, and you shouldn't uncomment them. Lines beginning with a single '#' mark are commented-out code, and you may want to uncomment them when appropriate."
+
+    # options.rpy:10
+    old "## Basics"
+    new "## Basics"
+
+    # options.rpy:12
+    old "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+    new "## A human-readable name of the game. This is used to set the default window title, and shows up in the interface and error reports."
+
+    # options.rpy:15
+    old "## The _() surrounding the string marks it as eligible for translation."
+    new "## The _() surrounding the string marks it as eligible for translation."
+
+    # options.rpy:17
+    old "Ren'Py 7 Default GUI"
+    new "Ren'Py 7 Default GUI"
+
+    # options.rpy:20
+    old "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+    new "## Determines if the title given above is shown on the main menu screen. Set this to False to hide the title."
+
+    # options.rpy:26
+    old "## The version of the game."
+    new "## The version of the game."
+
+    # options.rpy:31
+    old "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+    new "## Text that is placed on the game's about screen. To insert a blank line between paragraphs, write \\n\\n."
+
+    # options.rpy:37
+    old "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+    new "## A short name for the game used for executables and directories in the built distribution. This must be ASCII-only, and must not contain spaces, colons, or semicolons."
+
+    # options.rpy:44
+    old "## Sounds and music"
+    new "## Sounds and music"
+
+    # options.rpy:46
+    old "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+    new "## These three variables control which mixers are shown to the player by default. Setting one of these to False will hide the appropriate mixer."
+
+    # options.rpy:55
+    old "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+    new "## To allow the user to play a test sound on the sound or voice channel, uncomment a line below and use it to set a sample sound to play."
+
+    # options.rpy:62
+    old "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+    new "## Uncomment the following line to set an audio file that will be played while the player is at the main menu. This file will continue playing into the game, until it is stopped or another file is played."
+
+    # options.rpy:69
+    old "## Transitions"
+    new "## Transitions"
+
+    # options.rpy:71
+    old "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+    new "## These variables set transitions that are used when certain events occur. Each variable should be set to a transition, or None to indicate that no transition should be used."
+
+    # options.rpy:75
+    old "## Entering or exiting the game menu."
+    new "## Entering or exiting the game menu."
+
+    # options.rpy:81
+    old "## A transition that is used after a game has been loaded."
+    new "## A transition that is used after a game has been loaded."
+
+    # options.rpy:86
+    old "## Used when entering the main menu after the game has ended."
+    new "## Used when entering the main menu after the game has ended."
+
+    # options.rpy:91
+    old "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+    new "## A variable to set the transition used when the game starts does not exist. Instead, use a with statement after showing the initial scene."
+
+    # options.rpy:96
+    old "## Window management"
+    new "## Window management"
+
+    # options.rpy:98
+    old "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+    new "## This controls when the dialogue window is displayed. If \"show\", it is always displayed. If \"hide\", it is only displayed when dialogue is present. If \"auto\", the window is hidden before scene statements and shown again once dialogue is displayed."
+
+    # options.rpy:103
+    old "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+    new "## After the game has started, this can be changed with the \"window show\", \"window hide\", and \"window auto\" statements."
+
+    # options.rpy:109
+    old "## Transitions used to show and hide the dialogue window"
+    new "## Transitions used to show and hide the dialogue window"
+
+    # options.rpy:115
+    old "## Preference defaults"
+    new "## Preference defaults"
+
+    # options.rpy:117
+    old "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+    new "## Controls the default text speed. The default, 0, is infinite, while any other number is the number of characters per second to type out."
+
+    # options.rpy:123
+    old "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+    new "## The default auto-forward delay. Larger numbers lead to longer waits, with 0 to 30 being the valid range."
+
+    # options.rpy:129
+    old "## Save directory"
+    new "## Save directory"
+
+    # options.rpy:131
+    old "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+    new "## Controls the platform-specific place Ren'Py will place the save files for this game. The save files will be placed in:"
+
+    # options.rpy:134
+    old "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+    new "## Windows: %APPDATA\\RenPy\\<config.save_directory>"
+
+    # options.rpy:136
+    old "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+    new "## Macintosh: $HOME/Library/RenPy/<config.save_directory>"
+
+    # options.rpy:138
+    old "## Linux: $HOME/.renpy/<config.save_directory>"
+    new "## Linux: $HOME/.renpy/<config.save_directory>"
+
+    # options.rpy:140
+    old "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+    new "## This generally should not be changed, and if it is, should always be a literal string, not an expression."
+
+    # options.rpy:146
+    old "## Icon ########################################################################'"
+    new "## Icon ########################################################################'"
+
+    # options.rpy:148
+    old "## The icon displayed on the taskbar or dock."
+    new "## The icon displayed on the taskbar or dock."
+
+    # options.rpy:153
+    old "## Build configuration"
+    new "## Build configuration"
+
+    # options.rpy:155
+    old "## This section controls how Ren'Py turns your project into distribution files."
+    new "## This section controls how Ren'Py turns your project into distribution files."
+
+    # options.rpy:160
+    old "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+    new "## The following functions take file patterns. File patterns are case- insensitive, and matched against the path relative to the base directory, with and without a leading /. If multiple patterns match, the first is used."
+
+    # options.rpy:165
+    old "## In a pattern:"
+    new "## In a pattern:"
+
+    # options.rpy:167
+    old "## / is the directory separator."
+    new "## / is the directory separator."
+
+    # options.rpy:169
+    old "## * matches all characters, except the directory separator."
+    new "## * matches all characters, except the directory separator."
+
+    # options.rpy:171
+    old "## ** matches all characters, including the directory separator."
+    new "## ** matches all characters, including the directory separator."
+
+    # options.rpy:173
+    old "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+    new "## For example, \"*.txt\" matches txt files in the base directory, \"game/**.ogg\" matches ogg files in the game directory or any of its subdirectories, and \"**.psd\" matches psd files anywhere in the project."
+
+    # options.rpy:177
+    old "## Classify files as None to exclude them from the built distributions."
+    new "## Classify files as None to exclude them from the built distributions."
+
+    # options.rpy:185
+    old "## To archive files, classify them as 'archive'."
+    new "## To archive files, classify them as 'archive'."
+
+    # options.rpy:190
+    old "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+    new "## Files matching documentation patterns are duplicated in a mac app build, so they appear in both the app and the zip file."
+
+    # options.rpy:196
+    old "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+    new "## A Google Play license key is required to download expansion files and perform in-app purchases. It can be found on the \"Services & APIs\" page of the Google Play developer console."
+
+    # options.rpy:203
+    old "## The username and project name associated with an itch.io project, separated by a slash."
+    new "## The username and project name associated with an itch.io project, separated by a slash."
+
diff --git a/launcher/game/tl/vietnamese/preferences.rpy b/launcher/game/tl/vietnamese/preferences.rpy
deleted file mode 100644
index 361b2b1..0000000
--- a/launcher/game/tl/vietnamese/preferences.rpy
+++ /dev/null
@@ -1,83 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/preferences.rpy:64
-    old "Launcher Preferences"
-    new "Điều chỉnh"
-
-    # game/preferences.rpy:85
-    old "Projects Directory:"
-    new "Thư mục Project:"
-
-    # game/preferences.rpy:92
-    old "[persistent.projects_directory!q]"
-    new "[persistent.projects_directory!q]"
-
-    # game/preferences.rpy:94
-    old "Projects directory: [text]"
-    new "Thư mục project: [text]"
-
-    # game/preferences.rpy:96
-    old "Not Set"
-    new "Chưa thiết lập"
-
-    # game/preferences.rpy:111
-    old "Text Editor:"
-    new "Trình sửa văn bản:"
-
-    # game/preferences.rpy:117
-    old "Text editor: [text]"
-    new "Trình sửa văn bản: [text]"
-
-    # game/preferences.rpy:133
-    old "Update Channel:"
-    new "Kênh cập nhật:"
-
-    # game/preferences.rpy:153
-    old "Navigation Options:"
-    new "Tùy chọn chuyển hướng:"
-
-    # game/preferences.rpy:157
-    old "Include private names"
-    new "Bao gồm tên cá nhân"
-
-    # game/preferences.rpy:158
-    old "Include library names"
-    new "Bao gồm thư viện tên"
-
-    # game/preferences.rpy:168
-    old "Launcher Options:"
-    new "Tùy chọn trình chạy:"
-
-    # game/preferences.rpy:172
-    old "Hardware rendering"
-    new "Trình ghi phần cứng"
-
-    # game/preferences.rpy:173
-    old "Show templates"
-    new "Hiện mẫu"
-
-    # game/preferences.rpy:174
-    old "Show edit file section"
-    new "Hiện mục file chỉnh sửa"
-
-    # game/preferences.rpy:175
-    old "Large fonts"
-    new "Font lớn"
-
-    # game/preferences.rpy:176
-    old "Generate empty strings for translations"
-    new "Tạo chuỗi rỗng cho bản dịch"
-
-    # game/preferences.rpy:179
-    old "Console output"
-    new "Đầu ra bộ điều khiển"
-
-    # game/preferences.rpy:200
-    old "Open launcher project"
-    new "Mở dự án của trình chạy"
-
-    # game/preferences.rpy:214
-    old "Language:"
-    new "Ngôn ngữ:"
-
diff --git a/launcher/game/tl/vietnamese/project.rpy b/launcher/game/tl/vietnamese/project.rpy
deleted file mode 100644
index 221069e..0000000
--- a/launcher/game/tl/vietnamese/project.rpy
+++ /dev/null
@@ -1,51 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/project.rpy:47
-    old "After making changes to the script, press shift+R to reload your game."
-    new "Sau khi thay đổi nội dung kịch bản, nhấn shift+R để tải lại trò chơi."
-
-    # game/project.rpy:47
-    old "Press shift+O (the letter) to access the console."
-    new "Nhấn shift+O để truy cập đến bảng điều khiển."
-
-    # game/project.rpy:47
-    old "Press shift+D to access the developer menu."
-    new "Nhấn Shift+D để truy cập menu nhà phát triển."
-
-    # game/project.rpy:47
-    old "Have you backed up your projects recently?"
-    new "Bạn đã sao lưu dự án của bạn chưa?"
-
-    # game/project.rpy:225
-    old "Launching the project failed."
-    new "Chạy dự án thất bại."
-
-    # game/project.rpy:225
-    old "Please ensure that your project launches normally before running this command."
-    new "Hãy chắc chắn dự án của bạn vận hành bình thường trước khi chạy câu lệnh này."
-
-    # game/project.rpy:238
-    old "Ren'Py is scanning the project..."
-    new "Ren'Py đang quét dự án..."
-
-    # game/project.rpy:530
-    old "Launching"
-    new "Đang chạy"
-
-    # game/project.rpy:559
-    old "PROJECTS DIRECTORY"
-    new "THƯ MỤC DỰ ÁN"
-
-    # game/project.rpy:559
-    old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
-    new "Hãy chọn thư mục dự án.\n{b} Bảng chọn thư mục có thể hiện ở phía sau cửa sổ này.{/b}"
-
-    # game/project.rpy:559
-    old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
-    new "Ren'Py sẽ quét qua các dự án được chứa trong thư mục này, những dự án mới sẽ được tạo và đặt trong thư mục này."
-
-    # game/project.rpy:564
-    old "Ren'Py has set the projects directory to:"
-    new "Ren'Py đang thiết đặt thư mục dự án là:"
-
diff --git a/launcher/game/tl/vietnamese/screens.rpy b/launcher/game/tl/vietnamese/screens.rpy
new file mode 100644
index 0000000..3ee119b
--- /dev/null
+++ b/launcher/game/tl/vietnamese/screens.rpy
@@ -0,0 +1,643 @@
+
+translate vietnamese strings:
+
+    # screens.rpy:9
+    old "## Styles"
+    new "## Styles"
+
+    # screens.rpy:87
+    old "## In-game screens"
+    new "## In-game screens"
+
+    # screens.rpy:91
+    old "## Say screen"
+    new "## Say screen"
+
+    # screens.rpy:93
+    old "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+    new "## The say screen is used to display dialogue to the player. It takes two parameters, who and what, which are the name of the speaking character and the text to be displayed, respectively. (The who parameter can be None if no name is given.)"
+
+    # screens.rpy:98
+    old "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+    new "## This screen must create a text displayable with id \"what\", as Ren'Py uses this to manage text display. It can also create displayables with id \"who\" and id \"window\" to apply style properties."
+
+    # screens.rpy:102
+    old "## https://www.renpy.org/doc/html/screen_special.html#say"
+    new "## https://www.renpy.org/doc/html/screen_special.html#say"
+
+    # screens.rpy:169
+    old "## Input screen"
+    new "## Input screen"
+
+    # screens.rpy:171
+    old "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+    new "## This screen is used to display renpy.input. The prompt parameter is used to pass a text prompt in."
+
+    # screens.rpy:174
+    old "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+    new "## This screen must create an input displayable with id \"input\" to accept the various input parameters."
+
+    # screens.rpy:177
+    old "## http://www.renpy.org/doc/html/screen_special.html#input"
+    new "## http://www.renpy.org/doc/html/screen_special.html#input"
+
+    # screens.rpy:205
+    old "## Choice screen"
+    new "## Choice screen"
+
+    # screens.rpy:207
+    old "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+    new "## This screen is used to display the in-game choices presented by the menu statement. The one parameter, items, is a list of objects, each with caption and action fields."
+
+    # screens.rpy:211
+    old "## http://www.renpy.org/doc/html/screen_special.html#choice"
+    new "## http://www.renpy.org/doc/html/screen_special.html#choice"
+
+    # screens.rpy:221
+    old "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+    new "## When this is true, menu captions will be spoken by the narrator. When false, menu captions will be displayed as empty buttons."
+
+    # screens.rpy:244
+    old "## Quick Menu screen"
+    new "## Quick Menu screen"
+
+    # screens.rpy:246
+    old "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+    new "## The quick menu is displayed in-game to provide easy access to the out-of-game menus."
+
+    # screens.rpy:261
+    old "Back"
+    new "Trở lại"
+
+    # screens.rpy:262
+    old "History"
+    new "History"
+
+    # screens.rpy:263
+    old "Skip"
+    new "Skip"
+
+    # screens.rpy:264
+    old "Auto"
+    new "Auto"
+
+    # screens.rpy:265
+    old "Save"
+    new "Save"
+
+    # screens.rpy:266
+    old "Q.Save"
+    new "Q.Save"
+
+    # screens.rpy:267
+    old "Q.Load"
+    new "Q.Load"
+
+    # screens.rpy:268
+    old "Prefs"
+    new "Prefs"
+
+    # screens.rpy:271
+    old "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+    new "## This code ensures that the quick_menu screen is displayed in-game, whenever the player has not explicitly hidden the interface."
+
+    # screens.rpy:291
+    old "## Navigation screen"
+    new "## Navigation screen"
+
+    # screens.rpy:293
+    old "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+    new "## This screen is included in the main and game menus, and provides navigation to other menus, and to start the game."
+
+    # screens.rpy:308
+    old "Start"
+    new "Start"
+
+    # screens.rpy:316
+    old "Load"
+    new "Load"
+
+    # screens.rpy:318
+    old "Preferences"
+    new "Preferences"
+
+    # screens.rpy:322
+    old "End Replay"
+    new "End Replay"
+
+    # screens.rpy:326
+    old "Main Menu"
+    new "Main Menu"
+
+    # screens.rpy:328
+    old "About"
+    new "Giới thiệu"
+
+    # screens.rpy:332
+    old "## Help isn't necessary or relevant to mobile devices."
+    new "## Help isn't necessary or relevant to mobile devices."
+
+    # screens.rpy:333
+    old "Help"
+    new "Help"
+
+    # screens.rpy:335
+    old "## The quit button is banned on iOS and unnecessary on Android."
+    new "## The quit button is banned on iOS and unnecessary on Android."
+
+    # screens.rpy:336
+    old "Quit"
+    new "Quit"
+
+    # screens.rpy:350
+    old "## Main Menu screen"
+    new "## Main Menu screen"
+
+    # screens.rpy:352
+    old "## Used to display the main menu when Ren'Py starts."
+    new "## Used to display the main menu when Ren'Py starts."
+
+    # screens.rpy:354
+    old "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+    new "## http://www.renpy.org/doc/html/screen_special.html#main-menu"
+
+    # screens.rpy:369
+    old "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+    new "## The use statement includes another screen inside this one. The actual contents of the main menu are in the navigation screen."
+
+    # screens.rpy:413
+    old "## Game Menu screen"
+    new "## Game Menu screen"
+
+    # screens.rpy:415
+    old "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+    new "## This lays out the basic common structure of a game menu screen. It's called with the screen title, and displays the background, title, and navigation."
+
+    # screens.rpy:418
+    old "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+    new "## The scroll parameter can be None, or one of \"viewport\" or \"vpgrid\". When this screen is intended to be used with one or more children, which are transcluded (placed) inside it."
+
+    # screens.rpy:476
+    old "Return"
+    new "Return"
+
+    # screens.rpy:539
+    old "## About screen"
+    new "## About screen"
+
+    # screens.rpy:541
+    old "## This screen gives credit and copyright information about the game and Ren'Py."
+    new "## This screen gives credit and copyright information about the game and Ren'Py."
+
+    # screens.rpy:544
+    old "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+    new "## There's nothing special about this screen, and hence it also serves as an example of how to make a custom screen."
+
+    # screens.rpy:551
+    old "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+    new "## This use statement includes the game_menu screen inside this one. The vbox child is then included inside the viewport inside the game_menu screen."
+
+    # screens.rpy:561
+    old "Version [config.version!t]\n"
+    new "Version [config.version!t]\n"
+
+    # screens.rpy:563
+    old "## gui.about is usually set in options.rpy."
+    new "## gui.about is usually set in options.rpy."
+
+    # screens.rpy:567
+    old "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+    new "Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]"
+
+    # screens.rpy:570
+    old "## This is redefined in options.rpy to add text to the about screen."
+    new "## This is redefined in options.rpy to add text to the about screen."
+
+    # screens.rpy:582
+    old "## Load and Save screens"
+    new "## Load and Save screens"
+
+    # screens.rpy:584
+    old "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+    new "## These screens are responsible for letting the player save the game and load it again. Since they share nearly everything in common, both are implemented in terms of a third screen, file_slots."
+
+    # screens.rpy:588
+    old "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+    new "## https://www.renpy.org/doc/html/screen_special.html#save https://www.renpy.org/doc/html/screen_special.html#load"
+
+    # screens.rpy:607
+    old "Page {}"
+    new "Page {}"
+
+    # screens.rpy:607
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # screens.rpy:607
+    old "Quick saves"
+    new "Quick saves"
+
+    # screens.rpy:613
+    old "## This ensures the input will get the enter event before any of the buttons do."
+    new "## This ensures the input will get the enter event before any of the buttons do."
+
+    # screens.rpy:629
+    old "## The grid of file slots."
+    new "## The grid of file slots."
+
+    # screens.rpy:649
+    old "{#file_time}%A, %B %d %Y, %H:%M"
+    new "{#file_time}%A, %B %d %Y, %H:%M"
+
+    # screens.rpy:649
+    old "empty slot"
+    new "empty slot"
+
+    # screens.rpy:657
+    old "## Buttons to access other pages."
+    new "## Buttons to access other pages."
+
+    # screens.rpy:666
+    old "<"
+    new "<"
+
+    # screens.rpy:668
+    old "{#auto_page}A"
+    new "{#auto_page}A"
+
+    # screens.rpy:670
+    old "{#quick_page}Q"
+    new "{#quick_page}Q"
+
+    # screens.rpy:676
+    old ">"
+    new ">"
+
+    # screens.rpy:711
+    old "## Preferences screen"
+    new "## Preferences screen"
+
+    # screens.rpy:713
+    old "## The preferences screen allows the player to configure the game to better suit themselves."
+    new "## The preferences screen allows the player to configure the game to better suit themselves."
+
+    # screens.rpy:716
+    old "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+    new "## https://www.renpy.org/doc/html/screen_special.html#preferences"
+
+    # screens.rpy:738
+    old "Display"
+    new "Hiển thị"
+
+    # screens.rpy:739
+    old "Window"
+    new "Cửa sổ"
+
+    # screens.rpy:740
+    old "Fullscreen"
+    new "Toàn màn hình"
+
+    # screens.rpy:744
+    old "Rollback Side"
+    new "Rollback Side"
+
+    # screens.rpy:745
+    old "Disable"
+    new "Tắt"
+
+    # screens.rpy:746
+    old "Left"
+    new "Left"
+
+    # screens.rpy:747
+    old "Right"
+    new "Right"
+
+    # screens.rpy:752
+    old "Unseen Text"
+    new "Unseen Text"
+
+    # screens.rpy:753
+    old "After Choices"
+    new "After Choices"
+
+    # screens.rpy:754
+    old "Transitions"
+    new "Transitions"
+
+    # screens.rpy:756
+    old "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+    new "## Additional vboxes of type \"radio_pref\" or \"check_pref\" can be added here, to add additional creator-defined preferences."
+
+    # screens.rpy:767
+    old "Text Speed"
+    new "Text Speed"
+
+    # screens.rpy:771
+    old "Auto-Forward Time"
+    new "Auto-Forward Time"
+
+    # screens.rpy:778
+    old "Music Volume"
+    new "Music Volume"
+
+    # screens.rpy:785
+    old "Sound Volume"
+    new "Âm lượng"
+
+    # screens.rpy:791
+    old "Test"
+    new "Test"
+
+    # screens.rpy:795
+    old "Voice Volume"
+    new "Voice Volume"
+
+    # screens.rpy:806
+    old "Mute All"
+    new "Mute All"
+
+    # screens.rpy:882
+    old "## History screen"
+    new "## History screen"
+
+    # screens.rpy:884
+    old "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+    new "## This is a screen that displays the dialogue history to the player. While there isn't anything special about this screen, it does have to access the dialogue history stored in _history_list."
+
+    # screens.rpy:888
+    old "## https://www.renpy.org/doc/html/history.html"
+    new "## https://www.renpy.org/doc/html/history.html"
+
+    # screens.rpy:894
+    old "## Avoid predicting this screen, as it can be very large."
+    new "## Avoid predicting this screen, as it can be very large."
+
+    # screens.rpy:905
+    old "## This lays things out properly if history_height is None."
+    new "## This lays things out properly if history_height is None."
+
+    # screens.rpy:914
+    old "## Take the color of the who text from the Character, if set."
+    new "## Take the color of the who text from the Character, if set."
+
+    # screens.rpy:921
+    old "The dialogue history is empty."
+    new "The dialogue history is empty."
+
+    # screens.rpy:965
+    old "## Help screen"
+    new "## Help screen"
+
+    # screens.rpy:967
+    old "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+    new "## A screen that gives information about key and mouse bindings. It uses other screens (keyboard_help, mouse_help, and gamepad_help) to display the actual help."
+
+    # screens.rpy:986
+    old "Keyboard"
+    new "Keyboard"
+
+    # screens.rpy:987
+    old "Mouse"
+    new "Mouse"
+
+    # screens.rpy:990
+    old "Gamepad"
+    new "Tay cầm"
+
+    # screens.rpy:1003
+    old "Enter"
+    new "Enter"
+
+    # screens.rpy:1004
+    old "Advances dialogue and activates the interface."
+    new "Advances dialogue and activates the interface."
+
+    # screens.rpy:1007
+    old "Space"
+    new "Space"
+
+    # screens.rpy:1008
+    old "Advances dialogue without selecting choices."
+    new "Advances dialogue without selecting choices."
+
+    # screens.rpy:1011
+    old "Arrow Keys"
+    new "Arrow Keys"
+
+    # screens.rpy:1012
+    old "Navigate the interface."
+    new "Navigate the interface."
+
+    # screens.rpy:1015
+    old "Escape"
+    new "Escape"
+
+    # screens.rpy:1016
+    old "Accesses the game menu."
+    new "Accesses the game menu."
+
+    # screens.rpy:1019
+    old "Ctrl"
+    new "Ctrl"
+
+    # screens.rpy:1020
+    old "Skips dialogue while held down."
+    new "Skips dialogue while held down."
+
+    # screens.rpy:1023
+    old "Tab"
+    new "Tab"
+
+    # screens.rpy:1024
+    old "Toggles dialogue skipping."
+    new "Toggles dialogue skipping."
+
+    # screens.rpy:1027
+    old "Page Up"
+    new "Page Up"
+
+    # screens.rpy:1028
+    old "Rolls back to earlier dialogue."
+    new "Rolls back to earlier dialogue."
+
+    # screens.rpy:1031
+    old "Page Down"
+    new "Page Down"
+
+    # screens.rpy:1032
+    old "Rolls forward to later dialogue."
+    new "Rolls forward to later dialogue."
+
+    # screens.rpy:1036
+    old "Hides the user interface."
+    new "Hides the user interface."
+
+    # screens.rpy:1040
+    old "Takes a screenshot."
+    new "Takes a screenshot."
+
+    # screens.rpy:1044
+    old "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+    new "Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}."
+
+    # screens.rpy:1050
+    old "Left Click"
+    new "Left Click"
+
+    # screens.rpy:1054
+    old "Middle Click"
+    new "Middle Click"
+
+    # screens.rpy:1058
+    old "Right Click"
+    new "Right Click"
+
+    # screens.rpy:1062
+    old "Mouse Wheel Up\nClick Rollback Side"
+    new "Mouse Wheel Up\nClick Rollback Side"
+
+    # screens.rpy:1066
+    old "Mouse Wheel Down"
+    new "Mouse Wheel Down"
+
+    # screens.rpy:1073
+    old "Right Trigger\nA/Bottom Button"
+    new "Right Trigger\nA/Bottom Button"
+
+    # screens.rpy:1074
+    old "Advance dialogue and activates the interface."
+    new "Advance dialogue and activates the interface."
+
+    # screens.rpy:1078
+    old "Roll back to earlier dialogue."
+    new "Roll back to earlier dialogue."
+
+    # screens.rpy:1081
+    old "Right Shoulder"
+    new "Right Shoulder"
+
+    # screens.rpy:1082
+    old "Roll forward to later dialogue."
+    new "Roll forward to later dialogue."
+
+    # screens.rpy:1085
+    old "D-Pad, Sticks"
+    new "D-Pad, Sticks"
+
+    # screens.rpy:1089
+    old "Start, Guide"
+    new "Start, Guide"
+
+    # screens.rpy:1090
+    old "Access the game menu."
+    new "Access the game menu."
+
+    # screens.rpy:1093
+    old "Y/Top Button"
+    new "Y/Top Button"
+
+    # screens.rpy:1096
+    old "Calibrate"
+    new "Tinh chỉnh"
+
+    # screens.rpy:1124
+    old "## Additional screens"
+    new "## Additional screens"
+
+    # screens.rpy:1128
+    old "## Confirm screen"
+    new "## Confirm screen"
+
+    # screens.rpy:1130
+    old "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+    new "## The confirm screen is called when Ren'Py wants to ask the player a yes or no question."
+
+    # screens.rpy:1133
+    old "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+    new "## http://www.renpy.org/doc/html/screen_special.html#confirm"
+
+    # screens.rpy:1137
+    old "## Ensure other screens do not get input while this screen is displayed."
+    new "## Ensure other screens do not get input while this screen is displayed."
+
+    # screens.rpy:1161
+    old "Yes"
+    new "Có"
+
+    # screens.rpy:1162
+    old "No"
+    new "Không"
+
+    # screens.rpy:1164
+    old "## Right-click and escape answer \"no\"."
+    new "## Right-click and escape answer \"no\"."
+
+    # screens.rpy:1191
+    old "## Skip indicator screen"
+    new "## Skip indicator screen"
+
+    # screens.rpy:1193
+    old "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+    new "## The skip_indicator screen is displayed to indicate that skipping is in progress."
+
+    # screens.rpy:1196
+    old "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+    new "## https://www.renpy.org/doc/html/screen_special.html#skip-indicator"
+
+    # screens.rpy:1208
+    old "Skipping"
+    new "Skipping"
+
+    # screens.rpy:1215
+    old "## This transform is used to blink the arrows one after another."
+    new "## This transform is used to blink the arrows one after another."
+
+    # screens.rpy:1247
+    old "## Notify screen"
+    new "## Notify screen"
+
+    # screens.rpy:1249
+    old "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+    new "## The notify screen is used to show the player a message. (For example, when the game is quicksaved or a screenshot has been taken.)"
+
+    # screens.rpy:1252
+    old "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+    new "## https://www.renpy.org/doc/html/screen_special.html#notify-screen"
+
+    # screens.rpy:1286
+    old "## NVL screen"
+    new "## NVL screen"
+
+    # screens.rpy:1288
+    old "## This screen is used for NVL-mode dialogue and menus."
+    new "## This screen is used for NVL-mode dialogue and menus."
+
+    # screens.rpy:1290
+    old "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+    new "## http://www.renpy.org/doc/html/screen_special.html#nvl"
+
+    # screens.rpy:1301
+    old "## Displays dialogue in either a vpgrid or the vbox."
+    new "## Displays dialogue in either a vpgrid or the vbox."
+
+    # screens.rpy:1314
+    old "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+    new "## Displays the menu, if given. The menu may be displayed incorrectly if config.narrator_menu is set to True, as it is above."
+
+    # screens.rpy:1344
+    old "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+    new "## This controls the maximum number of NVL-mode entries that can be displayed at once."
+
+    # screens.rpy:1406
+    old "## Mobile Variants"
+    new "## Mobile Variants"
+
+    # screens.rpy:1413
+    old "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+    new "## Since a mouse may not be present, we replace the quick menu with a version that uses fewer and bigger buttons that are easier to touch."
+
+    # screens.rpy:1429
+    old "Menu"
+    new "Menu"
+
diff --git a/launcher/game/tl/vietnamese/translations.rpy b/launcher/game/tl/vietnamese/translations.rpy
deleted file mode 100644
index 5079e0d..0000000
--- a/launcher/game/tl/vietnamese/translations.rpy
+++ /dev/null
@@ -1,59 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/translations.rpy:34
-    old "Create or Update Translations"
-    new "Tạo hoặc cập nhật bản dịch"
-
-    # game/translations.rpy:34
-    old "Please enter the name of the language for which you want to create or update translations."
-    new "Hãy nhập tên của ngôn ngữ mà bạn muốn tạo hoặc cập nhật các bản dịch."
-
-    # game/translations.rpy:39
-    old "The language name can not be the empty string."
-    new "Các tên ngôn ngữ không được là chuỗi rỗng."
-
-    # game/translations.rpy:50
-    old "Ren'Py is generating translations...."
-    new "Ren'Py đang tạo bản dịch ...."
-
-    # game/translations.rpy:54
-    old "Ren'Py has finished generating [language] translations."
-    new "Ren'Py đã hoàn tất việc tạo bản dịch [language]."
-
-    # game/translations.rpy:68
-    old "Extract Dialogue: [project.current.name!q]"
-    new "Trích xuất hội thoại: [project.current.name!q]"
-
-    # game/translations.rpy:84
-    old "Format:"
-    new "Định dạng:"
-
-    # game/translations.rpy:92
-    old "Tab-delimited Spreadsheet (dialogue.tab)"
-    new "Bảng phân loại hội thoại (dialogue.tab)"
-
-    # game/translations.rpy:93
-    old "Dialogue Text Only (dialogue.txt)"
-    new "Chỉ văn bản hội thoại (dialogue.txt)"
-
-    # game/translations.rpy:106
-    old "Strip text tags from the dialogue."
-    new "Bỏ tag của văn bản ra khỏi hội thoại."
-
-    # game/translations.rpy:107
-    old "Escape quotes and other special characters."
-    new "Bỏ trích dẫn và các kí tự đặc biệt."
-
-    # game/translations.rpy:108
-    old "Extract all translatable strings, not just dialogue."
-    new "Trích xuất mọi bản dịch, không chỉ mỗi phần hội thoại."
-
-    # game/translations.rpy:136
-    old "Ren'Py is extracting dialogue...."
-    new "Ren'Py đang trích xuất hội thoại...."
-
-    # game/translations.rpy:140
-    old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
-    new "Ren'Py đã hoàn thành việc trích xuất hội thoại. File hội thoại được trích xuất có thể được tìm thất tại dialogue.[persistent.dialogue_format] trong thư mục gốc của dự án."
-
diff --git a/launcher/game/tl/vietnamese/updater.rpy b/launcher/game/tl/vietnamese/updater.rpy
deleted file mode 100644
index cb93f2d..0000000
--- a/launcher/game/tl/vietnamese/updater.rpy
+++ /dev/null
@@ -1,79 +0,0 @@
-
-translate vietnamese strings:
-
-    # game/updater.rpy:75
-    old "Select Update Channel"
-    new "Chọn kênh cập nhật"
-
-    # game/updater.rpy:86
-    old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
-    new "Kênh cập nhật sẽ kiểm soát và tải về bản cập nhật của Ren'Py. Vui lòng chọn một kênh cập nhật:"
-
-    # game/updater.rpy:91
-    old "Release"
-    new "Bản phát hành"
-
-    # game/updater.rpy:97
-    old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
-    new "{b}Khuyến khích{/b} sử dụng phiên bản này cho tất cả các trò chơi mới được phát hành."
-
-    # game/updater.rpy:102
-    old "Prerelease"
-    new "Bản gần hoàn thiện"
-
-    # game/updater.rpy:108
-    old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
-    new "Phiên bản dùng để thử các tiện ích mới, công cụ mới nhất sẽ có trong phiên bản sau của Ren'Py, nhưng không nên sử dụng để phát hành game cuối cùng vì có thể còn lỗi."
-
-    # game/updater.rpy:114
-    old "Experimental"
-    new "Bản thử nghiệm"
-
-    # game/updater.rpy:120
-    old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
-    new "Phiên bản thí nghiệm của Ren'Py. Bạn không nên chọn kênh này nếu chưa hỏi nhà phát triển Ren'py."
-
-    # game/updater.rpy:126
-    old "Nightly"
-    new "Bản tăm tối"
-
-    # game/updater.rpy:132
-    old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
-    new "Rìa gần nhất tới sự phát triển của Ren'Py. Nó có thể chứa các tính năng mới nhất hoặc chẳng chạy được luôn."
-
-    # game/updater.rpy:156
-    old "Ren'Py is up to date."
-    new "Ren'Py đã cập nhật phiên bản mới nhất."
-
-    # game/updater.rpy:158
-    old "[u.version] is now available. Do you want to install it?"
-    new "Có thể cập nhật bản [u.version]. Bạn có muốn cài đặt nó không?"
-
-    # game/updater.rpy:160
-    old "Preparing to download the update."
-    new "Chuẩn bị tải về bản cập nhật."
-
-    # game/updater.rpy:162
-    old "Downloading the update."
-    new "Đang tải bản cập nhật."
-
-    # game/updater.rpy:164
-    old "Unpacking the update."
-    new "Đang bung bản cập nhật."
-
-    # game/updater.rpy:168
-    old "The update has been installed. Ren'Py will restart."
-    new "Bản cập nhật đã được cài đặt. Ren'Py sẽ tái khởi động."
-
-    # game/updater.rpy:170
-    old "The update has been installed."
-    new "Bản cập nhật đã cài xong."
-
-    # game/updater.rpy:172
-    old "The update was cancelled."
-    new "Bản cập nhật đã được hủy."
-
-    # game/updater.rpy:189
-    old "Ren'Py Update"
-    new "Cập nhật Ren'Py"
-
diff --git a/launcher/game/translations.rpy b/launcher/game/translations.rpy
index f2be417..5184ecf 100644
--- a/launcher/game/translations.rpy
+++ b/launcher/game/translations.rpy
@@ -175,6 +175,12 @@ screen translate:
                         textbutton _("Replace existing translations") style "l_checkbox" action ToggleField(persistent, "replace_translations")
                         textbutton _("Reverse languages") style "l_checkbox" action ToggleField(persistent, "reverse_languages")
 
+                        add HALF_SPACER
+
+                        textbutton _("Update Default Interface Translations"):
+                            action [ Jump("update_renpy_strings") ]
+
+
 
                 frame:
                     style "l_indent"
@@ -193,7 +199,7 @@ screen translate:
 
                         text _("The extract command allows you to extract string translations from an existing project into a temporary file.\n\nThe merge command merges extracted translations into another project.")
 
-    textbutton _("Back") action Jump("front_page") style "l_left_button"
+    textbutton _("Return") action Jump("front_page") style "l_left_button"
 
 
 label translate:
@@ -267,6 +273,28 @@ label merge_strings:
 
         interface.info(_("Ren'Py has finished merging [language] string translations."))
 
+    return
+
+label update_renpy_strings:
+
+    python:
+
+        language = _preferences.language
+
+        interface.processing(_("Updating default interface translations..."))
+
+        renpy.translation.extract.extract_strings_core(language, STRINGS_JSON)
+
+        args = [ "translate", "None", "--common-only", "--strings-only", "--max-priority", "399", "--no-todo" ]
+        project.current.launch(args, wait=True)
+
+        args = [ "merge_strings", "None",  STRINGS_JSON ]
+        project.current.launch(args, wait=True)
+
+    return
+
+
+
 screen extract_dialogue:
 
     frame:
diff --git a/module/ffmedia.c b/module/ffmedia.c
index 2c00b27..6536c76 100644
--- a/module/ffmedia.c
+++ b/module/ffmedia.c
@@ -11,6 +11,9 @@
 /* The output audio sample rate. */
 static int audio_sample_rate = 44100;
 
+static int audio_sample_increase = 44100 / 5;
+static int audio_target_samples = 44100 * 2;
+
 const int CHANNELS = 2;
 const int BPC = 2; // Bytes per channel.
 const int BPS = 4; // Bytes per sample.
@@ -183,7 +186,7 @@ typedef struct MediaState {
 
 	/* The size of the audio queue, and the target size in seconds. */
 	int audio_queue_samples;
-	int audio_queue_target_seconds;
+	int audio_queue_target_samples;
 
 	/* A frame used for decoding. */
 	AVFrame *audio_decode_frame;
@@ -509,7 +512,11 @@ static void decode_audio(MediaState *ms) {
 
 	double timebase = av_q2d(ms->ctx->streams[ms->audio_stream]->time_base);
 
-	while (ms->audio_queue_samples < ms->audio_queue_target_seconds * audio_sample_rate ) {
+	if (ms->audio_queue_target_samples < audio_target_samples) {
+	    ms->audio_queue_target_samples += audio_sample_increase;
+	}
+
+	while (ms->audio_queue_samples < ms->audio_queue_target_samples) {
 
 		read_packet(ms, &ms->audio_packet_queue, &pkt);
 
@@ -1013,8 +1020,10 @@ int media_read_audio(struct MediaState *ms, Uint8 *stream, int len) {
 
 	SDL_LockMutex(ms->lock);
 
-	while (!ms->ready) {
-		SDL_CondWait(ms->cond, ms->lock);
+    if(!ms->ready) {
+	    SDL_UnlockMutex(ms->lock);
+	    memset(stream, 0, len);
+	    return len;
 	}
 
 	int rv = 0;
@@ -1091,6 +1100,17 @@ int media_read_audio(struct MediaState *ms, Uint8 *stream, int len) {
 	return rv;
 }
 
+void media_wait_ready(struct MediaState *ms) {
+    SDL_LockMutex(ms->lock);
+
+    while (!ms->ready) {
+        SDL_CondWait(ms->cond, ms->lock);
+    }
+
+    SDL_UnlockMutex(ms->lock);
+}
+
+
 double media_duration(MediaState *ms) {
 	return ms->total_duration;
 }
@@ -1118,7 +1138,6 @@ MediaState *media_open(SDL_RWops *rwops, const char *filename) {
 	ms->lock = SDL_CreateMutex();
 
 	ms->audio_duration = -1;
-	ms->audio_queue_target_seconds = 2;
 
 	return ms;
 }
diff --git a/module/gen/renpy.angle.gldraw.c b/module/gen/renpy.angle.gldraw.c
index 31a7cbe..2a260d3 100644
--- a/module/gen/renpy.angle.gldraw.c
+++ b/module/gen/renpy.angle.gldraw.c
@@ -13782,7 +13782,7 @@ static int __pyx_f_5renpy_5angle_6gldraw_6GLDraw_draw_transformed(struct __pyx_o
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:             # <<<<<<<<<<<<<<
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  */
     __pyx_t_14 = ((__pyx_v_reverse->ydx != 0.0) != 0);
     if (!__pyx_t_14) {
@@ -13799,7 +13799,7 @@ static int __pyx_f_5renpy_5angle_6gldraw_6GLDraw_draw_transformed(struct __pyx_o
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)             # <<<<<<<<<<<<<<
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0
  */
       __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_what, __pyx_n_s_render_to_texture); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 984; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -13813,15 +13813,19 @@ static int __pyx_f_5renpy_5angle_6gldraw_6GLDraw_draw_transformed(struct __pyx_o
       /* "renpy/angle/gldraw.pyx":985
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)             # <<<<<<<<<<<<<<
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)             # <<<<<<<<<<<<<<
  *                 return 0
  * 
  */
-      __pyx_t_13 = ((struct __pyx_vtabstruct_5renpy_5angle_6gldraw_GLDraw *)__pyx_v_self->__pyx_vtab)->draw_transformed(__pyx_v_self, __pyx_v_tex, __pyx_v_clip, __pyx_v_xo, __pyx_v_yo, __pyx_v_alpha, __pyx_v_over, __pyx_v_reverse, __pyx_v_nearest, __pyx_v_subpixel, 0); if (unlikely(__pyx_t_13 == 1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 985; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_12 = PyNumber_Multiply(((PyObject *)__pyx_v_reverse), ((PyObject *)__pyx_v_self->draw_to_virt)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 985; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_12);
+      if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5renpy_7display_6render_Matrix2D))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 985; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_13 = ((struct __pyx_vtabstruct_5renpy_5angle_6gldraw_GLDraw *)__pyx_v_self->__pyx_vtab)->draw_transformed(__pyx_v_self, __pyx_v_tex, __pyx_v_clip, __pyx_v_xo, __pyx_v_yo, __pyx_v_alpha, __pyx_v_over, ((struct __pyx_obj_5renpy_7display_6render_Matrix2D *)__pyx_t_12), __pyx_v_nearest, __pyx_v_subpixel, 0); if (unlikely(__pyx_t_13 == 1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 985; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
 
       /* "renpy/angle/gldraw.pyx":986
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0             # <<<<<<<<<<<<<<
  * 
  *             minx, miny, maxx, maxy = clip
@@ -13834,7 +13838,7 @@ static int __pyx_f_5renpy_5angle_6gldraw_6GLDraw_draw_transformed(struct __pyx_o
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:             # <<<<<<<<<<<<<<
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  */
     }
 
@@ -22728,7 +22732,7 @@ static int __Pyx_InitCachedConstants(void) {
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)             # <<<<<<<<<<<<<<
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0
  */
   __pyx_tuple__30 = PyTuple_Pack(1, Py_True); if (unlikely(!__pyx_tuple__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 984; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
diff --git a/module/gen/renpy.display.render.c b/module/gen/renpy.display.render.c
index 1a3da8c..9505e4b 100644
--- a/module/gen/renpy.display.render.c
+++ b/module/gen/renpy.display.render.c
@@ -1101,7 +1101,7 @@ static char __pyx_k_DISSOLVE[] = "DISSOLVE";
 static char __pyx_k_IDENTITY[] = "IDENTITY";
 static char __pyx_k_Sentinel[] = "Sentinel";
 static char __pyx_k_absolute[] = "absolute";
-static char __pyx_k_clipping[] = "clipping";
+static char __pyx_k_clipping[] = "_clipping";
 static char __pyx_k_get_size[] = "get_size";
 static char __pyx_k_get_time[] = "get_time";
 static char __pyx_k_pgrender[] = "pgrender";
@@ -1130,6 +1130,7 @@ static char __pyx_k_start_pos[] = "start_pos";
 static char __pyx_k_threading[] = "threading";
 static char __pyx_k_transform[] = "transform";
 static char __pyx_k_Canvas_arc[] = "Canvas.arc";
+static char __pyx_k_clipping_2[] = "clipping";
 static char __pyx_k_depends_on[] = "depends_on";
 static char __pyx_k_frame_time[] = "frame_time";
 static char __pyx_k_invalidate[] = "invalidate";
@@ -1244,6 +1245,7 @@ static PyObject *__pyx_n_s_circle;
 static PyObject *__pyx_n_s_class;
 static PyObject *__pyx_n_s_clear;
 static PyObject *__pyx_n_s_clipping;
+static PyObject *__pyx_n_s_clipping_2;
 static PyObject *__pyx_n_s_closed;
 static PyObject *__pyx_n_s_cmaxx;
 static PyObject *__pyx_n_s_cmaxy;
@@ -3045,18 +3047,18 @@ static PyObject *__pyx_f_5renpy_7display_6render_render(PyObject *__pyx_v_d, PyO
  * 
  *     rv.render_of.append(d)             # <<<<<<<<<<<<<<
  * 
- *     if style.clipping:
+ *     if d._clipping:
  */
   __pyx_t_20 = __Pyx_PyObject_Append(__pyx_v_rv->render_of, __pyx_v_d); if (unlikely(__pyx_t_20 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/display/render.pyx":196
  *     rv.render_of.append(d)
  * 
- *     if style.clipping:             # <<<<<<<<<<<<<<
+ *     if d._clipping:             # <<<<<<<<<<<<<<
  *         rv = rv.subsurface((0, 0, rv.width, rv.height), focus=True)
  *         rv.render_of.append(d)
  */
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_style, __pyx_n_s_clipping); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_d, __pyx_n_s_clipping); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -3064,7 +3066,7 @@ static PyObject *__pyx_f_5renpy_7display_6render_render(PyObject *__pyx_v_d, PyO
 
     /* "renpy/display/render.pyx":197
  * 
- *     if style.clipping:
+ *     if d._clipping:
  *         rv = rv.subsurface((0, 0, rv.width, rv.height), focus=True)             # <<<<<<<<<<<<<<
  *         rv.render_of.append(d)
  * 
@@ -3107,7 +3109,7 @@ static PyObject *__pyx_f_5renpy_7display_6render_render(PyObject *__pyx_v_d, PyO
     __pyx_t_2 = 0;
 
     /* "renpy/display/render.pyx":198
- *     if style.clipping:
+ *     if d._clipping:
  *         rv = rv.subsurface((0, 0, rv.width, rv.height), focus=True)
  *         rv.render_of.append(d)             # <<<<<<<<<<<<<<
  * 
@@ -3118,7 +3120,7 @@ static PyObject *__pyx_f_5renpy_7display_6render_render(PyObject *__pyx_v_d, PyO
     /* "renpy/display/render.pyx":196
  *     rv.render_of.append(d)
  * 
- *     if style.clipping:             # <<<<<<<<<<<<<<
+ *     if d._clipping:             # <<<<<<<<<<<<<<
  *         rv = rv.subsurface((0, 0, rv.width, rv.height), focus=True)
  *         rv.render_of.append(d)
  */
@@ -11021,7 +11023,7 @@ static PyObject *__pyx_pf_5renpy_7display_6render_6Render_18subsurface(struct __
           __pyx_t_7 = __pyx_t_8;
           goto __pyx_L40_bool_binop_done;
         }
-        __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_child, __pyx_n_s_clipping); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+        __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_child, __pyx_n_s_clipping_2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
         __Pyx_GOTREF(__pyx_t_4);
         __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -27686,6 +27688,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_class, __pyx_k_class, sizeof(__pyx_k_class), 0, 0, 1, 1},
   {&__pyx_n_s_clear, __pyx_k_clear, sizeof(__pyx_k_clear), 0, 0, 1, 1},
   {&__pyx_n_s_clipping, __pyx_k_clipping, sizeof(__pyx_k_clipping), 0, 0, 1, 1},
+  {&__pyx_n_s_clipping_2, __pyx_k_clipping_2, sizeof(__pyx_k_clipping_2), 0, 0, 1, 1},
   {&__pyx_n_s_closed, __pyx_k_closed, sizeof(__pyx_k_closed), 0, 0, 1, 1},
   {&__pyx_n_s_cmaxx, __pyx_k_cmaxx, sizeof(__pyx_k_cmaxx), 0, 0, 1, 1},
   {&__pyx_n_s_cmaxy, __pyx_k_cmaxy, sizeof(__pyx_k_cmaxy), 0, 0, 1, 1},
diff --git a/module/gen/renpy.gl.gldraw.c b/module/gen/renpy.gl.gldraw.c
index 0b5a2d3..1233aff 100644
--- a/module/gen/renpy.gl.gldraw.c
+++ b/module/gen/renpy.gl.gldraw.c
@@ -14169,7 +14169,7 @@ static int __pyx_f_5renpy_2gl_6gldraw_6GLDraw_draw_transformed(struct __pyx_obj_
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:             # <<<<<<<<<<<<<<
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  */
     __pyx_t_14 = ((__pyx_v_reverse->ydx != 0.0) != 0);
     if (!__pyx_t_14) {
@@ -14186,7 +14186,7 @@ static int __pyx_f_5renpy_2gl_6gldraw_6GLDraw_draw_transformed(struct __pyx_obj_
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)             # <<<<<<<<<<<<<<
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0
  */
       __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_what, __pyx_n_s_render_to_texture); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -14200,15 +14200,19 @@ static int __pyx_f_5renpy_2gl_6gldraw_6GLDraw_draw_transformed(struct __pyx_obj_
       /* "renpy/gl/gldraw.pyx":982
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)             # <<<<<<<<<<<<<<
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)             # <<<<<<<<<<<<<<
  *                 return 0
  * 
  */
-      __pyx_t_13 = ((struct __pyx_vtabstruct_5renpy_2gl_6gldraw_GLDraw *)__pyx_v_self->__pyx_vtab)->draw_transformed(__pyx_v_self, __pyx_v_tex, __pyx_v_clip, __pyx_v_xo, __pyx_v_yo, __pyx_v_alpha, __pyx_v_over, __pyx_v_reverse, __pyx_v_nearest, __pyx_v_subpixel, 0); if (unlikely(__pyx_t_13 == 1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 982; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_12 = PyNumber_Multiply(((PyObject *)__pyx_v_reverse), ((PyObject *)__pyx_v_self->draw_to_virt)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 982; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_12);
+      if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5renpy_7display_6render_Matrix2D))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 982; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_13 = ((struct __pyx_vtabstruct_5renpy_2gl_6gldraw_GLDraw *)__pyx_v_self->__pyx_vtab)->draw_transformed(__pyx_v_self, __pyx_v_tex, __pyx_v_clip, __pyx_v_xo, __pyx_v_yo, __pyx_v_alpha, __pyx_v_over, ((struct __pyx_obj_5renpy_7display_6render_Matrix2D *)__pyx_t_12), __pyx_v_nearest, __pyx_v_subpixel, 0); if (unlikely(__pyx_t_13 == 1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 982; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
 
       /* "renpy/gl/gldraw.pyx":983
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0             # <<<<<<<<<<<<<<
  * 
  *             minx, miny, maxx, maxy = clip
@@ -14221,7 +14225,7 @@ static int __pyx_f_5renpy_2gl_6gldraw_6GLDraw_draw_transformed(struct __pyx_obj_
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:             # <<<<<<<<<<<<<<
  *                 tex = what.render_to_texture(True)
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  */
     }
 
@@ -23120,7 +23124,7 @@ static int __Pyx_InitCachedConstants(void) {
  *             # Non-aligned clipping uses RTT.
  *             if reverse.ydx != 0 or reverse.xdy != 0:
  *                 tex = what.render_to_texture(True)             # <<<<<<<<<<<<<<
- *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+ *                 self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
  *                 return 0
  */
   __pyx_tuple__30 = PyTuple_Pack(1, Py_True); if (unlikely(!__pyx_tuple__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
diff --git a/module/gen/renpy.style.c b/module/gen/renpy.style.c
index 77691b2..ea068ed 100644
--- a/module/gen/renpy.style.c
+++ b/module/gen/renpy.style.c
@@ -991,6 +991,7 @@ static char __pyx_k_copy[] = "copy";
 static char __pyx_k_game[] = "game";
 static char __pyx_k_help[] = "help";
 static char __pyx_k_idle[] = "idle_";
+static char __pyx_k_keys[] = "keys";
 static char __pyx_k_main[] = "__main__";
 static char __pyx_k_name[] = "name";
 static char __pyx_k_rest[] = "rest";
@@ -1011,6 +1012,7 @@ static char __pyx_k_start[] = "start";
 static char __pyx_k_style[] = "style";
 static char __pyx_k_value[] = "value";
 static char __pyx_k_backup[] = "backup";
+static char __pyx_k_config[] = "config";
 static char __pyx_k_create[] = "create";
 static char __pyx_k_exists[] = "exists";
 static char __pyx_k_format[] = "format";
@@ -1088,6 +1090,7 @@ static char __pyx_k_style_name_to_string[] = "style_name_to_string";
 static char __pyx_k_StyleManager___getattr[] = "StyleManager.__getattr__";
 static char __pyx_k_StyleManager___setattr[] = "StyleManager.__setattr__";
 static char __pyx_k_Style_r_does_not_exist[] = "Style %r does not exist.";
+static char __pyx_k_build_styles_callbacks[] = "build_styles_callbacks";
 static char __pyx_k_prefixed_all_properties[] = "prefixed_all_properties";
 static char __pyx_k_renpy_styledata_stylesets[] = "renpy.styledata.stylesets";
 static char __pyx_k_inspect_locals_inspect_one[] = "inspect.<locals>.inspect_one";
@@ -1123,7 +1126,9 @@ static PyObject *__pyx_kp_s_anonymous_style;
 static PyObject *__pyx_n_s_args;
 static PyObject *__pyx_n_s_backup;
 static PyObject *__pyx_n_s_build_styles;
+static PyObject *__pyx_n_s_build_styles_callbacks;
 static PyObject *__pyx_n_s_clear;
+static PyObject *__pyx_n_s_config;
 static PyObject *__pyx_n_s_context;
 static PyObject *__pyx_n_s_copy;
 static PyObject *__pyx_n_s_copy_properties;
@@ -1168,6 +1173,7 @@ static PyObject *__pyx_n_s_items;
 static PyObject *__pyx_n_s_iteritems;
 static PyObject *__pyx_n_s_k;
 static PyObject *__pyx_n_s_key;
+static PyObject *__pyx_n_s_keys;
 static PyObject *__pyx_n_s_main;
 static PyObject *__pyx_n_s_metaclass;
 static PyObject *__pyx_n_s_module;
@@ -1321,6 +1327,7 @@ static PyObject *__pyx_tuple__3;
 static PyObject *__pyx_tuple__4;
 static PyObject *__pyx_tuple__7;
 static PyObject *__pyx_slice__19;
+static PyObject *__pyx_slice__20;
 static PyObject *__pyx_tuple__11;
 static PyObject *__pyx_tuple__12;
 static PyObject *__pyx_tuple__13;
@@ -1328,37 +1335,37 @@ static PyObject *__pyx_tuple__14;
 static PyObject *__pyx_tuple__15;
 static PyObject *__pyx_tuple__16;
 static PyObject *__pyx_tuple__17;
-static PyObject *__pyx_tuple__20;
-static PyObject *__pyx_tuple__22;
-static PyObject *__pyx_tuple__24;
-static PyObject *__pyx_tuple__26;
-static PyObject *__pyx_tuple__28;
+static PyObject *__pyx_tuple__21;
+static PyObject *__pyx_tuple__23;
+static PyObject *__pyx_tuple__25;
+static PyObject *__pyx_tuple__27;
 static PyObject *__pyx_tuple__29;
-static PyObject *__pyx_tuple__31;
-static PyObject *__pyx_tuple__33;
-static PyObject *__pyx_tuple__35;
-static PyObject *__pyx_tuple__37;
-static PyObject *__pyx_tuple__40;
-static PyObject *__pyx_tuple__42;
-static PyObject *__pyx_tuple__44;
-static PyObject *__pyx_tuple__46;
-static PyObject *__pyx_tuple__48;
+static PyObject *__pyx_tuple__30;
+static PyObject *__pyx_tuple__32;
+static PyObject *__pyx_tuple__34;
+static PyObject *__pyx_tuple__36;
+static PyObject *__pyx_tuple__38;
+static PyObject *__pyx_tuple__41;
+static PyObject *__pyx_tuple__43;
+static PyObject *__pyx_tuple__45;
+static PyObject *__pyx_tuple__47;
+static PyObject *__pyx_tuple__49;
 static PyObject *__pyx_codeobj__18;
-static PyObject *__pyx_codeobj__21;
-static PyObject *__pyx_codeobj__23;
-static PyObject *__pyx_codeobj__25;
-static PyObject *__pyx_codeobj__27;
-static PyObject *__pyx_codeobj__30;
-static PyObject *__pyx_codeobj__32;
-static PyObject *__pyx_codeobj__34;
-static PyObject *__pyx_codeobj__36;
-static PyObject *__pyx_codeobj__38;
+static PyObject *__pyx_codeobj__22;
+static PyObject *__pyx_codeobj__24;
+static PyObject *__pyx_codeobj__26;
+static PyObject *__pyx_codeobj__28;
+static PyObject *__pyx_codeobj__31;
+static PyObject *__pyx_codeobj__33;
+static PyObject *__pyx_codeobj__35;
+static PyObject *__pyx_codeobj__37;
 static PyObject *__pyx_codeobj__39;
-static PyObject *__pyx_codeobj__41;
-static PyObject *__pyx_codeobj__43;
-static PyObject *__pyx_codeobj__45;
-static PyObject *__pyx_codeobj__47;
-static PyObject *__pyx_codeobj__49;
+static PyObject *__pyx_codeobj__40;
+static PyObject *__pyx_codeobj__42;
+static PyObject *__pyx_codeobj__44;
+static PyObject *__pyx_codeobj__46;
+static PyObject *__pyx_codeobj__48;
+static PyObject *__pyx_codeobj__50;
 
 /* "renpy/style.pyx":42
  * cdef dict property_functions = { }
@@ -11681,7 +11688,7 @@ static PyObject *__pyx_pf_5renpy_5style_18reset(CYTHON_UNUSED PyObject *__pyx_se
  * 
  *     styles.clear()             # <<<<<<<<<<<<<<
  * 
- * #     import gc
+ * 
  */
   __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 752; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
@@ -11731,7 +11738,7 @@ static PyObject *__pyx_pf_5renpy_5style_18reset(CYTHON_UNUSED PyObject *__pyx_se
   return __pyx_r;
 }
 
-/* "renpy/style.pyx":761
+/* "renpy/style.pyx":755
  * 
  * 
  * def build_styles():             # <<<<<<<<<<<<<<
@@ -11755,200 +11762,298 @@ static PyObject *__pyx_pw_5renpy_5style_21build_styles(PyObject *__pyx_self, CYT
 }
 
 static PyObject *__pyx_pf_5renpy_5style_20build_styles(CYTHON_UNUSED PyObject *__pyx_self) {
+  PyObject *__pyx_v_i = NULL;
   PyObject *__pyx_v_s = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  Py_ssize_t __pyx_t_4;
-  PyObject *(*__pyx_t_5)(PyObject *);
+  Py_ssize_t __pyx_t_3;
+  PyObject *(*__pyx_t_4)(PyObject *);
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("build_styles", 0);
 
-  /* "renpy/style.pyx":766
+  /* "renpy/style.pyx":759
+ *     Builds or rebuilds all styles.
  *     """
- * 
- *     for s in styles.values():             # <<<<<<<<<<<<<<
- *         unbuild_style(s)
+ *     for i in renpy.config.build_styles_callbacks:             # <<<<<<<<<<<<<<
+ *         i()
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_config); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_values); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = NULL;
-  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_2)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_2);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-    }
-  }
-  if (__pyx_t_2) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  } else {
-    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_build_styles_callbacks); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
-    __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
-    __pyx_t_5 = NULL;
+    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
+    __pyx_t_4 = NULL;
   } else {
-    __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   for (;;) {
-    if (likely(!__pyx_t_5)) {
-      if (likely(PyList_CheckExact(__pyx_t_3))) {
-        if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
+    if (likely(!__pyx_t_4)) {
+      if (likely(PyList_CheckExact(__pyx_t_2))) {
+        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_1); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
         #endif
       } else {
-        if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
+        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_1); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
         #endif
       }
     } else {
-      __pyx_t_1 = __pyx_t_5(__pyx_t_3);
+      __pyx_t_1 = __pyx_t_4(__pyx_t_2);
       if (unlikely(!__pyx_t_1)) {
         PyObject* exc_type = PyErr_Occurred();
         if (exc_type) {
           if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
       __Pyx_GOTREF(__pyx_t_1);
     }
-    __Pyx_XDECREF_SET(__pyx_v_s, __pyx_t_1);
+    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
     __pyx_t_1 = 0;
 
-    /* "renpy/style.pyx":767
- * 
- *     for s in styles.values():
- *         unbuild_style(s)             # <<<<<<<<<<<<<<
+    /* "renpy/style.pyx":760
+ *     """
+ *     for i in renpy.config.build_styles_callbacks:
+ *         i()             # <<<<<<<<<<<<<<
  * 
  *     for s in styles.values():
  */
-    if (!(likely(((__pyx_v_s) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_s, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 767; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __pyx_f_5renpy_5style_unbuild_style(((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_v_s), 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 767; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_INCREF(__pyx_v_i);
+    __pyx_t_5 = __pyx_v_i; __pyx_t_6 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_5))) {
+      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+      if (likely(__pyx_t_6)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_5, function);
+      }
+    }
+    if (__pyx_t_6) {
+      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    } else {
+      __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_5); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
     __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "renpy/style.pyx":766
+    /* "renpy/style.pyx":759
+ *     Builds or rebuilds all styles.
  *     """
- * 
- *     for s in styles.values():             # <<<<<<<<<<<<<<
- *         unbuild_style(s)
+ *     for i in renpy.config.build_styles_callbacks:             # <<<<<<<<<<<<<<
+ *         i()
  * 
  */
   }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":769
- *         unbuild_style(s)
+  /* "renpy/style.pyx":762
+ *         i()
  * 
  *     for s in styles.values():             # <<<<<<<<<<<<<<
- *         build_style(s)
+ *         unbuild_style(s)
  * 
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_values); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_values); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_t_1 = NULL;
-  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_5);
     if (likely(__pyx_t_1)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
       __Pyx_INCREF(__pyx_t_1);
       __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
     }
   }
   if (__pyx_t_1) {
-    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   } else {
-    __pyx_t_3 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_5); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
-    __pyx_t_2 = __pyx_t_3; __Pyx_INCREF(__pyx_t_2); __pyx_t_4 = 0;
-    __pyx_t_5 = NULL;
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
+    __pyx_t_5 = __pyx_t_2; __Pyx_INCREF(__pyx_t_5); __pyx_t_3 = 0;
+    __pyx_t_4 = NULL;
   } else {
-    __pyx_t_4 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_4 = Py_TYPE(__pyx_t_5)->tp_iternext; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  for (;;) {
+    if (likely(!__pyx_t_4)) {
+      if (likely(PyList_CheckExact(__pyx_t_5))) {
+        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_5)) break;
+        #if CYTHON_COMPILING_IN_CPYTHON
+        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        #else
+        __pyx_t_2 = PySequence_ITEM(__pyx_t_5, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_2);
+        #endif
+      } else {
+        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
+        #if CYTHON_COMPILING_IN_CPYTHON
+        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        #else
+        __pyx_t_2 = PySequence_ITEM(__pyx_t_5, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_2);
+        #endif
+      }
+    } else {
+      __pyx_t_2 = __pyx_t_4(__pyx_t_5);
+      if (unlikely(!__pyx_t_2)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_s, __pyx_t_2);
+    __pyx_t_2 = 0;
+
+    /* "renpy/style.pyx":763
+ * 
+ *     for s in styles.values():
+ *         unbuild_style(s)             # <<<<<<<<<<<<<<
+ * 
+ *     for s in styles.values():
+ */
+    if (!(likely(((__pyx_v_s) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_s, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_5renpy_5style_unbuild_style(((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_v_s), 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "renpy/style.pyx":762
+ *         i()
+ * 
+ *     for s in styles.values():             # <<<<<<<<<<<<<<
+ *         unbuild_style(s)
+ * 
+ */
   }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+
+  /* "renpy/style.pyx":765
+ *         unbuild_style(s)
+ * 
+ *     for s in styles.values():             # <<<<<<<<<<<<<<
+ *         build_style(s)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = NULL;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_1))) {
+    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
+    if (likely(__pyx_t_2)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_1, function);
+    }
+  }
+  if (__pyx_t_2) {
+    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  } else {
+    __pyx_t_5 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (likely(PyList_CheckExact(__pyx_t_5)) || PyTuple_CheckExact(__pyx_t_5)) {
+    __pyx_t_1 = __pyx_t_5; __Pyx_INCREF(__pyx_t_1); __pyx_t_3 = 0;
+    __pyx_t_4 = NULL;
+  } else {
+    __pyx_t_3 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   for (;;) {
-    if (likely(!__pyx_t_5)) {
-      if (likely(PyList_CheckExact(__pyx_t_2))) {
-        if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_2)) break;
+    if (likely(!__pyx_t_4)) {
+      if (likely(PyList_CheckExact(__pyx_t_1))) {
+        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_1)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_5);
         #endif
       } else {
-        if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_5);
         #endif
       }
     } else {
-      __pyx_t_3 = __pyx_t_5(__pyx_t_2);
-      if (unlikely(!__pyx_t_3)) {
+      __pyx_t_5 = __pyx_t_4(__pyx_t_1);
+      if (unlikely(!__pyx_t_5)) {
         PyObject* exc_type = PyErr_Occurred();
         if (exc_type) {
           if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 769; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
-      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_GOTREF(__pyx_t_5);
     }
-    __Pyx_XDECREF_SET(__pyx_v_s, __pyx_t_3);
-    __pyx_t_3 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_s, __pyx_t_5);
+    __pyx_t_5 = 0;
 
-    /* "renpy/style.pyx":770
+    /* "renpy/style.pyx":766
  * 
  *     for s in styles.values():
  *         build_style(s)             # <<<<<<<<<<<<<<
  * 
  * def rebuild(prepare_screens=True):
  */
-    if (!(likely(((__pyx_v_s) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_s, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 770; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_3 = __pyx_f_5renpy_5style_build_style(((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_v_s), 0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 770; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (!(likely(((__pyx_v_s) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_s, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __pyx_f_5renpy_5style_build_style(((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_v_s), 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 766; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-    /* "renpy/style.pyx":769
+    /* "renpy/style.pyx":765
  *         unbuild_style(s)
  * 
  *     for s in styles.values():             # <<<<<<<<<<<<<<
@@ -11956,9 +12061,9 @@ static PyObject *__pyx_pf_5renpy_5style_20build_styles(CYTHON_UNUSED PyObject *_
  * 
  */
   }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/style.pyx":761
+  /* "renpy/style.pyx":755
  * 
  * 
  * def build_styles():             # <<<<<<<<<<<<<<
@@ -11972,17 +12077,19 @@ static PyObject *__pyx_pf_5renpy_5style_20build_styles(CYTHON_UNUSED PyObject *_
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("renpy.style.build_styles", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_i);
   __Pyx_XDECREF(__pyx_v_s);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "renpy/style.pyx":772
+/* "renpy/style.pyx":768
  *         build_style(s)
  * 
  * def rebuild(prepare_screens=True):             # <<<<<<<<<<<<<<
@@ -12023,7 +12130,7 @@ static PyObject *__pyx_pw_5renpy_5style_23rebuild(PyObject *__pyx_self, PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rebuild") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rebuild") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -12036,7 +12143,7 @@ static PyObject *__pyx_pw_5renpy_5style_23rebuild(PyObject *__pyx_self, PyObject
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("rebuild", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("rebuild", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.style.rebuild", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -12062,14 +12169,14 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("rebuild", 0);
 
-  /* "renpy/style.pyx":777
+  /* "renpy/style.pyx":773
  *     """
  * 
  *     build_styles()             # <<<<<<<<<<<<<<
  * 
  *     renpy.display.screen.prepared = False
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_build_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_build_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 773; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
   if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -12082,46 +12189,46 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
     }
   }
   if (__pyx_t_3) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 773; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   } else {
-    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 773; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/style.pyx":779
+  /* "renpy/style.pyx":775
  *     build_styles()
  * 
  *     renpy.display.screen.prepared = False             # <<<<<<<<<<<<<<
  * 
  *     if not renpy.game.context().init_phase:
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 779; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 775; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_display); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 779; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_display); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 775; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_screen); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 779; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_screen); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 775; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_t_1, __pyx_n_s_prepared, Py_False) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 779; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_PyObject_SetAttrStr(__pyx_t_1, __pyx_n_s_prepared, Py_False) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 775; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/style.pyx":781
+  /* "renpy/style.pyx":777
  *     renpy.display.screen.prepared = False
  * 
  *     if not renpy.game.context().init_phase:             # <<<<<<<<<<<<<<
  *         renpy.display.screen.prepare_screens()
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_game); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_game); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_context); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_context); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __pyx_t_3 = NULL;
@@ -12135,37 +12242,37 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
     }
   }
   if (__pyx_t_3) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   } else {
-    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_init_phase); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_init_phase); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_t_5 = ((!__pyx_t_4) != 0);
   if (__pyx_t_5) {
 
-    /* "renpy/style.pyx":782
+    /* "renpy/style.pyx":778
  * 
  *     if not renpy.game.context().init_phase:
  *         renpy.display.screen.prepare_screens()             # <<<<<<<<<<<<<<
  * 
  *     renpy.exports.restart_interaction()
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_display); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_display); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_screen); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_screen); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_prepare_screens); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_prepare_screens); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_t_1 = NULL;
@@ -12179,16 +12286,16 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
       }
     }
     if (__pyx_t_1) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     } else {
-      __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "renpy/style.pyx":781
+    /* "renpy/style.pyx":777
  *     renpy.display.screen.prepared = False
  * 
  *     if not renpy.game.context().init_phase:             # <<<<<<<<<<<<<<
@@ -12197,19 +12304,19 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
  */
   }
 
-  /* "renpy/style.pyx":784
+  /* "renpy/style.pyx":780
  *         renpy.display.screen.prepare_screens()
  * 
  *     renpy.exports.restart_interaction()             # <<<<<<<<<<<<<<
  * 
  * def copy_properties(p):
  */
-  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_renpy); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_exports); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_exports); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_restart_interaction); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_restart_interaction); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_t_1 = NULL;
@@ -12223,16 +12330,16 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
     }
   }
   if (__pyx_t_1) {
-    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   } else {
-    __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":772
+  /* "renpy/style.pyx":768
  *         build_style(s)
  * 
  * def rebuild(prepare_screens=True):             # <<<<<<<<<<<<<<
@@ -12255,7 +12362,7 @@ static PyObject *__pyx_pf_5renpy_5style_22rebuild(CYTHON_UNUSED PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "renpy/style.pyx":786
+/* "renpy/style.pyx":782
  *     renpy.exports.restart_interaction()
  * 
  * def copy_properties(p):             # <<<<<<<<<<<<<<
@@ -12293,7 +12400,7 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("copy_properties", 0);
 
-  /* "renpy/style.pyx":791
+  /* "renpy/style.pyx":787
  *     """
  * 
  *     return [ dict(i) for i in p ]             # <<<<<<<<<<<<<<
@@ -12301,32 +12408,32 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
  * def backup():
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   if (likely(PyList_CheckExact(__pyx_v_p)) || PyTuple_CheckExact(__pyx_v_p)) {
     __pyx_t_2 = __pyx_v_p; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
     __pyx_t_4 = NULL;
   } else {
-    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   for (;;) {
     if (likely(!__pyx_t_4)) {
       if (likely(PyList_CheckExact(__pyx_t_2))) {
         if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         #endif
       } else {
         if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         #endif
       }
@@ -12336,7 +12443,7 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
         PyObject* exc_type = PyErr_Occurred();
         if (exc_type) {
           if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -12344,15 +12451,15 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
     }
     __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_INCREF(__pyx_v_i);
     __Pyx_GIVEREF(__pyx_v_i);
     PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_i);
-    __pyx_t_6 = __Pyx_PyObject_Call(((PyObject *)(&PyDict_Type)), __pyx_t_5, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_Call(((PyObject *)(&PyDict_Type)), __pyx_t_5, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_6))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_6))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   }
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -12360,7 +12467,7 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "renpy/style.pyx":786
+  /* "renpy/style.pyx":782
  *     renpy.exports.restart_interaction()
  * 
  * def copy_properties(p):             # <<<<<<<<<<<<<<
@@ -12383,7 +12490,7 @@ static PyObject *__pyx_pf_5renpy_5style_24copy_properties(CYTHON_UNUSED PyObject
   return __pyx_r;
 }
 
-/* "renpy/style.pyx":793
+/* "renpy/style.pyx":789
  *     return [ dict(i) for i in p ]
  * 
  * def backup():             # <<<<<<<<<<<<<<
@@ -12428,19 +12535,19 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("backup", 0);
 
-  /* "renpy/style.pyx":798
+  /* "renpy/style.pyx":794
  *     """
  * 
  *     rv = { }             # <<<<<<<<<<<<<<
  * 
  *     for k, v in styles.iteritems():
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_rv = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "renpy/style.pyx":800
+  /* "renpy/style.pyx":796
  *     rv = { }
  * 
  *     for k, v in styles.iteritems():             # <<<<<<<<<<<<<<
@@ -12448,13 +12555,13 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
  * 
  */
   __pyx_t_2 = 0;
-  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   if (unlikely(__pyx_t_5 == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "iteritems");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_6 = __Pyx_dict_iterator(__pyx_t_5, 0, __pyx_n_s_iteritems, (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = __Pyx_dict_iterator(__pyx_t_5, 0, __pyx_n_s_iteritems, (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_XDECREF(__pyx_t_1);
@@ -12463,7 +12570,7 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
   while (1) {
     __pyx_t_7 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_3, &__pyx_t_2, &__pyx_t_6, &__pyx_t_5, NULL, __pyx_t_4);
     if (unlikely(__pyx_t_7 == 0)) break;
-    if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_XDECREF_SET(__pyx_v_k, __pyx_t_6);
@@ -12471,18 +12578,18 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
     __Pyx_XDECREF_SET(__pyx_v_v, __pyx_t_5);
     __pyx_t_5 = 0;
 
-    /* "renpy/style.pyx":801
+    /* "renpy/style.pyx":797
  * 
  *     for k, v in styles.iteritems():
  *         rv[k] = (v.parent, copy_properties(v.properties))             # <<<<<<<<<<<<<<
  * 
  *     return rv
  */
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_parent); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_parent); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_8 = __Pyx_GetModuleGlobalName(__pyx_n_s_copy_properties); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_GetModuleGlobalName(__pyx_n_s_copy_properties); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_properties); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_properties); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __pyx_t_10 = NULL;
     if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_8))) {
@@ -12495,22 +12602,22 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
       }
     }
     if (!__pyx_t_10) {
-      __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_9); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_9); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
       __Pyx_GOTREF(__pyx_t_6);
     } else {
-      __pyx_t_11 = PyTuple_New(1+1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = PyTuple_New(1+1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_11);
       __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_10); __pyx_t_10 = NULL;
       __Pyx_GIVEREF(__pyx_t_9);
       PyTuple_SET_ITEM(__pyx_t_11, 0+1, __pyx_t_9);
       __pyx_t_9 = 0;
-      __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_11, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_11, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
     }
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
     __Pyx_GIVEREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5);
@@ -12518,12 +12625,12 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
     PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_6);
     __pyx_t_5 = 0;
     __pyx_t_6 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v_rv, __pyx_v_k, __pyx_t_8) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(PyDict_SetItem(__pyx_v_rv, __pyx_v_k, __pyx_t_8) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/style.pyx":803
+  /* "renpy/style.pyx":799
  *         rv[k] = (v.parent, copy_properties(v.properties))
  * 
  *     return rv             # <<<<<<<<<<<<<<
@@ -12535,7 +12642,7 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
   __pyx_r = __pyx_v_rv;
   goto __pyx_L0;
 
-  /* "renpy/style.pyx":793
+  /* "renpy/style.pyx":789
  *     return [ dict(i) for i in p ]
  * 
  * def backup():             # <<<<<<<<<<<<<<
@@ -12563,7 +12670,7 @@ static PyObject *__pyx_pf_5renpy_5style_26backup(CYTHON_UNUSED PyObject *__pyx_s
   return __pyx_r;
 }
 
-/* "renpy/style.pyx":805
+/* "renpy/style.pyx":801
  *     return rv
  * 
  * def restore(o):             # <<<<<<<<<<<<<<
@@ -12588,6 +12695,8 @@ static PyObject *__pyx_pw_5renpy_5style_29restore(PyObject *__pyx_self, PyObject
 
 static PyObject *__pyx_pf_5renpy_5style_28restore(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_o) {
   struct __pyx_obj_5renpy_5style_StyleCore *__pyx_v_s = 0;
+  PyObject *__pyx_v_keys = NULL;
+  PyObject *__pyx_v_i = NULL;
   PyObject *__pyx_v_k = NULL;
   PyObject *__pyx_v_v = NULL;
   PyObject *__pyx_v_parent = NULL;
@@ -12595,67 +12704,246 @@ static PyObject *__pyx_pf_5renpy_5style_28restore(CYTHON_UNUSED PyObject *__pyx_
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  Py_ssize_t __pyx_t_2;
-  Py_ssize_t __pyx_t_3;
-  int __pyx_t_4;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  int __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
-  PyObject *(*__pyx_t_9)(PyObject *);
-  PyObject *__pyx_t_10 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  Py_ssize_t __pyx_t_4;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  Py_ssize_t __pyx_t_7;
+  int __pyx_t_8;
+  int __pyx_t_9;
+  Py_ssize_t __pyx_t_10;
+  PyObject *(*__pyx_t_11)(PyObject *);
+  PyObject *__pyx_t_12 = NULL;
+  PyObject *(*__pyx_t_13)(PyObject *);
+  PyObject *__pyx_t_14 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("restore", 0);
 
-  /* "renpy/style.pyx":812
+  /* "renpy/style.pyx":808
  *     cdef StyleCore s
  * 
+ *     keys = list(styles.keys())             # <<<<<<<<<<<<<<
+ * 
+ *     for i in keys:
+ */
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_keys); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = NULL;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_2)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+    }
+  }
+  if (__pyx_t_2) {
+    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  } else {
+    __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_3 = PySequence_List(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_keys = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+  /* "renpy/style.pyx":810
+ *     keys = list(styles.keys())
+ * 
+ *     for i in keys:             # <<<<<<<<<<<<<<
+ *         if i not in o:
+ *             del styles[i]
+ */
+  __pyx_t_3 = __pyx_v_keys; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
+  for (;;) {
+    if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
+    #if CYTHON_COMPILING_IN_CPYTHON
+    __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_1); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    #else
+    __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    #endif
+    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
+    __pyx_t_1 = 0;
+
+    /* "renpy/style.pyx":811
+ * 
+ *     for i in keys:
+ *         if i not in o:             # <<<<<<<<<<<<<<
+ *             del styles[i]
+ * 
+ */
+    __pyx_t_5 = (__Pyx_PySequence_ContainsTF(__pyx_v_i, __pyx_v_o, Py_NE)); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 811; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = (__pyx_t_5 != 0);
+    if (__pyx_t_6) {
+
+      /* "renpy/style.pyx":812
+ *     for i in keys:
+ *         if i not in o:
+ *             del styles[i]             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+      __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_styles); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      if (PyObject_DelItem(__pyx_t_1, __pyx_v_i) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+      /* "renpy/style.pyx":811
+ * 
+ *     for i in keys:
+ *         if i not in o:             # <<<<<<<<<<<<<<
+ *             del styles[i]
+ * 
+ */
+    }
+
+    /* "renpy/style.pyx":810
+ *     keys = list(styles.keys())
+ * 
+ *     for i in keys:             # <<<<<<<<<<<<<<
+ *         if i not in o:
+ *             del styles[i]
+ */
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "renpy/style.pyx":815
+ * 
+ * 
  *     for k, v in o.iteritems():             # <<<<<<<<<<<<<<
- *         s = get_full_style(k)
  * 
+ *         s = get_or_create_style(k[0])
  */
-  __pyx_t_2 = 0;
+  __pyx_t_4 = 0;
   if (unlikely(__pyx_v_o == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "iteritems");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_5 = __Pyx_dict_iterator(__pyx_v_o, 0, __pyx_n_s_iteritems, (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_1);
-  __pyx_t_1 = __pyx_t_5;
-  __pyx_t_5 = 0;
+  __pyx_t_1 = __Pyx_dict_iterator(__pyx_v_o, 0, __pyx_n_s_iteritems, (&__pyx_t_7), (&__pyx_t_8)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __pyx_t_3 = __pyx_t_1;
+  __pyx_t_1 = 0;
   while (1) {
-    __pyx_t_7 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_3, &__pyx_t_2, &__pyx_t_5, &__pyx_t_6, NULL, __pyx_t_4);
-    if (unlikely(__pyx_t_7 == 0)) break;
-    if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_XDECREF_SET(__pyx_v_k, __pyx_t_5);
-    __pyx_t_5 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_v, __pyx_t_6);
-    __pyx_t_6 = 0;
+    __pyx_t_9 = __Pyx_dict_iter_next(__pyx_t_3, __pyx_t_7, &__pyx_t_4, &__pyx_t_1, &__pyx_t_2, NULL, __pyx_t_8);
+    if (unlikely(__pyx_t_9 == 0)) break;
+    if (unlikely(__pyx_t_9 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_XDECREF_SET(__pyx_v_k, __pyx_t_1);
+    __pyx_t_1 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_v, __pyx_t_2);
+    __pyx_t_2 = 0;
 
-    /* "renpy/style.pyx":813
- * 
+    /* "renpy/style.pyx":817
  *     for k, v in o.iteritems():
- *         s = get_full_style(k)             # <<<<<<<<<<<<<<
+ * 
+ *         s = get_or_create_style(k[0])             # <<<<<<<<<<<<<<
+ * 
+ *         for i in k[1:]:
+ */
+    __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_k, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = __pyx_f_5renpy_5style_get_or_create_style(__pyx_t_2, 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_XDECREF_SET(__pyx_v_s, ((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_t_1));
+    __pyx_t_1 = 0;
+
+    /* "renpy/style.pyx":819
+ *         s = get_or_create_style(k[0])
+ * 
+ *         for i in k[1:]:             # <<<<<<<<<<<<<<
+ *             s = s[i]
+ * 
+ */
+    __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_k, 1, 0, NULL, NULL, &__pyx_slice__20, 1, 0, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
+      __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_10 = 0;
+      __pyx_t_11 = NULL;
+    } else {
+      __pyx_t_10 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_11 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    for (;;) {
+      if (likely(!__pyx_t_11)) {
+        if (likely(PyList_CheckExact(__pyx_t_2))) {
+          if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_2)) break;
+          #if CYTHON_COMPILING_IN_CPYTHON
+          __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_10); __Pyx_INCREF(__pyx_t_1); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          #else
+          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __Pyx_GOTREF(__pyx_t_1);
+          #endif
+        } else {
+          if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+          #if CYTHON_COMPILING_IN_CPYTHON
+          __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_10); __Pyx_INCREF(__pyx_t_1); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          #else
+          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __Pyx_GOTREF(__pyx_t_1);
+          #endif
+        }
+      } else {
+        __pyx_t_1 = __pyx_t_11(__pyx_t_2);
+        if (unlikely(!__pyx_t_1)) {
+          PyObject* exc_type = PyErr_Occurred();
+          if (exc_type) {
+            if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+            else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          }
+          break;
+        }
+        __Pyx_GOTREF(__pyx_t_1);
+      }
+      __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
+      __pyx_t_1 = 0;
+
+      /* "renpy/style.pyx":820
+ * 
+ *         for i in k[1:]:
+ *             s = s[i]             # <<<<<<<<<<<<<<
  * 
  *         parent, properties = v
  */
-    __pyx_t_6 = __pyx_f_5renpy_5style_get_full_style(__pyx_v_k, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_6);
-    if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_XDECREF_SET(__pyx_v_s, ((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_t_6));
-    __pyx_t_6 = 0;
+      __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_s), __pyx_v_i); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5renpy_5style_StyleCore))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF_SET(__pyx_v_s, ((struct __pyx_obj_5renpy_5style_StyleCore *)__pyx_t_1));
+      __pyx_t_1 = 0;
 
-    /* "renpy/style.pyx":815
- *         s = get_full_style(k)
+      /* "renpy/style.pyx":819
+ *         s = get_or_create_style(k[0])
+ * 
+ *         for i in k[1:]:             # <<<<<<<<<<<<<<
+ *             s = s[i]
+ * 
+ */
+    }
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "renpy/style.pyx":822
+ *             s = s[i]
  * 
  *         parent, properties = v             # <<<<<<<<<<<<<<
  * 
- *         s.set_parent(parent)
+ *         s.clear()
  */
     if ((likely(PyTuple_CheckExact(__pyx_v_v))) || (PyList_CheckExact(__pyx_v_v))) {
       PyObject* sequence = __pyx_v_v;
@@ -12667,128 +12955,157 @@ static PyObject *__pyx_pf_5renpy_5style_28restore(CYTHON_UNUSED PyObject *__pyx_
       if (unlikely(size != 2)) {
         if (size > 2) __Pyx_RaiseTooManyValuesError(2);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); 
       } else {
-        __pyx_t_6 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_5 = PyList_GET_ITEM(sequence, 1); 
+        __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_1 = PyList_GET_ITEM(sequence, 1); 
       }
-      __Pyx_INCREF(__pyx_t_6);
-      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_1);
       #else
-      __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_1 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
       #endif
     } else {
       Py_ssize_t index = -1;
-      __pyx_t_8 = PyObject_GetIter(__pyx_v_v); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
-      index = 0; __pyx_t_6 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_6)) goto __pyx_L5_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_6);
-      index = 1; __pyx_t_5 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_5)) goto __pyx_L5_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_5);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_9 = NULL;
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      goto __pyx_L6_unpacking_done;
-      __pyx_L5_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_9 = NULL;
+      __pyx_t_12 = PyObject_GetIter(__pyx_v_v); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_12);
+      __pyx_t_13 = Py_TYPE(__pyx_t_12)->tp_iternext;
+      index = 0; __pyx_t_2 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_2)) goto __pyx_L10_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_2);
+      index = 1; __pyx_t_1 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_1)) goto __pyx_L10_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_1);
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_13(__pyx_t_12), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_13 = NULL;
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+      goto __pyx_L11_unpacking_done;
+      __pyx_L10_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+      __pyx_t_13 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_L6_unpacking_done:;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_L11_unpacking_done:;
     }
-    __Pyx_XDECREF_SET(__pyx_v_parent, __pyx_t_6);
-    __pyx_t_6 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_properties, __pyx_t_5);
-    __pyx_t_5 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_parent, __pyx_t_2);
+    __pyx_t_2 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_properties, __pyx_t_1);
+    __pyx_t_1 = 0;
 
-    /* "renpy/style.pyx":817
+    /* "renpy/style.pyx":824
  *         parent, properties = v
  * 
+ *         s.clear()             # <<<<<<<<<<<<<<
+ *         s.set_parent(parent)
+ *         s.properties = copy_properties(properties)
+ */
+    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_s), __pyx_n_s_clear); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_12 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_12)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_12);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    if (__pyx_t_12) {
+      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+    } else {
+      __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+    /* "renpy/style.pyx":825
+ * 
+ *         s.clear()
  *         s.set_parent(parent)             # <<<<<<<<<<<<<<
  *         s.properties = copy_properties(properties)
  * 
  */
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_s), __pyx_n_s_set_parent); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_8 = NULL;
-    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_6))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
-        __Pyx_INCREF(__pyx_t_8);
+    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_s), __pyx_n_s_set_parent); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_12 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_12)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_12);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_6, function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
-    if (!__pyx_t_8) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_parent); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_5);
+    if (!__pyx_t_12) {
+      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_parent); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
     } else {
-      __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_10);
-      __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL;
+      __pyx_t_14 = PyTuple_New(1+1); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_14);
+      __Pyx_GIVEREF(__pyx_t_12); PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_12); __pyx_t_12 = NULL;
       __Pyx_INCREF(__pyx_v_parent);
       __Pyx_GIVEREF(__pyx_v_parent);
-      PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_v_parent);
-      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_10, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      PyTuple_SET_ITEM(__pyx_t_14, 0+1, __pyx_v_parent);
+      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_14, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
     }
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "renpy/style.pyx":818
- * 
+    /* "renpy/style.pyx":826
+ *         s.clear()
  *         s.set_parent(parent)
  *         s.properties = copy_properties(properties)             # <<<<<<<<<<<<<<
  * 
  */
-    __pyx_t_6 = __Pyx_GetModuleGlobalName(__pyx_n_s_copy_properties); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_10 = NULL;
-    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_6))) {
-      __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_6);
-      if (likely(__pyx_t_10)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
-        __Pyx_INCREF(__pyx_t_10);
+    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_copy_properties); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_14 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_14)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_14);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_6, function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
-    if (!__pyx_t_10) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_properties); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_5);
+    if (!__pyx_t_14) {
+      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_properties); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
     } else {
-      __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_10); __pyx_t_10 = NULL;
+      __pyx_t_12 = PyTuple_New(1+1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_12);
+      __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_14); __pyx_t_14 = NULL;
       __Pyx_INCREF(__pyx_v_properties);
       __Pyx_GIVEREF(__pyx_v_properties);
-      PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_properties);
-      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      PyTuple_SET_ITEM(__pyx_t_12, 0+1, __pyx_v_properties);
+      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_12, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
     }
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    if (!(likely(PyList_CheckExact(__pyx_t_5))||((__pyx_t_5) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_5)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    if (!(likely(PyList_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_1)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GIVEREF(__pyx_t_1);
     __Pyx_GOTREF(__pyx_v_s->properties);
     __Pyx_DECREF(__pyx_v_s->properties);
-    __pyx_v_s->properties = ((PyObject*)__pyx_t_5);
-    __pyx_t_5 = 0;
+    __pyx_v_s->properties = ((PyObject*)__pyx_t_1);
+    __pyx_t_1 = 0;
   }
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/style.pyx":805
+  /* "renpy/style.pyx":801
  *     return rv
  * 
  * def restore(o):             # <<<<<<<<<<<<<<
@@ -12801,14 +13118,16 @@ static PyObject *__pyx_pf_5renpy_5style_28restore(CYTHON_UNUSED PyObject *__pyx_
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_10);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_12);
+  __Pyx_XDECREF(__pyx_t_14);
   __Pyx_AddTraceback("renpy.style.restore", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XDECREF((PyObject *)__pyx_v_s);
+  __Pyx_XDECREF(__pyx_v_keys);
+  __Pyx_XDECREF(__pyx_v_i);
   __Pyx_XDECREF(__pyx_v_k);
   __Pyx_XDECREF(__pyx_v_v);
   __Pyx_XDECREF(__pyx_v_parent);
@@ -13667,7 +13986,9 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_args, __pyx_k_args, sizeof(__pyx_k_args), 0, 0, 1, 1},
   {&__pyx_n_s_backup, __pyx_k_backup, sizeof(__pyx_k_backup), 0, 0, 1, 1},
   {&__pyx_n_s_build_styles, __pyx_k_build_styles, sizeof(__pyx_k_build_styles), 0, 0, 1, 1},
+  {&__pyx_n_s_build_styles_callbacks, __pyx_k_build_styles_callbacks, sizeof(__pyx_k_build_styles_callbacks), 0, 0, 1, 1},
   {&__pyx_n_s_clear, __pyx_k_clear, sizeof(__pyx_k_clear), 0, 0, 1, 1},
+  {&__pyx_n_s_config, __pyx_k_config, sizeof(__pyx_k_config), 0, 0, 1, 1},
   {&__pyx_n_s_context, __pyx_k_context, sizeof(__pyx_k_context), 0, 0, 1, 1},
   {&__pyx_n_s_copy, __pyx_k_copy, sizeof(__pyx_k_copy), 0, 0, 1, 1},
   {&__pyx_n_s_copy_properties, __pyx_k_copy_properties, sizeof(__pyx_k_copy_properties), 0, 0, 1, 1},
@@ -13712,6 +14033,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_iteritems, __pyx_k_iteritems, sizeof(__pyx_k_iteritems), 0, 0, 1, 1},
   {&__pyx_n_s_k, __pyx_k_k, sizeof(__pyx_k_k), 0, 0, 1, 1},
   {&__pyx_n_s_key, __pyx_k_key, sizeof(__pyx_k_key), 0, 0, 1, 1},
+  {&__pyx_n_s_keys, __pyx_k_keys, sizeof(__pyx_k_keys), 0, 0, 1, 1},
   {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
   {&__pyx_n_s_metaclass, __pyx_k_metaclass, sizeof(__pyx_k_metaclass), 0, 0, 1, 1},
   {&__pyx_n_s_module, __pyx_k_module, sizeof(__pyx_k_module), 0, 0, 1, 1},
@@ -13956,6 +14278,17 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GOTREF(__pyx_slice__19);
   __Pyx_GIVEREF(__pyx_slice__19);
 
+  /* "renpy/style.pyx":819
+ *         s = get_or_create_style(k[0])
+ * 
+ *         for i in k[1:]:             # <<<<<<<<<<<<<<
+ *             s = s[i]
+ * 
+ */
+  __pyx_slice__20 = PySlice_New(__pyx_int_1, Py_None, Py_None); if (unlikely(!__pyx_slice__20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_slice__20);
+  __Pyx_GIVEREF(__pyx_slice__20);
+
   /* "renpy/style.pyx":157
  * 
  * 
@@ -13963,10 +14296,10 @@ static int __Pyx_InitCachedConstants(void) {
  *     """
  *     If style exists, returns `style` + "_text". Otherwise, returns `default`.
  */
-  __pyx_tuple__20 = PyTuple_Pack(6, __pyx_n_s_style, __pyx_n_s_default, __pyx_n_s_start, __pyx_n_s_rest, __pyx_n_s_rv, __pyx_n_s_i); if (unlikely(!__pyx_tuple__20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__20);
-  __Pyx_GIVEREF(__pyx_tuple__20);
-  __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_get_text_style, 157, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__21 = PyTuple_Pack(6, __pyx_n_s_style, __pyx_n_s_default, __pyx_n_s_start, __pyx_n_s_rest, __pyx_n_s_rv, __pyx_n_s_i); if (unlikely(!__pyx_tuple__21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__21);
+  __Pyx_GIVEREF(__pyx_tuple__21);
+  __pyx_codeobj__22 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__21, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_get_text_style, 157, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":184
  *     """
@@ -13975,10 +14308,10 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *         if not isinstance(value, StyleCore):
  */
-  __pyx_tuple__22 = PyTuple_Pack(4, __pyx_n_s_self, __pyx_n_s_name, __pyx_n_s_value, __pyx_n_s_style); if (unlikely(!__pyx_tuple__22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__22);
-  __Pyx_GIVEREF(__pyx_tuple__22);
-  __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(3, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_setattr, 184, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__23 = PyTuple_Pack(4, __pyx_n_s_self, __pyx_n_s_name, __pyx_n_s_value, __pyx_n_s_style); if (unlikely(!__pyx_tuple__23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__23);
+  __Pyx_GIVEREF(__pyx_tuple__23);
+  __pyx_codeobj__24 = (PyObject*)__Pyx_PyCode_New(3, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__23, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_setattr, 184, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__24)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":200
  *     __setitem__ = __setattr__
@@ -13987,10 +14320,10 @@ static int __Pyx_InitCachedConstants(void) {
  *         return get_style(name)
  * 
  */
-  __pyx_tuple__24 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__24)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__24);
-  __Pyx_GIVEREF(__pyx_tuple__24);
-  __pyx_codeobj__25 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__24, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_getattr, 200, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__25 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__25);
+  __Pyx_GIVEREF(__pyx_tuple__25);
+  __pyx_codeobj__26 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_getattr, 200, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":205
  *     __getitem__ = __getattr__
@@ -13999,13 +14332,13 @@ static int __Pyx_InitCachedConstants(void) {
  *         """
  *         Deprecated way of creating styles.
  */
-  __pyx_tuple__26 = PyTuple_Pack(5, __pyx_n_s_self, __pyx_n_s_name, __pyx_n_s_parent, __pyx_n_s_description, __pyx_n_s_s); if (unlikely(!__pyx_tuple__26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__26);
-  __Pyx_GIVEREF(__pyx_tuple__26);
-  __pyx_codeobj__27 = (PyObject*)__Pyx_PyCode_New(4, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_create, 205, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__27)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_tuple__28 = PyTuple_Pack(1, ((PyObject *)Py_None)); if (unlikely(!__pyx_tuple__28)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__28);
-  __Pyx_GIVEREF(__pyx_tuple__28);
+  __pyx_tuple__27 = PyTuple_Pack(5, __pyx_n_s_self, __pyx_n_s_name, __pyx_n_s_parent, __pyx_n_s_description, __pyx_n_s_s); if (unlikely(!__pyx_tuple__27)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__27);
+  __Pyx_GIVEREF(__pyx_tuple__27);
+  __pyx_codeobj__28 = (PyObject*)__Pyx_PyCode_New(4, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__27, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_create, 205, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__28)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__29 = PyTuple_Pack(1, ((PyObject *)Py_None)); if (unlikely(!__pyx_tuple__29)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__29);
+  __Pyx_GIVEREF(__pyx_tuple__29);
 
   /* "renpy/style.pyx":213
  *         self[name] = s
@@ -14014,10 +14347,10 @@ static int __Pyx_InitCachedConstants(void) {
  *         renpy.style.rebuild()
  * 
  */
-  __pyx_tuple__29 = PyTuple_Pack(1, __pyx_n_s_self); if (unlikely(!__pyx_tuple__29)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__29);
-  __Pyx_GIVEREF(__pyx_tuple__29);
-  __pyx_codeobj__30 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__29, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_rebuild, 213, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__30 = PyTuple_Pack(1, __pyx_n_s_self); if (unlikely(!__pyx_tuple__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__30);
+  __Pyx_GIVEREF(__pyx_tuple__30);
+  __pyx_codeobj__31 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__30, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_rebuild, 213, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__31)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":216
  *         renpy.style.rebuild()
@@ -14026,10 +14359,10 @@ static int __Pyx_InitCachedConstants(void) {
  *         """
  *         Returns `true` if name is a style.
  */
-  __pyx_tuple__31 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__31)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__31);
-  __Pyx_GIVEREF(__pyx_tuple__31);
-  __pyx_codeobj__32 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__31, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_exists, 216, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__32)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__32 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__32)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__32);
+  __Pyx_GIVEREF(__pyx_tuple__32);
+  __pyx_codeobj__33 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__32, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_exists, 216, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__33)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":223
  *         return (name in styles) or ((name,) in styles)
@@ -14038,10 +14371,10 @@ static int __Pyx_InitCachedConstants(void) {
  *         """
  *         Gets a style, which may be a name or a tuple.
  */
-  __pyx_tuple__33 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__33)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__33);
-  __Pyx_GIVEREF(__pyx_tuple__33);
-  __pyx_codeobj__34 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__33, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_get, 223, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__34)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__34 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_name); if (unlikely(!__pyx_tuple__34)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__34);
+  __Pyx_GIVEREF(__pyx_tuple__34);
+  __pyx_codeobj__35 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__34, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_get, 223, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__35)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":238
  * ################################################################################
@@ -14050,10 +14383,10 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *     if name is None:
  */
-  __pyx_tuple__35 = PyTuple_Pack(3, __pyx_n_s_name, __pyx_n_s_rv, __pyx_n_s_i); if (unlikely(!__pyx_tuple__35)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__35);
-  __Pyx_GIVEREF(__pyx_tuple__35);
-  __pyx_codeobj__36 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__35, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_style_name_to_string, 238, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__36)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__36 = PyTuple_Pack(3, __pyx_n_s_name, __pyx_n_s_rv, __pyx_n_s_i); if (unlikely(!__pyx_tuple__36)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__36);
+  __Pyx_GIVEREF(__pyx_tuple__36);
+  __pyx_codeobj__37 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__36, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_style_name_to_string, 238, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__37)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":726
  * affects = None
@@ -14062,10 +14395,10 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *     global priority
  */
-  __pyx_tuple__37 = PyTuple_Pack(6, __pyx_n_s_prefixname, __pyx_n_s_pri, __pyx_n_s_propname, __pyx_n_s_proplist, __pyx_n_s_a, __pyx_n_s_i); if (unlikely(!__pyx_tuple__37)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 726; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__37);
-  __Pyx_GIVEREF(__pyx_tuple__37);
-  __pyx_codeobj__38 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__37, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_init_inspect, 726, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__38)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 726; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__38 = PyTuple_Pack(6, __pyx_n_s_prefixname, __pyx_n_s_pri, __pyx_n_s_propname, __pyx_n_s_proplist, __pyx_n_s_a, __pyx_n_s_i); if (unlikely(!__pyx_tuple__38)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 726; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__38);
+  __Pyx_GIVEREF(__pyx_tuple__38);
+  __pyx_codeobj__39 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__38, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_init_inspect, 726, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__39)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 726; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "renpy/style.pyx":747
  * ################################################################################
@@ -14074,67 +14407,67 @@ static int __Pyx_InitCachedConstants(void) {
  *     """
  *     Reset the style system.
  */
-  __pyx_codeobj__39 = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_reset, 747, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__39)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 747; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_codeobj__40 = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_reset, 747, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__40)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 747; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/style.pyx":761
+  /* "renpy/style.pyx":755
  * 
  * 
  * def build_styles():             # <<<<<<<<<<<<<<
  *     """
  *     Builds or rebuilds all styles.
  */
-  __pyx_tuple__40 = PyTuple_Pack(1, __pyx_n_s_s); if (unlikely(!__pyx_tuple__40)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 761; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__40);
-  __Pyx_GIVEREF(__pyx_tuple__40);
-  __pyx_codeobj__41 = (PyObject*)__Pyx_PyCode_New(0, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__40, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_build_styles, 761, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__41)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 761; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__41 = PyTuple_Pack(2, __pyx_n_s_i, __pyx_n_s_s); if (unlikely(!__pyx_tuple__41)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 755; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__41);
+  __Pyx_GIVEREF(__pyx_tuple__41);
+  __pyx_codeobj__42 = (PyObject*)__Pyx_PyCode_New(0, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__41, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_build_styles, 755, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__42)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 755; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/style.pyx":772
+  /* "renpy/style.pyx":768
  *         build_style(s)
  * 
  * def rebuild(prepare_screens=True):             # <<<<<<<<<<<<<<
  *     """
  *     Rebuilds all styles.
  */
-  __pyx_tuple__42 = PyTuple_Pack(1, __pyx_n_s_prepare_screens); if (unlikely(!__pyx_tuple__42)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__42);
-  __Pyx_GIVEREF(__pyx_tuple__42);
-  __pyx_codeobj__43 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__42, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_rebuild, 772, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__43)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__43 = PyTuple_Pack(1, __pyx_n_s_prepare_screens); if (unlikely(!__pyx_tuple__43)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__43);
+  __Pyx_GIVEREF(__pyx_tuple__43);
+  __pyx_codeobj__44 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__43, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_rebuild, 768, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__44)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/style.pyx":786
+  /* "renpy/style.pyx":782
  *     renpy.exports.restart_interaction()
  * 
  * def copy_properties(p):             # <<<<<<<<<<<<<<
  *     """
  *     Makes a copy of the properties dict p.
  */
-  __pyx_tuple__44 = PyTuple_Pack(2, __pyx_n_s_p, __pyx_n_s_i); if (unlikely(!__pyx_tuple__44)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__44);
-  __Pyx_GIVEREF(__pyx_tuple__44);
-  __pyx_codeobj__45 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__44, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_copy_properties, 786, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__45)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__45 = PyTuple_Pack(2, __pyx_n_s_p, __pyx_n_s_i); if (unlikely(!__pyx_tuple__45)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__45);
+  __Pyx_GIVEREF(__pyx_tuple__45);
+  __pyx_codeobj__46 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__45, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_copy_properties, 782, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__46)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/style.pyx":793
+  /* "renpy/style.pyx":789
  *     return [ dict(i) for i in p ]
  * 
  * def backup():             # <<<<<<<<<<<<<<
  *     """
  *     Returns an opaque object that backs up the current styles.
  */
-  __pyx_tuple__46 = PyTuple_Pack(3, __pyx_n_s_rv, __pyx_n_s_k, __pyx_n_s_v); if (unlikely(!__pyx_tuple__46)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__46);
-  __Pyx_GIVEREF(__pyx_tuple__46);
-  __pyx_codeobj__47 = (PyObject*)__Pyx_PyCode_New(0, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__46, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_backup, 793, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__47)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__47 = PyTuple_Pack(3, __pyx_n_s_rv, __pyx_n_s_k, __pyx_n_s_v); if (unlikely(!__pyx_tuple__47)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 789; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__47);
+  __Pyx_GIVEREF(__pyx_tuple__47);
+  __pyx_codeobj__48 = (PyObject*)__Pyx_PyCode_New(0, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__47, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_backup, 789, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__48)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 789; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/style.pyx":805
+  /* "renpy/style.pyx":801
  *     return rv
  * 
  * def restore(o):             # <<<<<<<<<<<<<<
  *     """
  *     Restores a style backup.
  */
-  __pyx_tuple__48 = PyTuple_Pack(6, __pyx_n_s_o, __pyx_n_s_s, __pyx_n_s_k, __pyx_n_s_v, __pyx_n_s_parent, __pyx_n_s_properties); if (unlikely(!__pyx_tuple__48)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 805; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__48);
-  __Pyx_GIVEREF(__pyx_tuple__48);
-  __pyx_codeobj__49 = (PyObject*)__Pyx_PyCode_New(1, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__48, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_restore, 805, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__49)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 805; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__49 = PyTuple_Pack(8, __pyx_n_s_o, __pyx_n_s_s, __pyx_n_s_keys, __pyx_n_s_i, __pyx_n_s_k, __pyx_n_s_v, __pyx_n_s_parent, __pyx_n_s_properties); if (unlikely(!__pyx_tuple__49)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__49);
+  __Pyx_GIVEREF(__pyx_tuple__49);
+  __pyx_codeobj__50 = (PyObject*)__Pyx_PyCode_New(1, 0, 8, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__49, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_style_p, __pyx_n_s_restore, 801, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__50)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -14376,7 +14709,7 @@ PyMODINIT_FUNC PyInit_style(void)
  * 
  *         if not isinstance(value, StyleCore):
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_1__setattr__, 0, __pyx_n_s_StyleManager___setattr, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__23)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_1__setattr__, 0, __pyx_n_s_StyleManager___setattr, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__24)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_setattr, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -14405,7 +14738,7 @@ PyMODINIT_FUNC PyInit_style(void)
  *         return get_style(name)
  * 
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_3__getattr__, 0, __pyx_n_s_StyleManager___getattr, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__25)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_3__getattr__, 0, __pyx_n_s_StyleManager___getattr, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__26)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_getattr, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -14434,9 +14767,9 @@ PyMODINIT_FUNC PyInit_style(void)
  *         """
  *         Deprecated way of creating styles.
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_5create, 0, __pyx_n_s_StyleManager_create, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__27)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_5create, 0, __pyx_n_s_StyleManager_create, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__28)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_tuple__28);
+  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_tuple__29);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_create, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
@@ -14447,7 +14780,7 @@ PyMODINIT_FUNC PyInit_style(void)
  *         renpy.style.rebuild()
  * 
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_7rebuild, 0, __pyx_n_s_StyleManager_rebuild, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__30)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_7rebuild, 0, __pyx_n_s_StyleManager_rebuild, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__31)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_rebuild, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -14459,7 +14792,7 @@ PyMODINIT_FUNC PyInit_style(void)
  *         """
  *         Returns `true` if name is a style.
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_9exists, 0, __pyx_n_s_StyleManager_exists, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__32)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_9exists, 0, __pyx_n_s_StyleManager_exists, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__33)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_exists, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -14471,7 +14804,7 @@ PyMODINIT_FUNC PyInit_style(void)
  *         """
  *         Gets a style, which may be a name or a tuple.
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_11get, 0, __pyx_n_s_StyleManager_get, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__34)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_5renpy_5style_12StyleManager_11get, 0, __pyx_n_s_StyleManager_get, NULL, __pyx_n_s_renpy_style, __pyx_d, ((PyObject *)__pyx_codeobj__35)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_get, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -14765,64 +15098,64 @@ PyMODINIT_FUNC PyInit_style(void)
   if (PyDict_SetItem(__pyx_d, __pyx_n_s_reset, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 747; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":761
+  /* "renpy/style.pyx":755
  * 
  * 
  * def build_styles():             # <<<<<<<<<<<<<<
  *     """
  *     Builds or rebuilds all styles.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_21build_styles, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 761; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_21build_styles, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 755; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_build_styles, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 761; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_build_styles, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 755; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":772
+  /* "renpy/style.pyx":768
  *         build_style(s)
  * 
  * def rebuild(prepare_screens=True):             # <<<<<<<<<<<<<<
  *     """
  *     Rebuilds all styles.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_23rebuild, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_23rebuild, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_rebuild, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 772; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_rebuild, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":786
+  /* "renpy/style.pyx":782
  *     renpy.exports.restart_interaction()
  * 
  * def copy_properties(p):             # <<<<<<<<<<<<<<
  *     """
  *     Makes a copy of the properties dict p.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_25copy_properties, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_25copy_properties, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_copy_properties, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_copy_properties, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":793
+  /* "renpy/style.pyx":789
  *     return [ dict(i) for i in p ]
  * 
  * def backup():             # <<<<<<<<<<<<<<
  *     """
  *     Returns an opaque object that backs up the current styles.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_27backup, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_27backup, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 789; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_backup, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_backup, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 789; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/style.pyx":805
+  /* "renpy/style.pyx":801
  *     return rv
  * 
  * def restore(o):             # <<<<<<<<<<<<<<
  *     """
  *     Restores a style backup.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_29restore, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 805; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_5style_29restore, NULL, __pyx_n_s_renpy_style); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_restore, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 805; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_restore, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "renpy/style.pyx":1
diff --git a/module/gen/renpy.text.textsupport.c b/module/gen/renpy.text.textsupport.c
index d467a56..fa7473b 100644
--- a/module/gen/renpy.text.textsupport.c
+++ b/module/gen/renpy.text.textsupport.c
@@ -974,6 +974,7 @@ static char __pyx_k_mark_ruby_top[] = "mark_ruby_top";
 static char __pyx_k_no_ideographs[] = "no_ideographs";
 static char __pyx_k_reverse_lines[] = "reverse_lines";
 static char __pyx_k_justify_offset[] = "justify_offset";
+static char __pyx_k_linebreak_list[] = "linebreak_list";
 static char __pyx_k_place_vertical[] = "place_vertical";
 static char __pyx_k_hyperlink_areas[] = "hyperlink_areas";
 static char __pyx_k_language_tailor[] = "language_tailor";
@@ -1106,6 +1107,7 @@ static PyObject *__pyx_n_s_line;
 static PyObject *__pyx_n_s_line_spacing;
 static PyObject *__pyx_n_s_linebreak_debug;
 static PyObject *__pyx_n_s_linebreak_greedy;
+static PyObject *__pyx_n_s_linebreak_list;
 static PyObject *__pyx_n_s_linebreak_nobreak;
 static PyObject *__pyx_n_s_lines;
 static PyObject *__pyx_n_s_main;
@@ -1202,19 +1204,20 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_6annotate_unicode(CYTHON_UN
 static PyObject *__pyx_pf_5renpy_4text_11textsupport_8linebreak_greedy(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_first_width, int __pyx_v_rest_width); /* proto */
 static PyObject *__pyx_pf_5renpy_4text_11textsupport_10linebreak_nobreak(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /* proto */
 static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_start_x, float __pyx_v_first_indent, float __pyx_v_rest_indent); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_y, int __pyx_v_spacing, int __pyx_v_leading); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_amount); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_t, float __pyx_v_gps, PyObject *__pyx_v_glyphs); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_ruby_offset, CYTHON_UNUSED int __pyx_v_surf_width, CYTHON_UNUSED int __pyx_v_surf_height); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_lines, int __pyx_v_width, float __pyx_v_text_align, int __pyx_v_justify); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_source, PyObject *__pyx_v_dest); /* proto */
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, PyObject *__pyx_v_lines, double __pyx_v_dx, double __pyx_v_dy, double __pyx_v_w, double __pyx_v_h); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_14linebreak_list(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_horizontal(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_start_x, float __pyx_v_first_indent, float __pyx_v_rest_indent); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_18place_vertical(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_y, int __pyx_v_spacing, int __pyx_v_leading); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_20kerning(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_amount); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_22assign_times(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_t, float __pyx_v_gps, PyObject *__pyx_v_glyphs); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_24max_times(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_26hyperlink_areas(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_top(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_30mark_ruby_bottom(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_32place_ruby(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_ruby_offset, CYTHON_UNUSED int __pyx_v_surf_width, CYTHON_UNUSED int __pyx_v_surf_height); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_34align_and_justify(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_lines, int __pyx_v_width, float __pyx_v_text_align, int __pyx_v_justify); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_36reverse_lines(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_38copy_splits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_source, PyObject *__pyx_v_dest); /* proto */
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_40tweak_glyph_spacing(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, PyObject *__pyx_v_lines, double __pyx_v_dx, double __pyx_v_dy, double __pyx_v_w, double __pyx_v_h); /* proto */
 static PyObject *__pyx_tp_new_5renpy_4text_11textsupport_Glyph(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_5renpy_4text_11textsupport_Line(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_int_0;
@@ -1280,6 +1283,7 @@ static PyObject *__pyx_tuple__42;
 static PyObject *__pyx_tuple__44;
 static PyObject *__pyx_tuple__46;
 static PyObject *__pyx_tuple__48;
+static PyObject *__pyx_tuple__50;
 static PyObject *__pyx_codeobj__10;
 static PyObject *__pyx_codeobj__12;
 static PyObject *__pyx_codeobj__15;
@@ -1300,6 +1304,7 @@ static PyObject *__pyx_codeobj__43;
 static PyObject *__pyx_codeobj__45;
 static PyObject *__pyx_codeobj__47;
 static PyObject *__pyx_codeobj__49;
+static PyObject *__pyx_codeobj__51;
 
 /* "renpy/text/textsupport.pyx":26
  * cdef class Glyph:
@@ -6083,16 +6088,295 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN
 /* "renpy/text/textsupport.pyx":402
  * 
  * 
+ * def linebreak_list(list glyphs):             # <<<<<<<<<<<<<<
+ *     """
+ *     Returns a list of unicode strings, one per broken line.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_15linebreak_list(PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_14linebreak_list[] = "\n    Returns a list of unicode strings, one per broken line.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_15linebreak_list = {"linebreak_list", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_15linebreak_list, METH_O, __pyx_doc_5renpy_4text_11textsupport_14linebreak_list};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_15linebreak_list(PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
+  CYTHON_UNUSED int __pyx_lineno = 0;
+  CYTHON_UNUSED const char *__pyx_filename = NULL;
+  CYTHON_UNUSED int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("linebreak_list (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_14linebreak_list(__pyx_self, ((PyObject*)__pyx_v_glyphs));
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_14linebreak_list(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
+  struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
+  PyObject *__pyx_v_rv = NULL;
+  PyObject *__pyx_v_line = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("linebreak_list", 0);
+
+  /* "renpy/text/textsupport.pyx":409
+ *     cdef Glyph g
+ * 
+ *     rv = [ ]             # <<<<<<<<<<<<<<
+ *     line = u""
+ * 
+ */
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_rv = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "renpy/text/textsupport.pyx":410
+ * 
+ *     rv = [ ]
+ *     line = u""             # <<<<<<<<<<<<<<
+ * 
+ *     for g in glyphs:
+ */
+  __Pyx_INCREF(__pyx_kp_u_);
+  __pyx_v_line = __pyx_kp_u_;
+
+  /* "renpy/text/textsupport.pyx":412
+ *     line = u""
+ * 
+ *     for g in glyphs:             # <<<<<<<<<<<<<<
+ * 
+ *         if g.split == SPLIT_INSTEAD:
+ */
+  if (unlikely(__pyx_v_glyphs == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_1 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
+  for (;;) {
+    if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
+    #if CYTHON_COMPILING_IN_CPYTHON
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    #else
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    #endif
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
+    __pyx_t_3 = 0;
+
+    /* "renpy/text/textsupport.pyx":414
+ *     for g in glyphs:
+ * 
+ *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
+ *             rv.append(line)
+ *             line = u""
+ */
+    switch (__pyx_v_g->split) {
+      case __pyx_e_5renpy_4text_11textsupport_SPLIT_INSTEAD:
+
+      /* "renpy/text/textsupport.pyx":415
+ * 
+ *         if g.split == SPLIT_INSTEAD:
+ *             rv.append(line)             # <<<<<<<<<<<<<<
+ *             line = u""
+ *         elif g.split == SPLIT_BEFORE:
+ */
+      __pyx_t_4 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_v_line); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 415; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+      /* "renpy/text/textsupport.pyx":416
+ *         if g.split == SPLIT_INSTEAD:
+ *             rv.append(line)
+ *             line = u""             # <<<<<<<<<<<<<<
+ *         elif g.split == SPLIT_BEFORE:
+ *             rv.append(line)
+ */
+      __Pyx_INCREF(__pyx_kp_u_);
+      __Pyx_DECREF_SET(__pyx_v_line, __pyx_kp_u_);
+
+      /* "renpy/text/textsupport.pyx":414
+ *     for g in glyphs:
+ * 
+ *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
+ *             rv.append(line)
+ *             line = u""
+ */
+      break;
+
+      /* "renpy/text/textsupport.pyx":417
+ *             rv.append(line)
+ *             line = u""
+ *         elif g.split == SPLIT_BEFORE:             # <<<<<<<<<<<<<<
+ *             rv.append(line)
+ *             line = unichr(g.character)
+ */
+      case __pyx_e_5renpy_4text_11textsupport_SPLIT_BEFORE:
+
+      /* "renpy/text/textsupport.pyx":418
+ *             line = u""
+ *         elif g.split == SPLIT_BEFORE:
+ *             rv.append(line)             # <<<<<<<<<<<<<<
+ *             line = unichr(g.character)
+ *         else:
+ */
+      __pyx_t_4 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_v_line); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+      /* "renpy/text/textsupport.pyx":419
+ *         elif g.split == SPLIT_BEFORE:
+ *             rv.append(line)
+ *             line = unichr(g.character)             # <<<<<<<<<<<<<<
+ *         else:
+ *             line += unichr(g.character)
+ */
+      __pyx_t_3 = __Pyx_PyInt_From_unsigned_int(__pyx_v_g->character); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_GIVEREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_unichr, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_DECREF_SET(__pyx_v_line, __pyx_t_3);
+      __pyx_t_3 = 0;
+
+      /* "renpy/text/textsupport.pyx":417
+ *             rv.append(line)
+ *             line = u""
+ *         elif g.split == SPLIT_BEFORE:             # <<<<<<<<<<<<<<
+ *             rv.append(line)
+ *             line = unichr(g.character)
+ */
+      break;
+      default:
+
+      /* "renpy/text/textsupport.pyx":421
+ *             line = unichr(g.character)
+ *         else:
+ *             line += unichr(g.character)             # <<<<<<<<<<<<<<
+ * 
+ *     if line:
+ */
+      __pyx_t_3 = __Pyx_PyInt_From_unsigned_int(__pyx_v_g->character); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_GIVEREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_unichr, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_v_line, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_DECREF_SET(__pyx_v_line, __pyx_t_5);
+      __pyx_t_5 = 0;
+      break;
+    }
+
+    /* "renpy/text/textsupport.pyx":412
+ *     line = u""
+ * 
+ *     for g in glyphs:             # <<<<<<<<<<<<<<
+ * 
+ *         if g.split == SPLIT_INSTEAD:
+ */
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "renpy/text/textsupport.pyx":423
+ *             line += unichr(g.character)
+ * 
+ *     if line:             # <<<<<<<<<<<<<<
+ *         rv.append(line)
+ * 
+ */
+  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_line); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_t_6) {
+
+    /* "renpy/text/textsupport.pyx":424
+ * 
+ *     if line:
+ *         rv.append(line)             # <<<<<<<<<<<<<<
+ * 
+ *     return rv
+ */
+    __pyx_t_4 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_v_line); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+    /* "renpy/text/textsupport.pyx":423
+ *             line += unichr(g.character)
+ * 
+ *     if line:             # <<<<<<<<<<<<<<
+ *         rv.append(line)
+ * 
+ */
+  }
+
+  /* "renpy/text/textsupport.pyx":426
+ *         rv.append(line)
+ * 
+ *     return rv             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_rv);
+  __pyx_r = __pyx_v_rv;
+  goto __pyx_L0;
+
+  /* "renpy/text/textsupport.pyx":402
+ * 
+ * 
+ * def linebreak_list(list glyphs):             # <<<<<<<<<<<<<<
+ *     """
+ *     Returns a list of unicode strings, one per broken line.
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("renpy.text.textsupport.linebreak_list", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_g);
+  __Pyx_XDECREF(__pyx_v_rv);
+  __Pyx_XDECREF(__pyx_v_line);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "renpy/text/textsupport.pyx":429
+ * 
+ * 
  * def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):             # <<<<<<<<<<<<<<
  *     """
  *     Place the glyphs horizontally, without taking into account the indentation
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_15place_horizontal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_14place_horizontal[] = "\n    Place the glyphs horizontally, without taking into account the indentation\n    at the start of the line. Returns the width of the laid-out line.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_15place_horizontal = {"place_horizontal", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_15place_horizontal, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_14place_horizontal};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_15place_horizontal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_horizontal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_16place_horizontal[] = "\n    Place the glyphs horizontally, without taking into account the indentation\n    at the start of the line. Returns the width of the laid-out line.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_17place_horizontal = {"place_horizontal", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_17place_horizontal, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_16place_horizontal};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_horizontal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_glyphs = 0;
   float __pyx_v_start_x;
   float __pyx_v_first_indent;
@@ -6125,21 +6409,21 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_15place_horizontal(PyObject
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_start_x)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_first_indent)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_rest_indent)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_horizontal") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_horizontal") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -6150,20 +6434,20 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_15place_horizontal(PyObject
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
     __pyx_v_glyphs = ((PyObject*)values[0]);
-    __pyx_v_start_x = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_start_x == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_first_indent = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_first_indent == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_rest_indent = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_rest_indent == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_start_x = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_start_x == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_first_indent = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_first_indent == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_rest_indent = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_rest_indent == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("place_horizontal", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.place_horizontal", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_14place_horizontal(__pyx_self, __pyx_v_glyphs, __pyx_v_start_x, __pyx_v_first_indent, __pyx_v_rest_indent);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_16place_horizontal(__pyx_self, __pyx_v_glyphs, __pyx_v_start_x, __pyx_v_first_indent, __pyx_v_rest_indent);
 
   /* function exit code */
   goto __pyx_L0;
@@ -6174,7 +6458,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_15place_horizontal(PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_start_x, float __pyx_v_first_indent, float __pyx_v_rest_indent) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_horizontal(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_start_x, float __pyx_v_first_indent, float __pyx_v_rest_indent) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_old_g = 0;
   float __pyx_v_x;
@@ -6192,7 +6476,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("place_horizontal", 0);
 
-  /* "renpy/text/textsupport.pyx":408
+  /* "renpy/text/textsupport.pyx":435
  *     """
  * 
  *     if not glyphs:             # <<<<<<<<<<<<<<
@@ -6203,7 +6487,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
   __pyx_t_2 = ((!__pyx_t_1) != 0);
   if (__pyx_t_2) {
 
-    /* "renpy/text/textsupport.pyx":409
+    /* "renpy/text/textsupport.pyx":436
  * 
  *     if not glyphs:
  *         return 0             # <<<<<<<<<<<<<<
@@ -6215,7 +6499,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __pyx_r = __pyx_int_0;
     goto __pyx_L0;
 
-    /* "renpy/text/textsupport.pyx":408
+    /* "renpy/text/textsupport.pyx":435
  *     """
  * 
  *     if not glyphs:             # <<<<<<<<<<<<<<
@@ -6224,7 +6508,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
   }
 
-  /* "renpy/text/textsupport.pyx":414
+  /* "renpy/text/textsupport.pyx":441
  *     cdef float x, maxx
  * 
  *     x = start_x + first_indent             # <<<<<<<<<<<<<<
@@ -6233,7 +6517,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
   __pyx_v_x = (__pyx_v_start_x + __pyx_v_first_indent);
 
-  /* "renpy/text/textsupport.pyx":415
+  /* "renpy/text/textsupport.pyx":442
  * 
  *     x = start_x + first_indent
  *     maxx = 0             # <<<<<<<<<<<<<<
@@ -6242,7 +6526,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
   __pyx_v_maxx = 0.0;
 
-  /* "renpy/text/textsupport.pyx":416
+  /* "renpy/text/textsupport.pyx":443
  *     x = start_x + first_indent
  *     maxx = 0
  *     old_g = None             # <<<<<<<<<<<<<<
@@ -6252,7 +6536,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
   __Pyx_INCREF(Py_None);
   __pyx_v_old_g = ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)Py_None);
 
-  /* "renpy/text/textsupport.pyx":418
+  /* "renpy/text/textsupport.pyx":445
  *     old_g = None
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -6261,22 +6545,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_3 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
   for (;;) {
     if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     #endif
-    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_5));
     __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":420
+    /* "renpy/text/textsupport.pyx":447
  *     for g in glyphs:
  * 
  *         if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -6286,7 +6570,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __pyx_t_2 = ((__pyx_v_g->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":421
+      /* "renpy/text/textsupport.pyx":448
  * 
  *         if g.ruby == RUBY_TOP:
  *             continue             # <<<<<<<<<<<<<<
@@ -6295,7 +6579,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       goto __pyx_L4_continue;
 
-      /* "renpy/text/textsupport.pyx":420
+      /* "renpy/text/textsupport.pyx":447
  *     for g in glyphs:
  * 
  *         if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -6304,7 +6588,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     }
 
-    /* "renpy/text/textsupport.pyx":423
+    /* "renpy/text/textsupport.pyx":450
  *             continue
  * 
  *         if g.split != SPLIT_NONE and old_g:             # <<<<<<<<<<<<<<
@@ -6317,12 +6601,12 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
       __pyx_t_2 = __pyx_t_1;
       goto __pyx_L8_bool_binop_done;
     }
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_old_g)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_IsTrue(((PyObject *)__pyx_v_old_g)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 450; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_2 = __pyx_t_1;
     __pyx_L8_bool_binop_done:;
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":427
+      /* "renpy/text/textsupport.pyx":454
  *             # be its width. (This makes things like strikeout and underline
  *             # easier, since we only need consider advance.)
  *             old_g.advance = old_g.width             # <<<<<<<<<<<<<<
@@ -6332,7 +6616,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
       __pyx_t_6 = __pyx_v_old_g->width;
       __pyx_v_old_g->advance = __pyx_t_6;
 
-      /* "renpy/text/textsupport.pyx":423
+      /* "renpy/text/textsupport.pyx":450
  *             continue
  * 
  *         if g.split != SPLIT_NONE and old_g:             # <<<<<<<<<<<<<<
@@ -6341,7 +6625,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     }
 
-    /* "renpy/text/textsupport.pyx":429
+    /* "renpy/text/textsupport.pyx":456
  *             old_g.advance = old_g.width
  * 
  *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
@@ -6351,7 +6635,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     switch (__pyx_v_g->split) {
       case __pyx_e_5renpy_4text_11textsupport_SPLIT_INSTEAD:
 
-      /* "renpy/text/textsupport.pyx":430
+      /* "renpy/text/textsupport.pyx":457
  * 
  *         if g.split == SPLIT_INSTEAD:
  *             x = start_x + rest_indent             # <<<<<<<<<<<<<<
@@ -6360,7 +6644,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       __pyx_v_x = (__pyx_v_start_x + __pyx_v_rest_indent);
 
-      /* "renpy/text/textsupport.pyx":431
+      /* "renpy/text/textsupport.pyx":458
  *         if g.split == SPLIT_INSTEAD:
  *             x = start_x + rest_indent
  *             continue             # <<<<<<<<<<<<<<
@@ -6369,7 +6653,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       goto __pyx_L4_continue;
 
-      /* "renpy/text/textsupport.pyx":429
+      /* "renpy/text/textsupport.pyx":456
  *             old_g.advance = old_g.width
  * 
  *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
@@ -6378,7 +6662,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       break;
 
-      /* "renpy/text/textsupport.pyx":433
+      /* "renpy/text/textsupport.pyx":460
  *             continue
  * 
  *         elif g.split == SPLIT_BEFORE:             # <<<<<<<<<<<<<<
@@ -6387,7 +6671,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       case __pyx_e_5renpy_4text_11textsupport_SPLIT_BEFORE:
 
-      /* "renpy/text/textsupport.pyx":434
+      /* "renpy/text/textsupport.pyx":461
  * 
  *         elif g.split == SPLIT_BEFORE:
  *             x = start_x + rest_indent             # <<<<<<<<<<<<<<
@@ -6396,7 +6680,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       __pyx_v_x = (__pyx_v_start_x + __pyx_v_rest_indent);
 
-      /* "renpy/text/textsupport.pyx":433
+      /* "renpy/text/textsupport.pyx":460
  *             continue
  * 
  *         elif g.split == SPLIT_BEFORE:             # <<<<<<<<<<<<<<
@@ -6407,7 +6691,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
       default: break;
     }
 
-    /* "renpy/text/textsupport.pyx":436
+    /* "renpy/text/textsupport.pyx":463
  *             x = start_x + rest_indent
  * 
  *         g.x = <short> (x + .5)             # <<<<<<<<<<<<<<
@@ -6416,7 +6700,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     __pyx_v_g->x = ((short)(__pyx_v_x + .5));
 
-    /* "renpy/text/textsupport.pyx":438
+    /* "renpy/text/textsupport.pyx":465
  *         g.x = <short> (x + .5)
  * 
  *         if maxx < x + g.width:             # <<<<<<<<<<<<<<
@@ -6426,7 +6710,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __pyx_t_2 = ((__pyx_v_maxx < (__pyx_v_x + __pyx_v_g->width)) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":439
+      /* "renpy/text/textsupport.pyx":466
  * 
  *         if maxx < x + g.width:
  *             maxx = x + g.width             # <<<<<<<<<<<<<<
@@ -6435,7 +6719,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       __pyx_v_maxx = (__pyx_v_x + __pyx_v_g->width);
 
-      /* "renpy/text/textsupport.pyx":438
+      /* "renpy/text/textsupport.pyx":465
  *         g.x = <short> (x + .5)
  * 
  *         if maxx < x + g.width:             # <<<<<<<<<<<<<<
@@ -6444,7 +6728,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     }
 
-    /* "renpy/text/textsupport.pyx":440
+    /* "renpy/text/textsupport.pyx":467
  *         if maxx < x + g.width:
  *             maxx = x + g.width
  *         if maxx < x + g.advance:             # <<<<<<<<<<<<<<
@@ -6454,7 +6738,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __pyx_t_2 = ((__pyx_v_maxx < (__pyx_v_x + __pyx_v_g->advance)) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":441
+      /* "renpy/text/textsupport.pyx":468
  *             maxx = x + g.width
  *         if maxx < x + g.advance:
  *             maxx = x + g.advance             # <<<<<<<<<<<<<<
@@ -6463,7 +6747,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       __pyx_v_maxx = (__pyx_v_x + __pyx_v_g->advance);
 
-      /* "renpy/text/textsupport.pyx":440
+      /* "renpy/text/textsupport.pyx":467
  *         if maxx < x + g.width:
  *             maxx = x + g.width
  *         if maxx < x + g.advance:             # <<<<<<<<<<<<<<
@@ -6472,7 +6756,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     }
 
-    /* "renpy/text/textsupport.pyx":443
+    /* "renpy/text/textsupport.pyx":470
  *             maxx = x + g.advance
  * 
  *         x += g.advance             # <<<<<<<<<<<<<<
@@ -6481,7 +6765,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     __pyx_v_x = (__pyx_v_x + __pyx_v_g->advance);
 
-    /* "renpy/text/textsupport.pyx":446
+    /* "renpy/text/textsupport.pyx":473
  * 
  *         # Limit us to some width.
  *         if x > MAX_WIDTH:             # <<<<<<<<<<<<<<
@@ -6491,7 +6775,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __pyx_t_2 = ((__pyx_v_x > __pyx_v_5renpy_4text_11textsupport_MAX_WIDTH) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":447
+      /* "renpy/text/textsupport.pyx":474
  *         # Limit us to some width.
  *         if x > MAX_WIDTH:
  *             x = MAX_WIDTH             # <<<<<<<<<<<<<<
@@ -6500,7 +6784,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
       __pyx_v_x = __pyx_v_5renpy_4text_11textsupport_MAX_WIDTH;
 
-      /* "renpy/text/textsupport.pyx":446
+      /* "renpy/text/textsupport.pyx":473
  * 
  *         # Limit us to some width.
  *         if x > MAX_WIDTH:             # <<<<<<<<<<<<<<
@@ -6509,7 +6793,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
     }
 
-    /* "renpy/text/textsupport.pyx":449
+    /* "renpy/text/textsupport.pyx":476
  *             x = MAX_WIDTH
  * 
  *         old_g = g             # <<<<<<<<<<<<<<
@@ -6519,7 +6803,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
     __Pyx_INCREF(((PyObject *)__pyx_v_g));
     __Pyx_DECREF_SET(__pyx_v_old_g, __pyx_v_g);
 
-    /* "renpy/text/textsupport.pyx":418
+    /* "renpy/text/textsupport.pyx":445
  *     old_g = None
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -6530,7 +6814,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
   }
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/text/textsupport.pyx":451
+  /* "renpy/text/textsupport.pyx":478
  *         old_g = g
  * 
  *     return maxx             # <<<<<<<<<<<<<<
@@ -6538,13 +6822,13 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  * def place_vertical(list glyphs, int y, int spacing, int leading):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_maxx); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_maxx); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 478; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":402
+  /* "renpy/text/textsupport.pyx":429
  * 
  * 
  * def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):             # <<<<<<<<<<<<<<
@@ -6566,7 +6850,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":453
+/* "renpy/text/textsupport.pyx":480
  *     return maxx
  * 
  * def place_vertical(list glyphs, int y, int spacing, int leading):             # <<<<<<<<<<<<<<
@@ -6575,10 +6859,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_14place_horizontal(CYTHON_U
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_vertical(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_16place_vertical[] = "\n    Vertically places the non-ruby glyphs. Returns a list of line end heights,\n    and the y-value for the top of the next line.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_17place_vertical = {"place_vertical", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_17place_vertical, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_16place_vertical};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_vertical(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_19place_vertical(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_18place_vertical[] = "\n    Vertically places the non-ruby glyphs. Returns a list of line end heights,\n    and the y-value for the top of the next line.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_19place_vertical = {"place_vertical", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_19place_vertical, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_18place_vertical};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_19place_vertical(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_glyphs = 0;
   int __pyx_v_y;
   int __pyx_v_spacing;
@@ -6611,21 +6895,21 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_vertical(PyObject *
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_y)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_spacing)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_leading)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_vertical") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_vertical") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -6636,20 +6920,20 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_vertical(PyObject *
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
     __pyx_v_glyphs = ((PyObject*)values[0]);
-    __pyx_v_y = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_y == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_spacing = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_spacing == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_leading = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_leading == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_y == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_spacing = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_spacing == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_leading = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_leading == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("place_vertical", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.place_vertical", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_16place_vertical(__pyx_self, __pyx_v_glyphs, __pyx_v_y, __pyx_v_spacing, __pyx_v_leading);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_18place_vertical(__pyx_self, __pyx_v_glyphs, __pyx_v_y, __pyx_v_spacing, __pyx_v_leading);
 
   /* function exit code */
   goto __pyx_L0;
@@ -6660,7 +6944,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_17place_vertical(PyObject *
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_y, int __pyx_v_spacing, int __pyx_v_leading) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_18place_vertical(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_y, int __pyx_v_spacing, int __pyx_v_leading) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_gg = 0;
   int __pyx_v_pos;
@@ -6689,7 +6973,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("place_vertical", 0);
 
-  /* "renpy/text/textsupport.pyx":465
+  /* "renpy/text/textsupport.pyx":492
  *     cdef bint end_line
  * 
  *     if not glyphs:             # <<<<<<<<<<<<<<
@@ -6700,7 +6984,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
   __pyx_t_2 = ((!__pyx_t_1) != 0);
   if (__pyx_t_2) {
 
-    /* "renpy/text/textsupport.pyx":466
+    /* "renpy/text/textsupport.pyx":493
  * 
  *     if not glyphs:
  *         return [ ], y             # <<<<<<<<<<<<<<
@@ -6708,11 +6992,11 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  *     len_glyphs = len(glyphs)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 466; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_y); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 466; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_y); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 466; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_GIVEREF(__pyx_t_3);
     PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
@@ -6724,7 +7008,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     __pyx_t_5 = 0;
     goto __pyx_L0;
 
-    /* "renpy/text/textsupport.pyx":465
+    /* "renpy/text/textsupport.pyx":492
  *     cdef bint end_line
  * 
  *     if not glyphs:             # <<<<<<<<<<<<<<
@@ -6733,7 +7017,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   }
 
-  /* "renpy/text/textsupport.pyx":468
+  /* "renpy/text/textsupport.pyx":495
  *         return [ ], y
  * 
  *     len_glyphs = len(glyphs)             # <<<<<<<<<<<<<<
@@ -6742,12 +7026,12 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 495; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_6 = PyList_GET_SIZE(__pyx_v_glyphs); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyList_GET_SIZE(__pyx_v_glyphs); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 495; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_len_glyphs = __pyx_t_6;
 
-  /* "renpy/text/textsupport.pyx":470
+  /* "renpy/text/textsupport.pyx":497
  *     len_glyphs = len(glyphs)
  * 
  *     pos = 0             # <<<<<<<<<<<<<<
@@ -6756,7 +7040,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   __pyx_v_pos = 0;
 
-  /* "renpy/text/textsupport.pyx":471
+  /* "renpy/text/textsupport.pyx":498
  * 
  *     pos = 0
  *     sol = 0             # <<<<<<<<<<<<<<
@@ -6765,7 +7049,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   __pyx_v_sol = 0;
 
-  /* "renpy/text/textsupport.pyx":473
+  /* "renpy/text/textsupport.pyx":500
  *     sol = 0
  * 
  *     ascent = 0             # <<<<<<<<<<<<<<
@@ -6774,7 +7058,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   __pyx_v_ascent = 0;
 
-  /* "renpy/text/textsupport.pyx":474
+  /* "renpy/text/textsupport.pyx":501
  * 
  *     ascent = 0
  *     line_spacing = 0             # <<<<<<<<<<<<<<
@@ -6783,19 +7067,19 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   __pyx_v_line_spacing = 0;
 
-  /* "renpy/text/textsupport.pyx":476
+  /* "renpy/text/textsupport.pyx":503
  *     line_spacing = 0
  * 
  *     rv = [ ]             # <<<<<<<<<<<<<<
  * 
  *     y += leading
  */
-  __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 476; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 503; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __pyx_v_rv = ((PyObject*)__pyx_t_5);
   __pyx_t_5 = 0;
 
-  /* "renpy/text/textsupport.pyx":478
+  /* "renpy/text/textsupport.pyx":505
  *     rv = [ ]
  * 
  *     y += leading             # <<<<<<<<<<<<<<
@@ -6804,7 +7088,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   __pyx_v_y = (__pyx_v_y + __pyx_v_leading);
 
-  /* "renpy/text/textsupport.pyx":480
+  /* "renpy/text/textsupport.pyx":507
  *     y += leading
  * 
  *     while True:             # <<<<<<<<<<<<<<
@@ -6813,7 +7097,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
   while (1) {
 
-    /* "renpy/text/textsupport.pyx":482
+    /* "renpy/text/textsupport.pyx":509
  *     while True:
  * 
  *         if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -6823,7 +7107,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     __pyx_t_2 = ((__pyx_v_pos >= __pyx_v_len_glyphs) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":483
+      /* "renpy/text/textsupport.pyx":510
  * 
  *         if pos >= len_glyphs:
  *             end_line = True             # <<<<<<<<<<<<<<
@@ -6832,7 +7116,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_end_line = 1;
 
-      /* "renpy/text/textsupport.pyx":482
+      /* "renpy/text/textsupport.pyx":509
  *     while True:
  * 
  *         if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -6842,7 +7126,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
       goto __pyx_L6;
     }
 
-    /* "renpy/text/textsupport.pyx":485
+    /* "renpy/text/textsupport.pyx":512
  *             end_line = True
  *         else:
  *             g = glyphs[pos]             # <<<<<<<<<<<<<<
@@ -6852,15 +7136,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     /*else*/ {
       if (unlikely(__pyx_v_glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
       __Pyx_GOTREF(__pyx_t_5);
-      if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_5));
       __pyx_t_5 = 0;
 
-      /* "renpy/text/textsupport.pyx":486
+      /* "renpy/text/textsupport.pyx":513
  *         else:
  *             g = glyphs[pos]
  *             end_line = (g.split != SPLIT_NONE)             # <<<<<<<<<<<<<<
@@ -6871,7 +7155,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     }
     __pyx_L6:;
 
-    /* "renpy/text/textsupport.pyx":488
+    /* "renpy/text/textsupport.pyx":515
  *             end_line = (g.split != SPLIT_NONE)
  * 
  *         if end_line:             # <<<<<<<<<<<<<<
@@ -6881,7 +7165,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     __pyx_t_2 = (__pyx_v_end_line != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":490
+      /* "renpy/text/textsupport.pyx":517
  *         if end_line:
  * 
  *             for i from sol <= i < pos:             # <<<<<<<<<<<<<<
@@ -6891,7 +7175,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
       __pyx_t_7 = __pyx_v_pos;
       for (__pyx_v_i = __pyx_v_sol; __pyx_v_i < __pyx_t_7; __pyx_v_i++) {
 
-        /* "renpy/text/textsupport.pyx":491
+        /* "renpy/text/textsupport.pyx":518
  * 
  *             for i from sol <= i < pos:
  *                 gg = glyphs[i]             # <<<<<<<<<<<<<<
@@ -6900,15 +7184,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
         if (unlikely(__pyx_v_glyphs == Py_None)) {
           PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-          {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
-        __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+        __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
         __Pyx_GOTREF(__pyx_t_5);
-        if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_XDECREF_SET(__pyx_v_gg, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_5));
         __pyx_t_5 = 0;
 
-        /* "renpy/text/textsupport.pyx":493
+        /* "renpy/text/textsupport.pyx":520
  *                 gg = glyphs[i]
  * 
  *                 if gg.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -6918,7 +7202,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
         __pyx_t_2 = ((__pyx_v_gg->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
         if (__pyx_t_2) {
 
-          /* "renpy/text/textsupport.pyx":494
+          /* "renpy/text/textsupport.pyx":521
  * 
  *                 if gg.ruby == RUBY_TOP:
  *                     continue             # <<<<<<<<<<<<<<
@@ -6927,7 +7211,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
           goto __pyx_L8_continue;
 
-          /* "renpy/text/textsupport.pyx":493
+          /* "renpy/text/textsupport.pyx":520
  *                 gg = glyphs[i]
  * 
  *                 if gg.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -6936,7 +7220,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
         }
 
-        /* "renpy/text/textsupport.pyx":496
+        /* "renpy/text/textsupport.pyx":523
  *                     continue
  * 
  *                 if gg.ascent:             # <<<<<<<<<<<<<<
@@ -6946,7 +7230,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
         __pyx_t_2 = (__pyx_v_gg->ascent != 0);
         if (__pyx_t_2) {
 
-          /* "renpy/text/textsupport.pyx":497
+          /* "renpy/text/textsupport.pyx":524
  * 
  *                 if gg.ascent:
  *                     gg.y = y + ascent             # <<<<<<<<<<<<<<
@@ -6955,7 +7239,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
           __pyx_v_gg->y = (__pyx_v_y + __pyx_v_ascent);
 
-          /* "renpy/text/textsupport.pyx":496
+          /* "renpy/text/textsupport.pyx":523
  *                     continue
  * 
  *                 if gg.ascent:             # <<<<<<<<<<<<<<
@@ -6965,7 +7249,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
           goto __pyx_L11;
         }
 
-        /* "renpy/text/textsupport.pyx":502
+        /* "renpy/text/textsupport.pyx":529
  *                     # Glyphs without ascents are displayables, which get
  *                     # aligned to the top of the line.
  *                     gg.y = y             # <<<<<<<<<<<<<<
@@ -6975,7 +7259,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
         /*else*/ {
           __pyx_v_gg->y = __pyx_v_y;
 
-          /* "renpy/text/textsupport.pyx":503
+          /* "renpy/text/textsupport.pyx":530
  *                     # aligned to the top of the line.
  *                     gg.y = y
  *                     gg.ascent = ascent             # <<<<<<<<<<<<<<
@@ -6988,24 +7272,24 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
         __pyx_L8_continue:;
       }
 
-      /* "renpy/text/textsupport.pyx":505
+      /* "renpy/text/textsupport.pyx":532
  *                     gg.ascent = ascent
  * 
  *             l = Line(y - leading, leading + line_spacing + spacing, glyphs[sol:pos])             # <<<<<<<<<<<<<<
  *             rv.append(l)
  * 
  */
-      __pyx_t_5 = __Pyx_PyInt_From_int((__pyx_v_y - __pyx_v_leading)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __Pyx_PyInt_From_int((__pyx_v_y - __pyx_v_leading)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_4 = __Pyx_PyInt_From_int(((__pyx_v_leading + __pyx_v_line_spacing) + __pyx_v_spacing)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_PyInt_From_int(((__pyx_v_leading + __pyx_v_line_spacing) + __pyx_v_spacing)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       if (unlikely(__pyx_v_glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_3 = __Pyx_PyList_GetSlice(__pyx_v_glyphs, __pyx_v_sol, __pyx_v_pos); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_PyList_GetSlice(__pyx_v_glyphs, __pyx_v_sol, __pyx_v_pos); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_GIVEREF(__pyx_t_5);
       PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5);
@@ -7016,22 +7300,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
       __pyx_t_5 = 0;
       __pyx_t_4 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_5renpy_4text_11textsupport_Line), __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_5renpy_4text_11textsupport_Line), __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       __Pyx_XDECREF_SET(__pyx_v_l, ((struct __pyx_obj_5renpy_4text_11textsupport_Line *)__pyx_t_3));
       __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":506
+      /* "renpy/text/textsupport.pyx":533
  * 
  *             l = Line(y - leading, leading + line_spacing + spacing, glyphs[sol:pos])
  *             rv.append(l)             # <<<<<<<<<<<<<<
  * 
  *             y += line_spacing
  */
-      __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_rv, ((PyObject *)__pyx_v_l)); if (unlikely(__pyx_t_9 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_rv, ((PyObject *)__pyx_v_l)); if (unlikely(__pyx_t_9 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 533; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-      /* "renpy/text/textsupport.pyx":508
+      /* "renpy/text/textsupport.pyx":535
  *             rv.append(l)
  * 
  *             y += line_spacing             # <<<<<<<<<<<<<<
@@ -7040,7 +7324,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_y = (__pyx_v_y + __pyx_v_line_spacing);
 
-      /* "renpy/text/textsupport.pyx":509
+      /* "renpy/text/textsupport.pyx":536
  * 
  *             y += line_spacing
  *             y += spacing             # <<<<<<<<<<<<<<
@@ -7049,7 +7333,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_y = (__pyx_v_y + __pyx_v_spacing);
 
-      /* "renpy/text/textsupport.pyx":510
+      /* "renpy/text/textsupport.pyx":537
  *             y += line_spacing
  *             y += spacing
  *             y += leading             # <<<<<<<<<<<<<<
@@ -7058,7 +7342,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_y = (__pyx_v_y + __pyx_v_leading);
 
-      /* "renpy/text/textsupport.pyx":512
+      /* "renpy/text/textsupport.pyx":539
  *             y += leading
  * 
  *             sol = pos             # <<<<<<<<<<<<<<
@@ -7067,7 +7351,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_sol = __pyx_v_pos;
 
-      /* "renpy/text/textsupport.pyx":514
+      /* "renpy/text/textsupport.pyx":541
  *             sol = pos
  * 
  *             ascent = 0             # <<<<<<<<<<<<<<
@@ -7076,7 +7360,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_ascent = 0;
 
-      /* "renpy/text/textsupport.pyx":515
+      /* "renpy/text/textsupport.pyx":542
  * 
  *             ascent = 0
  *             line_spacing = 0             # <<<<<<<<<<<<<<
@@ -7085,18 +7369,18 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       __pyx_v_line_spacing = 0;
 
-      /* "renpy/text/textsupport.pyx":517
+      /* "renpy/text/textsupport.pyx":544
  *             line_spacing = 0
  * 
  *             if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
  *                 sol += 1
  *                 pos += 1
  */
-      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 517; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
       __pyx_t_2 = ((__pyx_v_g->split == __pyx_e_5renpy_4text_11textsupport_SPLIT_INSTEAD) != 0);
       if (__pyx_t_2) {
 
-        /* "renpy/text/textsupport.pyx":518
+        /* "renpy/text/textsupport.pyx":545
  * 
  *             if g.split == SPLIT_INSTEAD:
  *                 sol += 1             # <<<<<<<<<<<<<<
@@ -7105,7 +7389,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
         __pyx_v_sol = (__pyx_v_sol + 1);
 
-        /* "renpy/text/textsupport.pyx":519
+        /* "renpy/text/textsupport.pyx":546
  *             if g.split == SPLIT_INSTEAD:
  *                 sol += 1
  *                 pos += 1             # <<<<<<<<<<<<<<
@@ -7114,7 +7398,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
         __pyx_v_pos = (__pyx_v_pos + 1);
 
-        /* "renpy/text/textsupport.pyx":521
+        /* "renpy/text/textsupport.pyx":548
  *                 pos += 1
  * 
  *                 if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -7124,7 +7408,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
         __pyx_t_2 = ((__pyx_v_pos >= __pyx_v_len_glyphs) != 0);
         if (__pyx_t_2) {
 
-          /* "renpy/text/textsupport.pyx":522
+          /* "renpy/text/textsupport.pyx":549
  * 
  *                 if pos >= len_glyphs:
  *                     break             # <<<<<<<<<<<<<<
@@ -7133,7 +7417,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
           goto __pyx_L5_break;
 
-          /* "renpy/text/textsupport.pyx":521
+          /* "renpy/text/textsupport.pyx":548
  *                 pos += 1
  * 
  *                 if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -7142,7 +7426,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
         }
 
-        /* "renpy/text/textsupport.pyx":524
+        /* "renpy/text/textsupport.pyx":551
  *                     break
  *                 else:
  *                     continue             # <<<<<<<<<<<<<<
@@ -7153,7 +7437,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
           goto __pyx_L4_continue;
         }
 
-        /* "renpy/text/textsupport.pyx":517
+        /* "renpy/text/textsupport.pyx":544
  *             line_spacing = 0
  * 
  *             if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
@@ -7162,7 +7446,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       }
 
-      /* "renpy/text/textsupport.pyx":488
+      /* "renpy/text/textsupport.pyx":515
  *             end_line = (g.split != SPLIT_NONE)
  * 
  *         if end_line:             # <<<<<<<<<<<<<<
@@ -7171,7 +7455,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
     }
 
-    /* "renpy/text/textsupport.pyx":526
+    /* "renpy/text/textsupport.pyx":553
  *                     continue
  * 
  *         if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -7181,7 +7465,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
     __pyx_t_2 = ((__pyx_v_pos >= __pyx_v_len_glyphs) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":527
+      /* "renpy/text/textsupport.pyx":554
  * 
  *         if pos >= len_glyphs:
  *             break             # <<<<<<<<<<<<<<
@@ -7190,7 +7474,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
       goto __pyx_L5_break;
 
-      /* "renpy/text/textsupport.pyx":526
+      /* "renpy/text/textsupport.pyx":553
  *                     continue
  * 
  *         if pos >= len_glyphs:             # <<<<<<<<<<<<<<
@@ -7199,29 +7483,29 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
     }
 
-    /* "renpy/text/textsupport.pyx":529
+    /* "renpy/text/textsupport.pyx":556
  *             break
  * 
  *         if g.ascent > ascent:             # <<<<<<<<<<<<<<
  *             ascent = g.ascent
  * 
  */
-    if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+    if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 556; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
     __pyx_t_2 = ((__pyx_v_g->ascent > __pyx_v_ascent) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":530
+      /* "renpy/text/textsupport.pyx":557
  * 
  *         if g.ascent > ascent:
  *             ascent = g.ascent             # <<<<<<<<<<<<<<
  * 
  *         if g.line_spacing > line_spacing:
  */
-      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 557; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
       __pyx_t_10 = __pyx_v_g->ascent;
       __pyx_v_ascent = __pyx_t_10;
 
-      /* "renpy/text/textsupport.pyx":529
+      /* "renpy/text/textsupport.pyx":556
  *             break
  * 
  *         if g.ascent > ascent:             # <<<<<<<<<<<<<<
@@ -7230,29 +7514,29 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
     }
 
-    /* "renpy/text/textsupport.pyx":532
+    /* "renpy/text/textsupport.pyx":559
  *             ascent = g.ascent
  * 
  *         if g.line_spacing > line_spacing:             # <<<<<<<<<<<<<<
  *             line_spacing = g.line_spacing
  * 
  */
-    if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+    if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
     __pyx_t_2 = ((__pyx_v_g->line_spacing > __pyx_v_line_spacing) != 0);
     if (__pyx_t_2) {
 
-      /* "renpy/text/textsupport.pyx":533
+      /* "renpy/text/textsupport.pyx":560
  * 
  *         if g.line_spacing > line_spacing:
  *             line_spacing = g.line_spacing             # <<<<<<<<<<<<<<
  * 
  *         pos += 1
  */
-      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 533; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+      if (unlikely(!__pyx_v_g)) { __Pyx_RaiseUnboundLocalError("g"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
       __pyx_t_10 = __pyx_v_g->line_spacing;
       __pyx_v_line_spacing = __pyx_t_10;
 
-      /* "renpy/text/textsupport.pyx":532
+      /* "renpy/text/textsupport.pyx":559
  *             ascent = g.ascent
  * 
  *         if g.line_spacing > line_spacing:             # <<<<<<<<<<<<<<
@@ -7261,7 +7545,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
     }
 
-    /* "renpy/text/textsupport.pyx":535
+    /* "renpy/text/textsupport.pyx":562
  *             line_spacing = g.line_spacing
  * 
  *         pos += 1             # <<<<<<<<<<<<<<
@@ -7273,19 +7557,19 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
   }
   __pyx_L5_break:;
 
-  /* "renpy/text/textsupport.pyx":538
+  /* "renpy/text/textsupport.pyx":565
  * 
  * 
  *     rv[-1].eop = True             # <<<<<<<<<<<<<<
  *     return rv, y - leading
  * 
  */
-  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_rv, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_rv, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 565; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
   __Pyx_GOTREF(__pyx_t_3);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_t_3, __pyx_n_s_eop, Py_True) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_PyObject_SetAttrStr(__pyx_t_3, __pyx_n_s_eop, Py_True) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 565; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/text/textsupport.pyx":539
+  /* "renpy/text/textsupport.pyx":566
  * 
  *     rv[-1].eop = True
  *     return rv, y - leading             # <<<<<<<<<<<<<<
@@ -7293,9 +7577,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  * def kerning(list glyphs, float amount):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_y - __pyx_v_leading)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 539; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_y - __pyx_v_leading)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 566; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 539; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 566; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_INCREF(__pyx_v_rv);
   __Pyx_GIVEREF(__pyx_v_rv);
@@ -7307,7 +7591,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
   __pyx_t_8 = 0;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":453
+  /* "renpy/text/textsupport.pyx":480
  *     return maxx
  * 
  * def place_vertical(list glyphs, int y, int spacing, int leading):             # <<<<<<<<<<<<<<
@@ -7333,7 +7617,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":541
+/* "renpy/text/textsupport.pyx":568
  *     return rv, y - leading
  * 
  * def kerning(list glyphs, float amount):             # <<<<<<<<<<<<<<
@@ -7342,9 +7626,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_16place_vertical(CYTHON_UNU
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_19kerning(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_19kerning = {"kerning", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_19kerning, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_19kerning(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_21kerning(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_21kerning = {"kerning", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_21kerning, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_21kerning(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_glyphs = 0;
   float __pyx_v_amount;
   int __pyx_lineno = 0;
@@ -7373,11 +7657,11 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_19kerning(PyObject *__pyx_s
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_amount)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("kerning", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("kerning", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "kerning") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "kerning") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -7386,18 +7670,18 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_19kerning(PyObject *__pyx_s
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
     __pyx_v_glyphs = ((PyObject*)values[0]);
-    __pyx_v_amount = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_amount == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_amount = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_amount == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("kerning", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("kerning", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.kerning", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_18kerning(__pyx_self, __pyx_v_glyphs, __pyx_v_amount);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_20kerning(__pyx_self, __pyx_v_glyphs, __pyx_v_amount);
 
   /* function exit code */
   goto __pyx_L0;
@@ -7408,7 +7692,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_19kerning(PyObject *__pyx_s
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_amount) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_20kerning(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, float __pyx_v_amount) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -7420,7 +7704,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("kerning", 0);
 
-  /* "renpy/text/textsupport.pyx":544
+  /* "renpy/text/textsupport.pyx":571
  *     cdef Glyph g
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -7429,22 +7713,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":545
+    /* "renpy/text/textsupport.pyx":572
  * 
  *     for g in glyphs:
  *         g.advance += amount             # <<<<<<<<<<<<<<
@@ -7453,7 +7737,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
  */
     __pyx_v_g->advance = (__pyx_v_g->advance + __pyx_v_amount);
 
-    /* "renpy/text/textsupport.pyx":544
+    /* "renpy/text/textsupport.pyx":571
  *     cdef Glyph g
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -7463,7 +7747,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":541
+  /* "renpy/text/textsupport.pyx":568
  *     return rv, y - leading
  * 
  * def kerning(list glyphs, float amount):             # <<<<<<<<<<<<<<
@@ -7486,7 +7770,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":548
+/* "renpy/text/textsupport.pyx":575
  * 
  * 
  * def assign_times(float t, float gps, list glyphs):             # <<<<<<<<<<<<<<
@@ -7495,10 +7779,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_18kerning(CYTHON_UNUSED PyO
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_21assign_times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_20assign_times[] = "\n    Assign a display time to each glyph.\n\n    `t`\n        The start time of the first glyph.\n\n    `gps`\n        The number of glyphs per second to show.\n\n    `glyphs`\n        A list of glyphs to apply this to.\n\n    Returns the time of the first glyph in the next block.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_21assign_times = {"assign_times", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_21assign_times, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_20assign_times};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_21assign_times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_23assign_times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_22assign_times[] = "\n    Assign a display time to each glyph.\n\n    `t`\n        The start time of the first glyph.\n\n    `gps`\n        The number of glyphs per second to show.\n\n    `glyphs`\n        A list of glyphs to apply this to.\n\n    Returns the time of the first glyph in the next block.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_23assign_times = {"assign_times", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_23assign_times, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_22assign_times};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_23assign_times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   float __pyx_v_t;
   float __pyx_v_gps;
   PyObject *__pyx_v_glyphs = 0;
@@ -7529,16 +7813,16 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_21assign_times(PyObject *__
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_gps)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_glyphs)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "assign_times") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "assign_times") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
       goto __pyx_L5_argtuple_error;
@@ -7547,20 +7831,20 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_21assign_times(PyObject *__
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
       values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
     }
-    __pyx_v_t = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_t == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_gps = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_gps == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_t = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_t == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_gps = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_gps == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_glyphs = ((PyObject*)values[2]);
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("assign_times", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.assign_times", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_20assign_times(__pyx_self, __pyx_v_t, __pyx_v_gps, __pyx_v_glyphs);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_22assign_times(__pyx_self, __pyx_v_t, __pyx_v_gps, __pyx_v_glyphs);
 
   /* function exit code */
   goto __pyx_L0;
@@ -7571,7 +7855,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_21assign_times(PyObject *__
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_t, float __pyx_v_gps, PyObject *__pyx_v_glyphs) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_22assign_times(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_t, float __pyx_v_gps, PyObject *__pyx_v_glyphs) {
   float __pyx_v_tpg;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_r = NULL;
@@ -7585,7 +7869,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("assign_times", 0);
 
-  /* "renpy/text/textsupport.pyx":567
+  /* "renpy/text/textsupport.pyx":594
  *     cdef Glyph g
  * 
  *     if gps == 0:             # <<<<<<<<<<<<<<
@@ -7595,7 +7879,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
   __pyx_t_1 = ((__pyx_v_gps == 0.0) != 0);
   if (__pyx_t_1) {
 
-    /* "renpy/text/textsupport.pyx":568
+    /* "renpy/text/textsupport.pyx":595
  * 
  *     if gps == 0:
  *         tpg = 0.0             # <<<<<<<<<<<<<<
@@ -7604,7 +7888,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
     __pyx_v_tpg = 0.0;
 
-    /* "renpy/text/textsupport.pyx":567
+    /* "renpy/text/textsupport.pyx":594
  *     cdef Glyph g
  * 
  *     if gps == 0:             # <<<<<<<<<<<<<<
@@ -7614,7 +7898,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
     goto __pyx_L3;
   }
 
-  /* "renpy/text/textsupport.pyx":570
+  /* "renpy/text/textsupport.pyx":597
  *         tpg = 0.0
  *     else:
  *         tpg = 1.0 / gps             # <<<<<<<<<<<<<<
@@ -7624,13 +7908,13 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
   /*else*/ {
     if (unlikely(__pyx_v_gps == 0)) {
       PyErr_SetString(PyExc_ZeroDivisionError, "float division");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 570; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 597; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_v_tpg = (1.0 / __pyx_v_gps);
   }
   __pyx_L3:;
 
-  /* "renpy/text/textsupport.pyx":572
+  /* "renpy/text/textsupport.pyx":599
  *         tpg = 1.0 / gps
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -7639,22 +7923,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 599; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_2 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
   for (;;) {
     if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 599; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 599; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     #endif
-    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 599; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_4));
     __pyx_t_4 = 0;
 
-    /* "renpy/text/textsupport.pyx":574
+    /* "renpy/text/textsupport.pyx":601
  *     for g in glyphs:
  * 
  *         if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -7664,7 +7948,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
     __pyx_t_1 = ((__pyx_v_g->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
     if (__pyx_t_1) {
 
-      /* "renpy/text/textsupport.pyx":575
+      /* "renpy/text/textsupport.pyx":602
  * 
  *         if g.ruby == RUBY_TOP:
  *             g.time = t             # <<<<<<<<<<<<<<
@@ -7673,7 +7957,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
       __pyx_v_g->time = __pyx_v_t;
 
-      /* "renpy/text/textsupport.pyx":576
+      /* "renpy/text/textsupport.pyx":603
  *         if g.ruby == RUBY_TOP:
  *             g.time = t
  *             continue             # <<<<<<<<<<<<<<
@@ -7682,7 +7966,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
       goto __pyx_L4_continue;
 
-      /* "renpy/text/textsupport.pyx":574
+      /* "renpy/text/textsupport.pyx":601
  *     for g in glyphs:
  * 
  *         if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -7691,7 +7975,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
     }
 
-    /* "renpy/text/textsupport.pyx":578
+    /* "renpy/text/textsupport.pyx":605
  *             continue
  * 
  *         t += tpg             # <<<<<<<<<<<<<<
@@ -7700,7 +7984,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
     __pyx_v_t = (__pyx_v_t + __pyx_v_tpg);
 
-    /* "renpy/text/textsupport.pyx":579
+    /* "renpy/text/textsupport.pyx":606
  * 
  *         t += tpg
  *         g.time = t             # <<<<<<<<<<<<<<
@@ -7709,7 +7993,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
     __pyx_v_g->time = __pyx_v_t;
 
-    /* "renpy/text/textsupport.pyx":572
+    /* "renpy/text/textsupport.pyx":599
  *         tpg = 1.0 / gps
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -7720,7 +8004,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
   }
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":581
+  /* "renpy/text/textsupport.pyx":608
  *         g.time = t
  * 
  *     return t             # <<<<<<<<<<<<<<
@@ -7728,13 +8012,13 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 581; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 608; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":548
+  /* "renpy/text/textsupport.pyx":575
  * 
  * 
  * def assign_times(float t, float gps, list glyphs):             # <<<<<<<<<<<<<<
@@ -7755,7 +8039,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":584
+/* "renpy/text/textsupport.pyx":611
  * 
  * 
  * def max_times(list l):             # <<<<<<<<<<<<<<
@@ -7764,18 +8048,18 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_20assign_times(CYTHON_UNUSE
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_23max_times(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_22max_times[] = "\n    Set the max_time filed on each line.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_23max_times = {"max_times", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_23max_times, METH_O, __pyx_doc_5renpy_4text_11textsupport_22max_times};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_23max_times(PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_25max_times(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_24max_times[] = "\n    Set the max_time filed on each line.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_25max_times = {"max_times", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_25max_times, METH_O, __pyx_doc_5renpy_4text_11textsupport_24max_times};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_25max_times(PyObject *__pyx_self, PyObject *__pyx_v_l) {
   CYTHON_UNUSED int __pyx_lineno = 0;
   CYTHON_UNUSED const char *__pyx_filename = NULL;
   CYTHON_UNUSED int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("max_times (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 584; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_22max_times(__pyx_self, ((PyObject*)__pyx_v_l));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 611; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_24max_times(__pyx_self, ((PyObject*)__pyx_v_l));
 
   /* function exit code */
   goto __pyx_L0;
@@ -7786,7 +8070,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_23max_times(PyObject *__pyx
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_24max_times(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
   struct __pyx_obj_5renpy_4text_11textsupport_Line *__pyx_v_line = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   float __pyx_v_max_time;
@@ -7804,7 +8088,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("max_times", 0);
 
-  /* "renpy/text/textsupport.pyx":593
+  /* "renpy/text/textsupport.pyx":620
  *     cdef float max_time
  * 
  *     max_time = 0             # <<<<<<<<<<<<<<
@@ -7813,7 +8097,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
   __pyx_v_max_time = 0.0;
 
-  /* "renpy/text/textsupport.pyx":595
+  /* "renpy/text/textsupport.pyx":622
  *     max_time = 0
  * 
  *     for line in l:             # <<<<<<<<<<<<<<
@@ -7822,22 +8106,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
   if (unlikely(__pyx_v_l == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 622; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_l; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 622; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 622; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 622; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_line, ((struct __pyx_obj_5renpy_4text_11textsupport_Line *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":596
+    /* "renpy/text/textsupport.pyx":623
  * 
  *     for line in l:
  *         for g in line.glyphs:             # <<<<<<<<<<<<<<
@@ -7846,22 +8130,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
     if (unlikely(__pyx_v_line->glyphs == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 596; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_3 = __pyx_v_line->glyphs; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
     for (;;) {
       if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 596; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 596; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       #endif
-      if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 596; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_5));
       __pyx_t_5 = 0;
 
-      /* "renpy/text/textsupport.pyx":597
+      /* "renpy/text/textsupport.pyx":624
  *     for line in l:
  *         for g in line.glyphs:
  *             if g.time > max_time:             # <<<<<<<<<<<<<<
@@ -7871,7 +8155,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
       __pyx_t_6 = ((__pyx_v_g->time > __pyx_v_max_time) != 0);
       if (__pyx_t_6) {
 
-        /* "renpy/text/textsupport.pyx":598
+        /* "renpy/text/textsupport.pyx":625
  *         for g in line.glyphs:
  *             if g.time > max_time:
  *                 max_time = g.time             # <<<<<<<<<<<<<<
@@ -7881,7 +8165,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
         __pyx_t_7 = __pyx_v_g->time;
         __pyx_v_max_time = __pyx_t_7;
 
-        /* "renpy/text/textsupport.pyx":597
+        /* "renpy/text/textsupport.pyx":624
  *     for line in l:
  *         for g in line.glyphs:
  *             if g.time > max_time:             # <<<<<<<<<<<<<<
@@ -7890,7 +8174,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
       }
 
-      /* "renpy/text/textsupport.pyx":596
+      /* "renpy/text/textsupport.pyx":623
  * 
  *     for line in l:
  *         for g in line.glyphs:             # <<<<<<<<<<<<<<
@@ -7900,7 +8184,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
     }
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":600
+    /* "renpy/text/textsupport.pyx":627
  *                 max_time = g.time
  * 
  *         line.max_time = max_time             # <<<<<<<<<<<<<<
@@ -7909,7 +8193,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
     __pyx_v_line->max_time = __pyx_v_max_time;
 
-    /* "renpy/text/textsupport.pyx":595
+    /* "renpy/text/textsupport.pyx":622
  *     max_time = 0
  * 
  *     for line in l:             # <<<<<<<<<<<<<<
@@ -7919,7 +8203,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":602
+  /* "renpy/text/textsupport.pyx":629
  *         line.max_time = max_time
  * 
  *     return max_time             # <<<<<<<<<<<<<<
@@ -7927,13 +8211,13 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_max_time); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 602; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_max_time); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 629; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":584
+  /* "renpy/text/textsupport.pyx":611
  * 
  * 
  * def max_times(list l):             # <<<<<<<<<<<<<<
@@ -7956,7 +8240,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":605
+/* "renpy/text/textsupport.pyx":632
  * 
  * 
  * def hyperlink_areas(list l):             # <<<<<<<<<<<<<<
@@ -7965,18 +8249,18 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_22max_times(CYTHON_UNUSED P
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_25hyperlink_areas(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_24hyperlink_areas[] = "\n    Returns a list of (hyperlink, x, y, w, h) tuples, where each entry in\n    the rectangle represents a contiguous portion of a hyperlink on the\n    given line.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_25hyperlink_areas = {"hyperlink_areas", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_25hyperlink_areas, METH_O, __pyx_doc_5renpy_4text_11textsupport_24hyperlink_areas};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_25hyperlink_areas(PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_27hyperlink_areas(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_26hyperlink_areas[] = "\n    Returns a list of (hyperlink, x, y, w, h) tuples, where each entry in\n    the rectangle represents a contiguous portion of a hyperlink on the\n    given line.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_27hyperlink_areas = {"hyperlink_areas", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_27hyperlink_areas, METH_O, __pyx_doc_5renpy_4text_11textsupport_26hyperlink_areas};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_27hyperlink_areas(PyObject *__pyx_self, PyObject *__pyx_v_l) {
   CYTHON_UNUSED int __pyx_lineno = 0;
   CYTHON_UNUSED const char *__pyx_filename = NULL;
   CYTHON_UNUSED int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("hyperlink_areas (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 605; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(__pyx_self, ((PyObject*)__pyx_v_l));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 632; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_26hyperlink_areas(__pyx_self, ((PyObject*)__pyx_v_l));
 
   /* function exit code */
   goto __pyx_L0;
@@ -7987,7 +8271,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_25hyperlink_areas(PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_26hyperlink_areas(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
   struct __pyx_obj_5renpy_4text_11textsupport_Line *__pyx_v_line = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_v_gl = 0;
@@ -8017,19 +8301,19 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("hyperlink_areas", 0);
 
-  /* "renpy/text/textsupport.pyx":623
+  /* "renpy/text/textsupport.pyx":650
  *     cdef int hyperlink
  * 
  *     rv = [ ]             # <<<<<<<<<<<<<<
  * 
  *     for line in l:
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 650; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_rv = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":625
+  /* "renpy/text/textsupport.pyx":652
  *     rv = [ ]
  * 
  *     for line in l:             # <<<<<<<<<<<<<<
@@ -8038,22 +8322,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
   if (unlikely(__pyx_v_l == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 625; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_l; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 625; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 625; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 625; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_line, ((struct __pyx_obj_5renpy_4text_11textsupport_Line *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":626
+    /* "renpy/text/textsupport.pyx":653
  * 
  *     for line in l:
  *         gl = line.glyphs             # <<<<<<<<<<<<<<
@@ -8065,7 +8349,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
     __Pyx_XDECREF_SET(__pyx_v_gl, ((PyObject*)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":627
+    /* "renpy/text/textsupport.pyx":654
  *     for line in l:
  *         gl = line.glyphs
  *         len_gl = len(gl)             # <<<<<<<<<<<<<<
@@ -8074,12 +8358,12 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     if (unlikely(__pyx_v_gl == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 627; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 654; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_4 = PyList_GET_SIZE(__pyx_v_gl); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 627; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyList_GET_SIZE(__pyx_v_gl); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 654; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_len_gl = __pyx_t_4;
 
-    /* "renpy/text/textsupport.pyx":629
+    /* "renpy/text/textsupport.pyx":656
  *         len_gl = len(gl)
  * 
  *         hyperlink = 0             # <<<<<<<<<<<<<<
@@ -8088,7 +8372,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     __pyx_v_hyperlink = 0;
 
-    /* "renpy/text/textsupport.pyx":630
+    /* "renpy/text/textsupport.pyx":657
  * 
  *         hyperlink = 0
  *         max_x = 0             # <<<<<<<<<<<<<<
@@ -8097,7 +8381,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     __pyx_v_max_x = 0;
 
-    /* "renpy/text/textsupport.pyx":631
+    /* "renpy/text/textsupport.pyx":658
  *         hyperlink = 0
  *         max_x = 0
  *         min_x = 1000000             # <<<<<<<<<<<<<<
@@ -8106,7 +8390,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     __pyx_v_min_x = 0xF4240;
 
-    /* "renpy/text/textsupport.pyx":632
+    /* "renpy/text/textsupport.pyx":659
  *         max_x = 0
  *         min_x = 1000000
  *         pos = 0             # <<<<<<<<<<<<<<
@@ -8115,7 +8399,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     __pyx_v_pos = 0;
 
-    /* "renpy/text/textsupport.pyx":634
+    /* "renpy/text/textsupport.pyx":661
  *         pos = 0
  * 
  *         while pos < len_gl:             # <<<<<<<<<<<<<<
@@ -8126,7 +8410,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_t_5 = ((__pyx_v_pos < __pyx_v_len_gl) != 0);
       if (!__pyx_t_5) break;
 
-      /* "renpy/text/textsupport.pyx":636
+      /* "renpy/text/textsupport.pyx":663
  *         while pos < len_gl:
  * 
  *             g = gl[pos]             # <<<<<<<<<<<<<<
@@ -8135,15 +8419,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
       if (unlikely(__pyx_v_gl == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 636; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 663; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_gl, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 636; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_gl, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 663; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
       __Pyx_GOTREF(__pyx_t_3);
-      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 636; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 663; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
       __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":638
+      /* "renpy/text/textsupport.pyx":665
  *             g = gl[pos]
  * 
  *             if (hyperlink and g.hyperlink != hyperlink):             # <<<<<<<<<<<<<<
@@ -8161,24 +8445,24 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_L8_bool_binop_done:;
       if (__pyx_t_5) {
 
-        /* "renpy/text/textsupport.pyx":639
+        /* "renpy/text/textsupport.pyx":666
  * 
  *             if (hyperlink and g.hyperlink != hyperlink):
  *                 rv.append((hyperlink, min_x, line.y, max_x - min_x, line.height))             # <<<<<<<<<<<<<<
  *                 hyperlink = 0
  *                 max_x = 0
  */
-        __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_hyperlink); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_hyperlink); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_min_x); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_min_x); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = __Pyx_PyInt_From_short(__pyx_v_line->y); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = __Pyx_PyInt_From_short(__pyx_v_line->y); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_9 = __Pyx_PyInt_From_int((__pyx_v_max_x - __pyx_v_min_x)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_9 = __Pyx_PyInt_From_int((__pyx_v_max_x - __pyx_v_min_x)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_9);
-        __pyx_t_10 = __Pyx_PyInt_From_short(__pyx_v_line->height); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_10 = __Pyx_PyInt_From_short(__pyx_v_line->height); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_10);
-        __pyx_t_11 = PyTuple_New(5); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_11 = PyTuple_New(5); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_11);
         __Pyx_GIVEREF(__pyx_t_3);
         PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_3);
@@ -8195,10 +8479,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
         __pyx_t_8 = 0;
         __pyx_t_9 = 0;
         __pyx_t_10 = 0;
-        __pyx_t_12 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_t_11); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 639; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_12 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_t_11); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 666; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
 
-        /* "renpy/text/textsupport.pyx":640
+        /* "renpy/text/textsupport.pyx":667
  *             if (hyperlink and g.hyperlink != hyperlink):
  *                 rv.append((hyperlink, min_x, line.y, max_x - min_x, line.height))
  *                 hyperlink = 0             # <<<<<<<<<<<<<<
@@ -8207,7 +8491,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
         __pyx_v_hyperlink = 0;
 
-        /* "renpy/text/textsupport.pyx":641
+        /* "renpy/text/textsupport.pyx":668
  *                 rv.append((hyperlink, min_x, line.y, max_x - min_x, line.height))
  *                 hyperlink = 0
  *                 max_x = 0             # <<<<<<<<<<<<<<
@@ -8216,7 +8500,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
         __pyx_v_max_x = 0;
 
-        /* "renpy/text/textsupport.pyx":642
+        /* "renpy/text/textsupport.pyx":669
  *                 hyperlink = 0
  *                 max_x = 0
  *                 min_x = 1000000             # <<<<<<<<<<<<<<
@@ -8225,7 +8509,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
         __pyx_v_min_x = 0xF4240;
 
-        /* "renpy/text/textsupport.pyx":638
+        /* "renpy/text/textsupport.pyx":665
  *             g = gl[pos]
  * 
  *             if (hyperlink and g.hyperlink != hyperlink):             # <<<<<<<<<<<<<<
@@ -8234,7 +8518,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
       }
 
-      /* "renpy/text/textsupport.pyx":644
+      /* "renpy/text/textsupport.pyx":671
  *                 min_x = 1000000
  * 
  *             hyperlink = g.hyperlink             # <<<<<<<<<<<<<<
@@ -8244,7 +8528,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_t_13 = __pyx_v_g->hyperlink;
       __pyx_v_hyperlink = __pyx_t_13;
 
-      /* "renpy/text/textsupport.pyx":646
+      /* "renpy/text/textsupport.pyx":673
  *             hyperlink = g.hyperlink
  * 
  *             if hyperlink:             # <<<<<<<<<<<<<<
@@ -8254,7 +8538,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_t_5 = (__pyx_v_hyperlink != 0);
       if (__pyx_t_5) {
 
-        /* "renpy/text/textsupport.pyx":647
+        /* "renpy/text/textsupport.pyx":674
  * 
  *             if hyperlink:
  *                 if g.x < min_x:             # <<<<<<<<<<<<<<
@@ -8264,7 +8548,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
         __pyx_t_5 = ((__pyx_v_g->x < __pyx_v_min_x) != 0);
         if (__pyx_t_5) {
 
-          /* "renpy/text/textsupport.pyx":648
+          /* "renpy/text/textsupport.pyx":675
  *             if hyperlink:
  *                 if g.x < min_x:
  *                     min_x = g.x             # <<<<<<<<<<<<<<
@@ -8274,7 +8558,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
           __pyx_t_13 = __pyx_v_g->x;
           __pyx_v_min_x = __pyx_t_13;
 
-          /* "renpy/text/textsupport.pyx":647
+          /* "renpy/text/textsupport.pyx":674
  * 
  *             if hyperlink:
  *                 if g.x < min_x:             # <<<<<<<<<<<<<<
@@ -8283,7 +8567,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
         }
 
-        /* "renpy/text/textsupport.pyx":650
+        /* "renpy/text/textsupport.pyx":677
  *                     min_x = g.x
  * 
  *                 if g.x + g.width > max_x:             # <<<<<<<<<<<<<<
@@ -8293,7 +8577,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
         __pyx_t_5 = (((__pyx_v_g->x + __pyx_v_g->width) > __pyx_v_max_x) != 0);
         if (__pyx_t_5) {
 
-          /* "renpy/text/textsupport.pyx":651
+          /* "renpy/text/textsupport.pyx":678
  * 
  *                 if g.x + g.width > max_x:
  *                     max_x = g.x + <int> g.width             # <<<<<<<<<<<<<<
@@ -8302,7 +8586,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
           __pyx_v_max_x = (__pyx_v_g->x + ((int)__pyx_v_g->width));
 
-          /* "renpy/text/textsupport.pyx":650
+          /* "renpy/text/textsupport.pyx":677
  *                     min_x = g.x
  * 
  *                 if g.x + g.width > max_x:             # <<<<<<<<<<<<<<
@@ -8311,7 +8595,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
         }
 
-        /* "renpy/text/textsupport.pyx":646
+        /* "renpy/text/textsupport.pyx":673
  *             hyperlink = g.hyperlink
  * 
  *             if hyperlink:             # <<<<<<<<<<<<<<
@@ -8320,7 +8604,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
       }
 
-      /* "renpy/text/textsupport.pyx":653
+      /* "renpy/text/textsupport.pyx":680
  *                     max_x = g.x + <int> g.width
  * 
  *             pos += 1             # <<<<<<<<<<<<<<
@@ -8330,7 +8614,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_v_pos = (__pyx_v_pos + 1);
     }
 
-    /* "renpy/text/textsupport.pyx":655
+    /* "renpy/text/textsupport.pyx":682
  *             pos += 1
  * 
  *         if hyperlink:             # <<<<<<<<<<<<<<
@@ -8340,24 +8624,24 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
     __pyx_t_5 = (__pyx_v_hyperlink != 0);
     if (__pyx_t_5) {
 
-      /* "renpy/text/textsupport.pyx":656
+      /* "renpy/text/textsupport.pyx":683
  * 
  *         if hyperlink:
  *             rv.append((hyperlink, min_x, line.y, max_x - min_x, line.height))             # <<<<<<<<<<<<<<
  * 
  *     return rv
  */
-      __pyx_t_11 = __Pyx_PyInt_From_int(__pyx_v_hyperlink); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = __Pyx_PyInt_From_int(__pyx_v_hyperlink); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_11);
-      __pyx_t_10 = __Pyx_PyInt_From_int(__pyx_v_min_x); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = __Pyx_PyInt_From_int(__pyx_v_min_x); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_10);
-      __pyx_t_9 = __Pyx_PyInt_From_short(__pyx_v_line->y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = __Pyx_PyInt_From_short(__pyx_v_line->y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_8 = __Pyx_PyInt_From_int((__pyx_v_max_x - __pyx_v_min_x)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = __Pyx_PyInt_From_int((__pyx_v_max_x - __pyx_v_min_x)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_7 = __Pyx_PyInt_From_short(__pyx_v_line->height); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = __Pyx_PyInt_From_short(__pyx_v_line->height); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_3 = PyTuple_New(5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyTuple_New(5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_GIVEREF(__pyx_t_11);
       PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_11);
@@ -8374,10 +8658,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
       __pyx_t_9 = 0;
       __pyx_t_8 = 0;
       __pyx_t_7 = 0;
-      __pyx_t_12 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_t_3); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 656; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_12 = __Pyx_PyList_Append(__pyx_v_rv, __pyx_t_3); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 683; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":655
+      /* "renpy/text/textsupport.pyx":682
  *             pos += 1
  * 
  *         if hyperlink:             # <<<<<<<<<<<<<<
@@ -8386,7 +8670,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
     }
 
-    /* "renpy/text/textsupport.pyx":625
+    /* "renpy/text/textsupport.pyx":652
  *     rv = [ ]
  * 
  *     for line in l:             # <<<<<<<<<<<<<<
@@ -8396,7 +8680,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":658
+  /* "renpy/text/textsupport.pyx":685
  *             rv.append((hyperlink, min_x, line.y, max_x - min_x, line.height))
  * 
  *     return rv             # <<<<<<<<<<<<<<
@@ -8408,7 +8692,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
   __pyx_r = __pyx_v_rv;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":605
+  /* "renpy/text/textsupport.pyx":632
  * 
  * 
  * def hyperlink_areas(list l):             # <<<<<<<<<<<<<<
@@ -8437,7 +8721,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":661
+/* "renpy/text/textsupport.pyx":688
  * 
  * 
  * def mark_ruby_top(list l):             # <<<<<<<<<<<<<<
@@ -8446,17 +8730,17 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_24hyperlink_areas(CYTHON_UN
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_27mark_ruby_top(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_27mark_ruby_top = {"mark_ruby_top", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_27mark_ruby_top, METH_O, 0};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_27mark_ruby_top(PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_top(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_29mark_ruby_top = {"mark_ruby_top", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_top, METH_O, 0};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_top(PyObject *__pyx_self, PyObject *__pyx_v_l) {
   CYTHON_UNUSED int __pyx_lineno = 0;
   CYTHON_UNUSED const char *__pyx_filename = NULL;
   CYTHON_UNUSED int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("mark_ruby_top (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 661; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(__pyx_self, ((PyObject*)__pyx_v_l));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 688; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_28mark_ruby_top(__pyx_self, ((PyObject*)__pyx_v_l));
 
   /* function exit code */
   goto __pyx_L0;
@@ -8467,7 +8751,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_27mark_ruby_top(PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_top(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -8479,7 +8763,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("mark_ruby_top", 0);
 
-  /* "renpy/text/textsupport.pyx":665
+  /* "renpy/text/textsupport.pyx":692
  *     cdef Glyph g
  * 
  *     for g in l:             # <<<<<<<<<<<<<<
@@ -8488,22 +8772,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
  */
   if (unlikely(__pyx_v_l == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 665; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 692; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_l; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 665; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 692; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 665; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 692; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 665; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 692; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":666
+    /* "renpy/text/textsupport.pyx":693
  * 
  *     for g in l:
  *         g.ruby = RUBY_TOP             # <<<<<<<<<<<<<<
@@ -8512,7 +8796,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
  */
     __pyx_v_g->ruby = __pyx_e_5renpy_4text_11textsupport_RUBY_TOP;
 
-    /* "renpy/text/textsupport.pyx":665
+    /* "renpy/text/textsupport.pyx":692
  *     cdef Glyph g
  * 
  *     for g in l:             # <<<<<<<<<<<<<<
@@ -8522,7 +8806,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":661
+  /* "renpy/text/textsupport.pyx":688
  * 
  * 
  * def mark_ruby_top(list l):             # <<<<<<<<<<<<<<
@@ -8545,7 +8829,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":668
+/* "renpy/text/textsupport.pyx":695
  *         g.ruby = RUBY_TOP
  * 
  * def mark_ruby_bottom(list l):             # <<<<<<<<<<<<<<
@@ -8554,17 +8838,17 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_26mark_ruby_top(CYTHON_UNUS
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_bottom(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_29mark_ruby_bottom = {"mark_ruby_bottom", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_bottom, METH_O, 0};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_bottom(PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_31mark_ruby_bottom(PyObject *__pyx_self, PyObject *__pyx_v_l); /*proto*/
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_31mark_ruby_bottom = {"mark_ruby_bottom", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_31mark_ruby_bottom, METH_O, 0};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_31mark_ruby_bottom(PyObject *__pyx_self, PyObject *__pyx_v_l) {
   CYTHON_UNUSED int __pyx_lineno = 0;
   CYTHON_UNUSED const char *__pyx_filename = NULL;
   CYTHON_UNUSED int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("mark_ruby_bottom (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 668; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(__pyx_self, ((PyObject*)__pyx_v_l));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_l), (&PyList_Type), 1, "l", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 695; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_30mark_ruby_bottom(__pyx_self, ((PyObject*)__pyx_v_l));
 
   /* function exit code */
   goto __pyx_L0;
@@ -8575,7 +8859,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_29mark_ruby_bottom(PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_30mark_ruby_bottom(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_l) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -8587,7 +8871,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("mark_ruby_bottom", 0);
 
-  /* "renpy/text/textsupport.pyx":672
+  /* "renpy/text/textsupport.pyx":699
  *     cdef Glyph g
  * 
  *     for g in l:             # <<<<<<<<<<<<<<
@@ -8596,22 +8880,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
  */
   if (unlikely(__pyx_v_l == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 672; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 699; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_l; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 672; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 699; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 672; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 699; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 672; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 699; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":673
+    /* "renpy/text/textsupport.pyx":700
  * 
  *     for g in l:
  *         g.ruby = RUBY_BOTTOM             # <<<<<<<<<<<<<<
@@ -8620,7 +8904,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
  */
     __pyx_v_g->ruby = __pyx_e_5renpy_4text_11textsupport_RUBY_BOTTOM;
 
-    /* "renpy/text/textsupport.pyx":672
+    /* "renpy/text/textsupport.pyx":699
  *     cdef Glyph g
  * 
  *     for g in l:             # <<<<<<<<<<<<<<
@@ -8630,7 +8914,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":668
+  /* "renpy/text/textsupport.pyx":695
  *         g.ruby = RUBY_TOP
  * 
  * def mark_ruby_bottom(list l):             # <<<<<<<<<<<<<<
@@ -8653,7 +8937,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":676
+/* "renpy/text/textsupport.pyx":703
  * 
  * 
  * def place_ruby(list glyphs, int ruby_offset, int surf_width, int surf_height):             # <<<<<<<<<<<<<<
@@ -8662,9 +8946,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_28mark_ruby_bottom(CYTHON_U
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_31place_ruby(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_31place_ruby = {"place_ruby", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_31place_ruby, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_31place_ruby(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_33place_ruby(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_33place_ruby = {"place_ruby", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_33place_ruby, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_33place_ruby(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_glyphs = 0;
   int __pyx_v_ruby_offset;
   CYTHON_UNUSED int __pyx_v_surf_width;
@@ -8697,21 +8981,21 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_31place_ruby(PyObject *__py
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_ruby_offset)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_surf_width)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_surf_height)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_ruby") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "place_ruby") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -8722,20 +9006,20 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_31place_ruby(PyObject *__py
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
     __pyx_v_glyphs = ((PyObject*)values[0]);
-    __pyx_v_ruby_offset = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_ruby_offset == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_surf_width = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_surf_width == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_surf_height = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_surf_height == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_ruby_offset = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_ruby_offset == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_surf_width = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_surf_width == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_surf_height = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_surf_height == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("place_ruby", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.place_ruby", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_30place_ruby(__pyx_self, __pyx_v_glyphs, __pyx_v_ruby_offset, __pyx_v_surf_width, __pyx_v_surf_height);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_32place_ruby(__pyx_self, __pyx_v_glyphs, __pyx_v_ruby_offset, __pyx_v_surf_width, __pyx_v_surf_height);
 
   /* function exit code */
   goto __pyx_L0;
@@ -8746,7 +9030,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_31place_ruby(PyObject *__py
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_ruby_offset, CYTHON_UNUSED int __pyx_v_surf_width, CYTHON_UNUSED int __pyx_v_surf_height) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_32place_ruby(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, int __pyx_v_ruby_offset, CYTHON_UNUSED int __pyx_v_surf_width, CYTHON_UNUSED int __pyx_v_surf_height) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   enum __pyx_t_5renpy_4text_11textsupport_ruby_t __pyx_v_last_ruby;
   int __pyx_v_len_glyphs;
@@ -8774,7 +9058,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("place_ruby", 0);
 
-  /* "renpy/text/textsupport.pyx":679
+  /* "renpy/text/textsupport.pyx":706
  * 
  *     cdef Glyph g
  *     cdef ruby_t last_ruby = RUBY_NONE             # <<<<<<<<<<<<<<
@@ -8783,7 +9067,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
   __pyx_v_last_ruby = __pyx_e_5renpy_4text_11textsupport_RUBY_NONE;
 
-  /* "renpy/text/textsupport.pyx":680
+  /* "renpy/text/textsupport.pyx":707
  *     cdef Glyph g
  *     cdef ruby_t last_ruby = RUBY_NONE
  *     cdef int len_glyphs = len(glyphs)             # <<<<<<<<<<<<<<
@@ -8792,12 +9076,12 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 680; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 707; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_1 = PyList_GET_SIZE(__pyx_v_glyphs); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 680; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_GET_SIZE(__pyx_v_glyphs); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 707; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_len_glyphs = __pyx_t_1;
 
-  /* "renpy/text/textsupport.pyx":681
+  /* "renpy/text/textsupport.pyx":708
  *     cdef ruby_t last_ruby = RUBY_NONE
  *     cdef int len_glyphs = len(glyphs)
  *     cdef float x, width, min_x = 0, max_x = 0             # <<<<<<<<<<<<<<
@@ -8807,7 +9091,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
   __pyx_v_min_x = 0.0;
   __pyx_v_max_x = 0.0;
 
-  /* "renpy/text/textsupport.pyx":682
+  /* "renpy/text/textsupport.pyx":709
  *     cdef int len_glyphs = len(glyphs)
  *     cdef float x, width, min_x = 0, max_x = 0
  *     cdef int y = 0             # <<<<<<<<<<<<<<
@@ -8816,7 +9100,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
   __pyx_v_y = 0;
 
-  /* "renpy/text/textsupport.pyx":684
+  /* "renpy/text/textsupport.pyx":711
  *     cdef int y = 0
  *     cdef int start_top
  *     cdef int pos = 0             # <<<<<<<<<<<<<<
@@ -8825,7 +9109,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
   __pyx_v_pos = 0;
 
-  /* "renpy/text/textsupport.pyx":687
+  /* "renpy/text/textsupport.pyx":714
  *     cdef int i
  * 
  *     while pos < len_glyphs:             # <<<<<<<<<<<<<<
@@ -8836,7 +9120,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     __pyx_t_2 = ((__pyx_v_pos < __pyx_v_len_glyphs) != 0);
     if (!__pyx_t_2) break;
 
-    /* "renpy/text/textsupport.pyx":689
+    /* "renpy/text/textsupport.pyx":716
  *     while pos < len_glyphs:
  * 
  *         g = glyphs[pos]             # <<<<<<<<<<<<<<
@@ -8845,15 +9129,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
     if (unlikely(__pyx_v_glyphs == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 689; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 716; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 689; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 716; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
     __Pyx_GOTREF(__pyx_t_3);
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 689; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 716; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":691
+    /* "renpy/text/textsupport.pyx":718
  *         g = glyphs[pos]
  * 
  *         if g.ruby == RUBY_NONE:             # <<<<<<<<<<<<<<
@@ -8863,7 +9147,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     switch (__pyx_v_g->ruby) {
       case __pyx_e_5renpy_4text_11textsupport_RUBY_NONE:
 
-      /* "renpy/text/textsupport.pyx":693
+      /* "renpy/text/textsupport.pyx":720
  *         if g.ruby == RUBY_NONE:
  * 
  *             min_x = g.x             # <<<<<<<<<<<<<<
@@ -8873,7 +9157,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_4 = __pyx_v_g->x;
       __pyx_v_min_x = __pyx_t_4;
 
-      /* "renpy/text/textsupport.pyx":694
+      /* "renpy/text/textsupport.pyx":721
  * 
  *             min_x = g.x
  *             max_x = g.x + g.width             # <<<<<<<<<<<<<<
@@ -8882,7 +9166,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_max_x = (__pyx_v_g->x + __pyx_v_g->width);
 
-      /* "renpy/text/textsupport.pyx":695
+      /* "renpy/text/textsupport.pyx":722
  *             min_x = g.x
  *             max_x = g.x + g.width
  *             y = g.y             # <<<<<<<<<<<<<<
@@ -8892,7 +9176,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_4 = __pyx_v_g->y;
       __pyx_v_y = __pyx_t_4;
 
-      /* "renpy/text/textsupport.pyx":697
+      /* "renpy/text/textsupport.pyx":724
  *             y = g.y
  * 
  *             last_ruby = RUBY_NONE             # <<<<<<<<<<<<<<
@@ -8901,7 +9185,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_last_ruby = __pyx_e_5renpy_4text_11textsupport_RUBY_NONE;
 
-      /* "renpy/text/textsupport.pyx":699
+      /* "renpy/text/textsupport.pyx":726
  *             last_ruby = RUBY_NONE
  * 
  *             pos += 1             # <<<<<<<<<<<<<<
@@ -8910,7 +9194,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_pos = (__pyx_v_pos + 1);
 
-      /* "renpy/text/textsupport.pyx":700
+      /* "renpy/text/textsupport.pyx":727
  * 
  *             pos += 1
  *             continue             # <<<<<<<<<<<<<<
@@ -8919,7 +9203,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       goto __pyx_L3_continue;
 
-      /* "renpy/text/textsupport.pyx":691
+      /* "renpy/text/textsupport.pyx":718
  *         g = glyphs[pos]
  * 
  *         if g.ruby == RUBY_NONE:             # <<<<<<<<<<<<<<
@@ -8928,7 +9212,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       break;
 
-      /* "renpy/text/textsupport.pyx":702
+      /* "renpy/text/textsupport.pyx":729
  *             continue
  * 
  *         elif g.ruby == RUBY_BOTTOM:             # <<<<<<<<<<<<<<
@@ -8937,7 +9221,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       case __pyx_e_5renpy_4text_11textsupport_RUBY_BOTTOM:
 
-      /* "renpy/text/textsupport.pyx":704
+      /* "renpy/text/textsupport.pyx":731
  *         elif g.ruby == RUBY_BOTTOM:
  * 
  *             if last_ruby != RUBY_BOTTOM:             # <<<<<<<<<<<<<<
@@ -8947,7 +9231,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_2 = ((__pyx_v_last_ruby != __pyx_e_5renpy_4text_11textsupport_RUBY_BOTTOM) != 0);
       if (__pyx_t_2) {
 
-        /* "renpy/text/textsupport.pyx":705
+        /* "renpy/text/textsupport.pyx":732
  * 
  *             if last_ruby != RUBY_BOTTOM:
  *                 min_x = g.x             # <<<<<<<<<<<<<<
@@ -8957,7 +9241,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
         __pyx_t_4 = __pyx_v_g->x;
         __pyx_v_min_x = __pyx_t_4;
 
-        /* "renpy/text/textsupport.pyx":704
+        /* "renpy/text/textsupport.pyx":731
  *         elif g.ruby == RUBY_BOTTOM:
  * 
  *             if last_ruby != RUBY_BOTTOM:             # <<<<<<<<<<<<<<
@@ -8966,7 +9250,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       }
 
-      /* "renpy/text/textsupport.pyx":707
+      /* "renpy/text/textsupport.pyx":734
  *                 min_x = g.x
  * 
  *             max_x = g.x + g.width             # <<<<<<<<<<<<<<
@@ -8975,7 +9259,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_max_x = (__pyx_v_g->x + __pyx_v_g->width);
 
-      /* "renpy/text/textsupport.pyx":708
+      /* "renpy/text/textsupport.pyx":735
  * 
  *             max_x = g.x + g.width
  *             y = g.y             # <<<<<<<<<<<<<<
@@ -8985,7 +9269,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_4 = __pyx_v_g->y;
       __pyx_v_y = __pyx_t_4;
 
-      /* "renpy/text/textsupport.pyx":710
+      /* "renpy/text/textsupport.pyx":737
  *             y = g.y
  * 
  *             last_ruby = RUBY_BOTTOM             # <<<<<<<<<<<<<<
@@ -8994,7 +9278,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_last_ruby = __pyx_e_5renpy_4text_11textsupport_RUBY_BOTTOM;
 
-      /* "renpy/text/textsupport.pyx":712
+      /* "renpy/text/textsupport.pyx":739
  *             last_ruby = RUBY_BOTTOM
  * 
  *             pos += 1             # <<<<<<<<<<<<<<
@@ -9003,7 +9287,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_pos = (__pyx_v_pos + 1);
 
-      /* "renpy/text/textsupport.pyx":713
+      /* "renpy/text/textsupport.pyx":740
  * 
  *             pos += 1
  *             continue             # <<<<<<<<<<<<<<
@@ -9012,7 +9296,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       goto __pyx_L3_continue;
 
-      /* "renpy/text/textsupport.pyx":702
+      /* "renpy/text/textsupport.pyx":729
  *             continue
  * 
  *         elif g.ruby == RUBY_BOTTOM:             # <<<<<<<<<<<<<<
@@ -9023,7 +9307,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       default: break;
     }
 
-    /* "renpy/text/textsupport.pyx":719
+    /* "renpy/text/textsupport.pyx":746
  *         # Find the run of RUBY_TOP. When this is done, the run will be in
  *         # glyphs[start_top:pos].
  *         start_top = pos             # <<<<<<<<<<<<<<
@@ -9032,7 +9316,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
     __pyx_v_start_top = __pyx_v_pos;
 
-    /* "renpy/text/textsupport.pyx":721
+    /* "renpy/text/textsupport.pyx":748
  *         start_top = pos
  * 
  *         while pos < len_glyphs:             # <<<<<<<<<<<<<<
@@ -9043,7 +9327,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_2 = ((__pyx_v_pos < __pyx_v_len_glyphs) != 0);
       if (!__pyx_t_2) break;
 
-      /* "renpy/text/textsupport.pyx":723
+      /* "renpy/text/textsupport.pyx":750
  *         while pos < len_glyphs:
  * 
  *             g = glyphs[pos]             # <<<<<<<<<<<<<<
@@ -9052,15 +9336,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       if (unlikely(__pyx_v_glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 723; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 723; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_pos, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
       __Pyx_GOTREF(__pyx_t_3);
-      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 723; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
       __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":724
+      /* "renpy/text/textsupport.pyx":751
  * 
  *             g = glyphs[pos]
  *             if g.ruby != RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9070,7 +9354,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_t_2 = ((__pyx_v_g->ruby != __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
       if (__pyx_t_2) {
 
-        /* "renpy/text/textsupport.pyx":725
+        /* "renpy/text/textsupport.pyx":752
  *             g = glyphs[pos]
  *             if g.ruby != RUBY_TOP:
  *                 break             # <<<<<<<<<<<<<<
@@ -9079,7 +9363,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
         goto __pyx_L7_break;
 
-        /* "renpy/text/textsupport.pyx":724
+        /* "renpy/text/textsupport.pyx":751
  * 
  *             g = glyphs[pos]
  *             if g.ruby != RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9088,7 +9372,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       }
 
-      /* "renpy/text/textsupport.pyx":727
+      /* "renpy/text/textsupport.pyx":754
  *                 break
  * 
  *             pos += 1             # <<<<<<<<<<<<<<
@@ -9099,7 +9383,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     }
     __pyx_L7_break:;
 
-    /* "renpy/text/textsupport.pyx":731
+    /* "renpy/text/textsupport.pyx":758
  *         # Compute the width of the run.
  * 
  *         width = 0             # <<<<<<<<<<<<<<
@@ -9108,7 +9392,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
     __pyx_v_width = 0.0;
 
-    /* "renpy/text/textsupport.pyx":732
+    /* "renpy/text/textsupport.pyx":759
  * 
  *         width = 0
  *         for i from start_top <= i < pos:             # <<<<<<<<<<<<<<
@@ -9118,7 +9402,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     __pyx_t_5 = __pyx_v_pos;
     for (__pyx_v_i = __pyx_v_start_top; __pyx_v_i < __pyx_t_5; __pyx_v_i++) {
 
-      /* "renpy/text/textsupport.pyx":733
+      /* "renpy/text/textsupport.pyx":760
  *         width = 0
  *         for i from start_top <= i < pos:
  *             g = glyphs[i]             # <<<<<<<<<<<<<<
@@ -9127,15 +9411,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       if (unlikely(__pyx_v_glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 733; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 733; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
       __Pyx_GOTREF(__pyx_t_3);
-      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 733; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
       __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":734
+      /* "renpy/text/textsupport.pyx":761
  *         for i from start_top <= i < pos:
  *             g = glyphs[i]
  *             width += g.advance             # <<<<<<<<<<<<<<
@@ -9145,61 +9429,61 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_v_width = (__pyx_v_width + __pyx_v_g->advance);
     }
 
-    /* "renpy/text/textsupport.pyx":736
+    /* "renpy/text/textsupport.pyx":763
  *             width += g.advance
  * 
  *         width -= glyphs[pos - 1].advance             # <<<<<<<<<<<<<<
  *         width += glyphs[pos - 1].width
  * 
  */
-    __pyx_t_3 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     if (unlikely(__pyx_v_glyphs == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_6 = (__pyx_v_pos - 1);
-    __pyx_t_7 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_t_6, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __pyx_t_7 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_t_6, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
     __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_advance); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_advance); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_7 = PyNumber_InPlaceSubtract(__pyx_t_3, __pyx_t_8); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyNumber_InPlaceSubtract(__pyx_t_3, __pyx_t_8); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_t_9 = __pyx_PyFloat_AsFloat(__pyx_t_7); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 736; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_PyFloat_AsFloat(__pyx_t_7); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 763; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __pyx_v_width = __pyx_t_9;
 
-    /* "renpy/text/textsupport.pyx":737
+    /* "renpy/text/textsupport.pyx":764
  * 
  *         width -= glyphs[pos - 1].advance
  *         width += glyphs[pos - 1].width             # <<<<<<<<<<<<<<
  * 
  *         # Place the glyphs.
  */
-    __pyx_t_7 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     if (unlikely(__pyx_v_glyphs == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_6 = (__pyx_v_pos - 1);
-    __pyx_t_8 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_t_6, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __pyx_t_8 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_t_6, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
     __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_width); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_width); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_t_8 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_9 = __pyx_PyFloat_AsFloat(__pyx_t_8); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 737; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_PyFloat_AsFloat(__pyx_t_8); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 764; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
     __pyx_v_width = __pyx_t_9;
 
-    /* "renpy/text/textsupport.pyx":740
+    /* "renpy/text/textsupport.pyx":767
  * 
  *         # Place the glyphs.
  *         x = (max_x + min_x) / 2 - width / 2             # <<<<<<<<<<<<<<
@@ -9208,7 +9492,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
     __pyx_v_x = (((__pyx_v_max_x + __pyx_v_min_x) / 2.0) - (__pyx_v_width / 2.0));
 
-    /* "renpy/text/textsupport.pyx":742
+    /* "renpy/text/textsupport.pyx":769
  *         x = (max_x + min_x) / 2 - width / 2
  * 
  *         for i from start_top <= i < pos:             # <<<<<<<<<<<<<<
@@ -9218,7 +9502,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     __pyx_t_5 = __pyx_v_pos;
     for (__pyx_v_i = __pyx_v_start_top; __pyx_v_i < __pyx_t_5; __pyx_v_i++) {
 
-      /* "renpy/text/textsupport.pyx":743
+      /* "renpy/text/textsupport.pyx":770
  * 
  *         for i from start_top <= i < pos:
  *             g = glyphs[i]             # <<<<<<<<<<<<<<
@@ -9227,15 +9511,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       if (unlikely(__pyx_v_glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 743; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 770; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_8 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 743; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+      __pyx_t_8 = __Pyx_GetItemInt_List(__pyx_v_glyphs, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 770; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
       __Pyx_GOTREF(__pyx_t_8);
-      if (!(likely(((__pyx_t_8) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_8, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 743; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_8) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_8, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 770; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_8));
       __pyx_t_8 = 0;
 
-      /* "renpy/text/textsupport.pyx":744
+      /* "renpy/text/textsupport.pyx":771
  *         for i from start_top <= i < pos:
  *             g = glyphs[i]
  *             g.x = <int> (x + .5)             # <<<<<<<<<<<<<<
@@ -9244,7 +9528,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_g->x = ((int)(__pyx_v_x + .5));
 
-      /* "renpy/text/textsupport.pyx":745
+      /* "renpy/text/textsupport.pyx":772
  *             g = glyphs[i]
  *             g.x = <int> (x + .5)
  *             g.y = y + ruby_offset             # <<<<<<<<<<<<<<
@@ -9253,7 +9537,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
       __pyx_v_g->y = (__pyx_v_y + __pyx_v_ruby_offset);
 
-      /* "renpy/text/textsupport.pyx":747
+      /* "renpy/text/textsupport.pyx":774
  *             g.y = y + ruby_offset
  * 
  *             x += g.advance             # <<<<<<<<<<<<<<
@@ -9263,7 +9547,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
       __pyx_v_x = (__pyx_v_x + __pyx_v_g->advance);
     }
 
-    /* "renpy/text/textsupport.pyx":749
+    /* "renpy/text/textsupport.pyx":776
  *             x += g.advance
  * 
  *         last_ruby = RUBY_TOP             # <<<<<<<<<<<<<<
@@ -9274,7 +9558,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
     __pyx_L3_continue:;
   }
 
-  /* "renpy/text/textsupport.pyx":676
+  /* "renpy/text/textsupport.pyx":703
  * 
  * 
  * def place_ruby(list glyphs, int ruby_offset, int surf_width, int surf_height):             # <<<<<<<<<<<<<<
@@ -9298,7 +9582,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":751
+/* "renpy/text/textsupport.pyx":778
  *         last_ruby = RUBY_TOP
  * 
  * def align_and_justify(list lines, int width, float text_align, bint justify):             # <<<<<<<<<<<<<<
@@ -9307,10 +9591,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_30place_ruby(CYTHON_UNUSED
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_33align_and_justify(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_32align_and_justify[] = "\n    Handle text alignment and justification.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_33align_and_justify = {"align_and_justify", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_33align_and_justify, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_32align_and_justify};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_33align_and_justify(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_35align_and_justify(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_34align_and_justify[] = "\n    Handle text alignment and justification.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_35align_and_justify = {"align_and_justify", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_35align_and_justify, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_34align_and_justify};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_35align_and_justify(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_lines = 0;
   int __pyx_v_width;
   float __pyx_v_text_align;
@@ -9343,21 +9627,21 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_33align_and_justify(PyObjec
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_width)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_text_align)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_justify)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "align_and_justify") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "align_and_justify") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -9368,20 +9652,20 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_33align_and_justify(PyObjec
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
     __pyx_v_lines = ((PyObject*)values[0]);
-    __pyx_v_width = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_width == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_text_align = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_text_align == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_justify = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_justify == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_width = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_width == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_text_align = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_text_align == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_justify = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_justify == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("align_and_justify", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.align_and_justify", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lines), (&PyList_Type), 1, "lines", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_32align_and_justify(__pyx_self, __pyx_v_lines, __pyx_v_width, __pyx_v_text_align, __pyx_v_justify);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lines), (&PyList_Type), 1, "lines", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_34align_and_justify(__pyx_self, __pyx_v_lines, __pyx_v_width, __pyx_v_text_align, __pyx_v_justify);
 
   /* function exit code */
   goto __pyx_L0;
@@ -9392,7 +9676,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_33align_and_justify(PyObjec
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_lines, int __pyx_v_width, float __pyx_v_text_align, int __pyx_v_justify) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_34align_and_justify(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_lines, int __pyx_v_width, float __pyx_v_text_align, int __pyx_v_justify) {
   struct __pyx_obj_5renpy_4text_11textsupport_Line *__pyx_v_l = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   int __pyx_v_max_x;
@@ -9415,7 +9699,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("align_and_justify", 0);
 
-  /* "renpy/text/textsupport.pyx":768
+  /* "renpy/text/textsupport.pyx":795
  * 
  *     # See if we have to do anything at all.
  *     if not justify and text_align == 0.0:             # <<<<<<<<<<<<<<
@@ -9433,7 +9717,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
   __pyx_L4_bool_binop_done:;
   if (__pyx_t_1) {
 
-    /* "renpy/text/textsupport.pyx":769
+    /* "renpy/text/textsupport.pyx":796
  *     # See if we have to do anything at all.
  *     if not justify and text_align == 0.0:
  *         return             # <<<<<<<<<<<<<<
@@ -9444,7 +9728,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     __pyx_r = Py_None; __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "renpy/text/textsupport.pyx":768
+    /* "renpy/text/textsupport.pyx":795
  * 
  *     # See if we have to do anything at all.
  *     if not justify and text_align == 0.0:             # <<<<<<<<<<<<<<
@@ -9453,7 +9737,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
   }
 
-  /* "renpy/text/textsupport.pyx":771
+  /* "renpy/text/textsupport.pyx":798
  *         return
  * 
  *     for l in lines:             # <<<<<<<<<<<<<<
@@ -9462,22 +9746,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
   if (unlikely(__pyx_v_lines == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_3 = __pyx_v_lines; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
   for (;;) {
     if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     #endif
-    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Line))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_l, ((struct __pyx_obj_5renpy_4text_11textsupport_Line *)__pyx_t_5));
     __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":773
+    /* "renpy/text/textsupport.pyx":800
  *     for l in lines:
  * 
  *         spaces = 0             # <<<<<<<<<<<<<<
@@ -9486,7 +9770,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
     __pyx_v_spaces = 0;
 
-    /* "renpy/text/textsupport.pyx":774
+    /* "renpy/text/textsupport.pyx":801
  * 
  *         spaces = 0
  *         max_x = 0             # <<<<<<<<<<<<<<
@@ -9495,7 +9779,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
     __pyx_v_max_x = 0;
 
-    /* "renpy/text/textsupport.pyx":776
+    /* "renpy/text/textsupport.pyx":803
  *         max_x = 0
  * 
  *         for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9504,22 +9788,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
     if (unlikely(__pyx_v_l->glyphs == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 776; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_5 = __pyx_v_l->glyphs; __Pyx_INCREF(__pyx_t_5); __pyx_t_6 = 0;
     for (;;) {
       if (__pyx_t_6 >= PyList_GET_SIZE(__pyx_t_5)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 776; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 776; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       #endif
-      if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 776; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_7));
       __pyx_t_7 = 0;
 
-      /* "renpy/text/textsupport.pyx":778
+      /* "renpy/text/textsupport.pyx":805
  *         for g in l.glyphs:
  * 
  *             if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9529,7 +9813,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
       __pyx_t_1 = ((__pyx_v_g->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
       if (__pyx_t_1) {
 
-        /* "renpy/text/textsupport.pyx":779
+        /* "renpy/text/textsupport.pyx":806
  * 
  *             if g.ruby == RUBY_TOP:
  *                 continue             # <<<<<<<<<<<<<<
@@ -9538,7 +9822,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         goto __pyx_L8_continue;
 
-        /* "renpy/text/textsupport.pyx":778
+        /* "renpy/text/textsupport.pyx":805
  *         for g in l.glyphs:
  * 
  *             if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9547,7 +9831,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       }
 
-      /* "renpy/text/textsupport.pyx":781
+      /* "renpy/text/textsupport.pyx":808
  *                 continue
  * 
  *             if g.character == 0x20:             # <<<<<<<<<<<<<<
@@ -9557,7 +9841,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
       __pyx_t_1 = ((__pyx_v_g->character == 0x20) != 0);
       if (__pyx_t_1) {
 
-        /* "renpy/text/textsupport.pyx":782
+        /* "renpy/text/textsupport.pyx":809
  * 
  *             if g.character == 0x20:
  *                 spaces += 1             # <<<<<<<<<<<<<<
@@ -9566,7 +9850,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         __pyx_v_spaces = (__pyx_v_spaces + 1);
 
-        /* "renpy/text/textsupport.pyx":781
+        /* "renpy/text/textsupport.pyx":808
  *                 continue
  * 
  *             if g.character == 0x20:             # <<<<<<<<<<<<<<
@@ -9575,7 +9859,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       }
 
-      /* "renpy/text/textsupport.pyx":784
+      /* "renpy/text/textsupport.pyx":811
  *                 spaces += 1
  * 
  *             max_x = <int> (g.x + g.width)             # <<<<<<<<<<<<<<
@@ -9584,7 +9868,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       __pyx_v_max_x = ((int)(__pyx_v_g->x + __pyx_v_g->width));
 
-      /* "renpy/text/textsupport.pyx":776
+      /* "renpy/text/textsupport.pyx":803
  *         max_x = 0
  * 
  *         for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9595,7 +9879,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     }
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":787
+    /* "renpy/text/textsupport.pyx":814
  * 
  *         # If we're too big, give up.
  *         if max_x >= MAX_WIDTH:             # <<<<<<<<<<<<<<
@@ -9605,7 +9889,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     __pyx_t_1 = ((__pyx_v_max_x >= __pyx_v_5renpy_4text_11textsupport_MAX_WIDTH) != 0);
     if (__pyx_t_1) {
 
-      /* "renpy/text/textsupport.pyx":788
+      /* "renpy/text/textsupport.pyx":815
  *         # If we're too big, give up.
  *         if max_x >= MAX_WIDTH:
  *             continue             # <<<<<<<<<<<<<<
@@ -9614,7 +9898,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       goto __pyx_L6_continue;
 
-      /* "renpy/text/textsupport.pyx":787
+      /* "renpy/text/textsupport.pyx":814
  * 
  *         # If we're too big, give up.
  *         if max_x >= MAX_WIDTH:             # <<<<<<<<<<<<<<
@@ -9623,7 +9907,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
     }
 
-    /* "renpy/text/textsupport.pyx":790
+    /* "renpy/text/textsupport.pyx":817
  *             continue
  * 
  *         if justify and spaces and not l.eop:             # <<<<<<<<<<<<<<
@@ -9647,7 +9931,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     __pyx_L14_bool_binop_done:;
     if (__pyx_t_1) {
 
-      /* "renpy/text/textsupport.pyx":792
+      /* "renpy/text/textsupport.pyx":819
  *         if justify and spaces and not l.eop:
  * 
  *             justify_per_space = 1.0 * (width - max_x) / spaces             # <<<<<<<<<<<<<<
@@ -9657,11 +9941,11 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
       __pyx_t_8 = (1.0 * (__pyx_v_width - __pyx_v_max_x));
       if (unlikely(__pyx_v_spaces == 0)) {
         PyErr_SetString(PyExc_ZeroDivisionError, "float division");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_v_justify_per_space = (__pyx_t_8 / __pyx_v_spaces);
 
-      /* "renpy/text/textsupport.pyx":793
+      /* "renpy/text/textsupport.pyx":820
  * 
  *             justify_per_space = 1.0 * (width - max_x) / spaces
  *             justify_offset = 0.5 # Makes numbers round better.             # <<<<<<<<<<<<<<
@@ -9670,7 +9954,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       __pyx_v_justify_offset = 0.5;
 
-      /* "renpy/text/textsupport.pyx":795
+      /* "renpy/text/textsupport.pyx":822
  *             justify_offset = 0.5 # Makes numbers round better.
  * 
  *             for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9679,22 +9963,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       if (unlikely(__pyx_v_l->glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_5 = __pyx_v_l->glyphs; __Pyx_INCREF(__pyx_t_5); __pyx_t_6 = 0;
       for (;;) {
         if (__pyx_t_6 >= PyList_GET_SIZE(__pyx_t_5)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         #endif
-        if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_7));
         __pyx_t_7 = 0;
 
-        /* "renpy/text/textsupport.pyx":797
+        /* "renpy/text/textsupport.pyx":824
  *             for g in l.glyphs:
  * 
  *                 if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9704,7 +9988,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
         __pyx_t_1 = ((__pyx_v_g->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
         if (__pyx_t_1) {
 
-          /* "renpy/text/textsupport.pyx":798
+          /* "renpy/text/textsupport.pyx":825
  * 
  *                 if g.ruby == RUBY_TOP:
  *                     continue             # <<<<<<<<<<<<<<
@@ -9713,7 +9997,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
           goto __pyx_L17_continue;
 
-          /* "renpy/text/textsupport.pyx":797
+          /* "renpy/text/textsupport.pyx":824
  *             for g in l.glyphs:
  * 
  *                 if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9722,7 +10006,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         }
 
-        /* "renpy/text/textsupport.pyx":800
+        /* "renpy/text/textsupport.pyx":827
  *                     continue
  * 
  *                 if g.character == 0x20:             # <<<<<<<<<<<<<<
@@ -9732,7 +10016,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
         __pyx_t_1 = ((__pyx_v_g->character == 0x20) != 0);
         if (__pyx_t_1) {
 
-          /* "renpy/text/textsupport.pyx":801
+          /* "renpy/text/textsupport.pyx":828
  * 
  *                 if g.character == 0x20:
  *                     justify_offset += justify_per_space             # <<<<<<<<<<<<<<
@@ -9741,7 +10025,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
           __pyx_v_justify_offset = (__pyx_v_justify_offset + __pyx_v_justify_per_space);
 
-          /* "renpy/text/textsupport.pyx":800
+          /* "renpy/text/textsupport.pyx":827
  *                     continue
  * 
  *                 if g.character == 0x20:             # <<<<<<<<<<<<<<
@@ -9750,7 +10034,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         }
 
-        /* "renpy/text/textsupport.pyx":803
+        /* "renpy/text/textsupport.pyx":830
  *                     justify_offset += justify_per_space
  * 
  *                 g.x += <int> justify_offset             # <<<<<<<<<<<<<<
@@ -9759,7 +10043,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         __pyx_v_g->x = (__pyx_v_g->x + ((int)__pyx_v_justify_offset));
 
-        /* "renpy/text/textsupport.pyx":795
+        /* "renpy/text/textsupport.pyx":822
  *             justify_offset = 0.5 # Makes numbers round better.
  * 
  *             for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9770,7 +10054,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
       }
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-      /* "renpy/text/textsupport.pyx":790
+      /* "renpy/text/textsupport.pyx":817
  *             continue
  * 
  *         if justify and spaces and not l.eop:             # <<<<<<<<<<<<<<
@@ -9780,7 +10064,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
       goto __pyx_L13;
     }
 
-    /* "renpy/text/textsupport.pyx":806
+    /* "renpy/text/textsupport.pyx":833
  * 
  *         else:
  *             offset = <int> ((width - max_x) * text_align)             # <<<<<<<<<<<<<<
@@ -9790,7 +10074,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     /*else*/ {
       __pyx_v_offset = ((int)((__pyx_v_width - __pyx_v_max_x) * __pyx_v_text_align));
 
-      /* "renpy/text/textsupport.pyx":808
+      /* "renpy/text/textsupport.pyx":835
  *             offset = <int> ((width - max_x) * text_align)
  * 
  *             for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9799,22 +10083,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
       if (unlikely(__pyx_v_l->glyphs == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_5 = __pyx_v_l->glyphs; __Pyx_INCREF(__pyx_t_5); __pyx_t_6 = 0;
       for (;;) {
         if (__pyx_t_6 >= PyList_GET_SIZE(__pyx_t_5)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_7); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         #endif
-        if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_7));
         __pyx_t_7 = 0;
 
-        /* "renpy/text/textsupport.pyx":810
+        /* "renpy/text/textsupport.pyx":837
  *             for g in l.glyphs:
  * 
  *                 if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9824,7 +10108,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
         __pyx_t_1 = ((__pyx_v_g->ruby == __pyx_e_5renpy_4text_11textsupport_RUBY_TOP) != 0);
         if (__pyx_t_1) {
 
-          /* "renpy/text/textsupport.pyx":811
+          /* "renpy/text/textsupport.pyx":838
  * 
  *                 if g.ruby == RUBY_TOP:
  *                     continue             # <<<<<<<<<<<<<<
@@ -9833,7 +10117,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
           goto __pyx_L21_continue;
 
-          /* "renpy/text/textsupport.pyx":810
+          /* "renpy/text/textsupport.pyx":837
  *             for g in l.glyphs:
  * 
  *                 if g.ruby == RUBY_TOP:             # <<<<<<<<<<<<<<
@@ -9842,7 +10126,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         }
 
-        /* "renpy/text/textsupport.pyx":813
+        /* "renpy/text/textsupport.pyx":840
  *                     continue
  * 
  *                 g.x += offset             # <<<<<<<<<<<<<<
@@ -9851,7 +10135,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
         __pyx_v_g->x = (__pyx_v_g->x + __pyx_v_offset);
 
-        /* "renpy/text/textsupport.pyx":808
+        /* "renpy/text/textsupport.pyx":835
  *             offset = <int> ((width - max_x) * text_align)
  * 
  *             for g in l.glyphs:             # <<<<<<<<<<<<<<
@@ -9864,7 +10148,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
     }
     __pyx_L13:;
 
-    /* "renpy/text/textsupport.pyx":771
+    /* "renpy/text/textsupport.pyx":798
  *         return
  * 
  *     for l in lines:             # <<<<<<<<<<<<<<
@@ -9875,7 +10159,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
   }
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/text/textsupport.pyx":751
+  /* "renpy/text/textsupport.pyx":778
  *         last_ruby = RUBY_TOP
  * 
  * def align_and_justify(list lines, int width, float text_align, bint justify):             # <<<<<<<<<<<<<<
@@ -9900,7 +10184,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":815
+/* "renpy/text/textsupport.pyx":842
  *                 g.x += offset
  * 
  * def reverse_lines(list glyphs):             # <<<<<<<<<<<<<<
@@ -9909,18 +10193,18 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_32align_and_justify(CYTHON_
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_35reverse_lines(PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_34reverse_lines[] = "\n    Reverses each line in glyphs, while keeping the lines themselves in\n    the original order.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_35reverse_lines = {"reverse_lines", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_35reverse_lines, METH_O, __pyx_doc_5renpy_4text_11textsupport_34reverse_lines};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_35reverse_lines(PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_37reverse_lines(PyObject *__pyx_self, PyObject *__pyx_v_glyphs); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_36reverse_lines[] = "\n    Reverses each line in glyphs, while keeping the lines themselves in\n    the original order.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_37reverse_lines = {"reverse_lines", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_37reverse_lines, METH_O, __pyx_doc_5renpy_4text_11textsupport_36reverse_lines};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_37reverse_lines(PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
   CYTHON_UNUSED int __pyx_lineno = 0;
   CYTHON_UNUSED const char *__pyx_filename = NULL;
   CYTHON_UNUSED int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("reverse_lines (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_34reverse_lines(__pyx_self, ((PyObject*)__pyx_v_glyphs));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_36reverse_lines(__pyx_self, ((PyObject*)__pyx_v_glyphs));
 
   /* function exit code */
   goto __pyx_L0;
@@ -9931,7 +10215,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_35reverse_lines(PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_36reverse_lines(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs) {
   PyObject *__pyx_v_rv = 0;
   PyObject *__pyx_v_block = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
@@ -9947,31 +10231,31 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("reverse_lines", 0);
 
-  /* "renpy/text/textsupport.pyx":825
+  /* "renpy/text/textsupport.pyx":852
  *     cdef Glyph g
  * 
  *     rv = [ ]             # <<<<<<<<<<<<<<
  *     block = [ ]
  * 
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 852; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_rv = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":826
+  /* "renpy/text/textsupport.pyx":853
  * 
  *     rv = [ ]
  *     block = [ ]             # <<<<<<<<<<<<<<
  * 
  *     for g in glyphs:
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 853; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_block = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":828
+  /* "renpy/text/textsupport.pyx":855
  *     block = [ ]
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -9980,22 +10264,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_1 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
     if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     #endif
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_3));
     __pyx_t_3 = 0;
 
-    /* "renpy/text/textsupport.pyx":830
+    /* "renpy/text/textsupport.pyx":857
  *     for g in glyphs:
  * 
  *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
@@ -10005,46 +10289,46 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
     __pyx_t_4 = ((__pyx_v_g->split == __pyx_e_5renpy_4text_11textsupport_SPLIT_INSTEAD) != 0);
     if (__pyx_t_4) {
 
-      /* "renpy/text/textsupport.pyx":831
+      /* "renpy/text/textsupport.pyx":858
  * 
  *         if g.split == SPLIT_INSTEAD:
  *             block.reverse()             # <<<<<<<<<<<<<<
  *             rv.extend(block)
  *             rv.append(g)
  */
-      __pyx_t_5 = PyList_Reverse(__pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyList_Reverse(__pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 858; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-      /* "renpy/text/textsupport.pyx":832
+      /* "renpy/text/textsupport.pyx":859
  *         if g.split == SPLIT_INSTEAD:
  *             block.reverse()
  *             rv.extend(block)             # <<<<<<<<<<<<<<
  *             rv.append(g)
  *             block = [ ]
  */
-      __pyx_t_5 = __Pyx_PyList_Extend(__pyx_v_rv, __pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __Pyx_PyList_Extend(__pyx_v_rv, __pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 859; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-      /* "renpy/text/textsupport.pyx":833
+      /* "renpy/text/textsupport.pyx":860
  *             block.reverse()
  *             rv.extend(block)
  *             rv.append(g)             # <<<<<<<<<<<<<<
  *             block = [ ]
  * 
  */
-      __pyx_t_5 = __Pyx_PyList_Append(__pyx_v_rv, ((PyObject *)__pyx_v_g)); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __Pyx_PyList_Append(__pyx_v_rv, ((PyObject *)__pyx_v_g)); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 860; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-      /* "renpy/text/textsupport.pyx":834
+      /* "renpy/text/textsupport.pyx":861
  *             rv.extend(block)
  *             rv.append(g)
  *             block = [ ]             # <<<<<<<<<<<<<<
  * 
  *             continue
  */
-      __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF_SET(__pyx_v_block, ((PyObject*)__pyx_t_3));
       __pyx_t_3 = 0;
 
-      /* "renpy/text/textsupport.pyx":836
+      /* "renpy/text/textsupport.pyx":863
  *             block = [ ]
  * 
  *             continue             # <<<<<<<<<<<<<<
@@ -10053,7 +10337,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
  */
       goto __pyx_L3_continue;
 
-      /* "renpy/text/textsupport.pyx":830
+      /* "renpy/text/textsupport.pyx":857
  *     for g in glyphs:
  * 
  *         if g.split == SPLIT_INSTEAD:             # <<<<<<<<<<<<<<
@@ -10062,16 +10346,16 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
  */
     }
 
-    /* "renpy/text/textsupport.pyx":838
+    /* "renpy/text/textsupport.pyx":865
  *             continue
  * 
  *         block.append(g)             # <<<<<<<<<<<<<<
  * 
  *     block.reverse()
  */
-    __pyx_t_5 = __Pyx_PyList_Append(__pyx_v_block, ((PyObject *)__pyx_v_g)); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyList_Append(__pyx_v_block, ((PyObject *)__pyx_v_g)); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 865; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-    /* "renpy/text/textsupport.pyx":828
+    /* "renpy/text/textsupport.pyx":855
  *     block = [ ]
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -10082,25 +10366,25 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "renpy/text/textsupport.pyx":840
+  /* "renpy/text/textsupport.pyx":867
  *         block.append(g)
  * 
  *     block.reverse()             # <<<<<<<<<<<<<<
  *     rv.extend(block)
  * 
  */
-  __pyx_t_5 = PyList_Reverse(__pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyList_Reverse(__pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 867; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":841
+  /* "renpy/text/textsupport.pyx":868
  * 
  *     block.reverse()
  *     rv.extend(block)             # <<<<<<<<<<<<<<
  * 
  *     return rv
  */
-  __pyx_t_5 = __Pyx_PyList_Extend(__pyx_v_rv, __pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __Pyx_PyList_Extend(__pyx_v_rv, __pyx_v_block); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 868; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":843
+  /* "renpy/text/textsupport.pyx":870
  *     rv.extend(block)
  * 
  *     return rv             # <<<<<<<<<<<<<<
@@ -10112,7 +10396,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
   __pyx_r = __pyx_v_rv;
   goto __pyx_L0;
 
-  /* "renpy/text/textsupport.pyx":815
+  /* "renpy/text/textsupport.pyx":842
  *                 g.x += offset
  * 
  * def reverse_lines(list glyphs):             # <<<<<<<<<<<<<<
@@ -10135,7 +10419,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":845
+/* "renpy/text/textsupport.pyx":872
  *     return rv
  * 
  * def copy_splits(list source, list dest):             # <<<<<<<<<<<<<<
@@ -10144,10 +10428,10 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_34reverse_lines(CYTHON_UNUS
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_37copy_splits(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_5renpy_4text_11textsupport_36copy_splits[] = "\n    Copies break and timing information from one list of glyphs\n    to another.\n    ";
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_37copy_splits = {"copy_splits", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_37copy_splits, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_36copy_splits};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_37copy_splits(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_39copy_splits(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_5renpy_4text_11textsupport_38copy_splits[] = "\n    Copies break and timing information from one list of glyphs\n    to another.\n    ";
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_39copy_splits = {"copy_splits", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_39copy_splits, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5renpy_4text_11textsupport_38copy_splits};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_39copy_splits(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_source = 0;
   PyObject *__pyx_v_dest = 0;
   int __pyx_lineno = 0;
@@ -10176,11 +10460,11 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_37copy_splits(PyObject *__p
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_dest)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("copy_splits", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("copy_splits", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "copy_splits") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "copy_splits") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -10193,15 +10477,15 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_37copy_splits(PyObject *__p
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("copy_splits", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("copy_splits", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.copy_splits", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_source), (&PyList_Type), 1, "source", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dest), (&PyList_Type), 1, "dest", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_36copy_splits(__pyx_self, __pyx_v_source, __pyx_v_dest);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_source), (&PyList_Type), 1, "source", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dest), (&PyList_Type), 1, "dest", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_38copy_splits(__pyx_self, __pyx_v_source, __pyx_v_dest);
 
   /* function exit code */
   goto __pyx_L0;
@@ -10212,7 +10496,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_37copy_splits(PyObject *__p
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_source, PyObject *__pyx_v_dest) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_38copy_splits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_source, PyObject *__pyx_v_dest) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_s = 0;
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_d = 0;
   int __pyx_v_i;
@@ -10226,7 +10510,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("copy_splits", 0);
 
-  /* "renpy/text/textsupport.pyx":855
+  /* "renpy/text/textsupport.pyx":882
  *     cdef int i
  * 
  *     for 0 <= i < len(dest):             # <<<<<<<<<<<<<<
@@ -10235,12 +10519,12 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
  */
   if (unlikely(__pyx_v_dest == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_1 = PyList_GET_SIZE(__pyx_v_dest); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 855; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_GET_SIZE(__pyx_v_dest); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_1; __pyx_v_i++) {
 
-    /* "renpy/text/textsupport.pyx":856
+    /* "renpy/text/textsupport.pyx":883
  * 
  *     for 0 <= i < len(dest):
  *         s = source[i]             # <<<<<<<<<<<<<<
@@ -10249,15 +10533,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
  */
     if (unlikely(__pyx_v_source == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 856; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_source, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 856; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_source, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
     __Pyx_GOTREF(__pyx_t_2);
-    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 856; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_s, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_2));
     __pyx_t_2 = 0;
 
-    /* "renpy/text/textsupport.pyx":857
+    /* "renpy/text/textsupport.pyx":884
  *     for 0 <= i < len(dest):
  *         s = source[i]
  *         d = dest[i]             # <<<<<<<<<<<<<<
@@ -10266,15 +10550,15 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
  */
     if (unlikely(__pyx_v_dest == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 884; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_dest, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_dest, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 884; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
     __Pyx_GOTREF(__pyx_t_2);
-    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 884; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_d, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_2));
     __pyx_t_2 = 0;
 
-    /* "renpy/text/textsupport.pyx":859
+    /* "renpy/text/textsupport.pyx":886
  *         d = dest[i]
  * 
  *         d.split = s.split             # <<<<<<<<<<<<<<
@@ -10285,7 +10569,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
     __pyx_v_d->split = __pyx_t_3;
   }
 
-  /* "renpy/text/textsupport.pyx":845
+  /* "renpy/text/textsupport.pyx":872
  *     return rv
  * 
  * def copy_splits(list source, list dest):             # <<<<<<<<<<<<<<
@@ -10308,7 +10592,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
   return __pyx_r;
 }
 
-/* "renpy/text/textsupport.pyx":861
+/* "renpy/text/textsupport.pyx":888
  *         d.split = s.split
  * 
  * def tweak_glyph_spacing(list glyphs, list lines, double dx, double dy, double w, double h):             # <<<<<<<<<<<<<<
@@ -10317,9 +10601,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_36copy_splits(CYTHON_UNUSED
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_39tweak_glyph_spacing = {"tweak_glyph_spacing", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_41tweak_glyph_spacing(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_5renpy_4text_11textsupport_41tweak_glyph_spacing = {"tweak_glyph_spacing", (PyCFunction)__pyx_pw_5renpy_4text_11textsupport_41tweak_glyph_spacing, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_5renpy_4text_11textsupport_41tweak_glyph_spacing(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_glyphs = 0;
   PyObject *__pyx_v_lines = 0;
   double __pyx_v_dx;
@@ -10356,31 +10640,31 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing(PyObj
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lines)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_dx)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_dy)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  4:
         if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_w)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  5:
         if (likely((values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_h)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "tweak_glyph_spacing") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "tweak_glyph_spacing") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 6) {
       goto __pyx_L5_argtuple_error;
@@ -10394,22 +10678,22 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing(PyObj
     }
     __pyx_v_glyphs = ((PyObject*)values[0]);
     __pyx_v_lines = ((PyObject*)values[1]);
-    __pyx_v_dx = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_dx == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_dy = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_dy == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_w = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_w == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_h = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_h == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_dx = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_dx == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_dy = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_dy == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_w = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_w == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_h = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_h == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("tweak_glyph_spacing", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("renpy.text.textsupport.tweak_glyph_spacing", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lines), (&PyList_Type), 1, "lines", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(__pyx_self, __pyx_v_glyphs, __pyx_v_lines, __pyx_v_dx, __pyx_v_dy, __pyx_v_w, __pyx_v_h);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_glyphs), (&PyList_Type), 1, "glyphs", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lines), (&PyList_Type), 1, "lines", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_5renpy_4text_11textsupport_40tweak_glyph_spacing(__pyx_self, __pyx_v_glyphs, __pyx_v_lines, __pyx_v_dx, __pyx_v_dy, __pyx_v_w, __pyx_v_h);
 
   /* function exit code */
   goto __pyx_L0;
@@ -10420,7 +10704,7 @@ static PyObject *__pyx_pw_5renpy_4text_11textsupport_39tweak_glyph_spacing(PyObj
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, PyObject *__pyx_v_lines, double __pyx_v_dx, double __pyx_v_dy, double __pyx_v_w, double __pyx_v_h) {
+static PyObject *__pyx_pf_5renpy_4text_11textsupport_40tweak_glyph_spacing(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_glyphs, PyObject *__pyx_v_lines, double __pyx_v_dx, double __pyx_v_dy, double __pyx_v_w, double __pyx_v_h) {
   struct __pyx_obj_5renpy_4text_11textsupport_Glyph *__pyx_v_g = 0;
   PyObject *__pyx_v_old_x_offset = NULL;
   PyObject *__pyx_v_x_offset = NULL;
@@ -10443,7 +10727,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("tweak_glyph_spacing", 0);
 
-  /* "renpy/text/textsupport.pyx":864
+  /* "renpy/text/textsupport.pyx":891
  *     cdef Glyph g
  * 
  *     if w <= 0 or h <= 0:             # <<<<<<<<<<<<<<
@@ -10461,7 +10745,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
   __pyx_L4_bool_binop_done:;
   if (__pyx_t_1) {
 
-    /* "renpy/text/textsupport.pyx":865
+    /* "renpy/text/textsupport.pyx":892
  * 
  *     if w <= 0 or h <= 0:
  *         return             # <<<<<<<<<<<<<<
@@ -10472,7 +10756,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
     __pyx_r = Py_None; __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "renpy/text/textsupport.pyx":864
+    /* "renpy/text/textsupport.pyx":891
  *     cdef Glyph g
  * 
  *     if w <= 0 or h <= 0:             # <<<<<<<<<<<<<<
@@ -10481,7 +10765,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
  */
   }
 
-  /* "renpy/text/textsupport.pyx":868
+  /* "renpy/text/textsupport.pyx":895
  * 
  * 
  *     old_x_offset = 0             # <<<<<<<<<<<<<<
@@ -10491,7 +10775,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
   __Pyx_INCREF(__pyx_int_0);
   __pyx_v_old_x_offset = __pyx_int_0;
 
-  /* "renpy/text/textsupport.pyx":870
+  /* "renpy/text/textsupport.pyx":897
  *     old_x_offset = 0
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -10500,22 +10784,22 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
  */
   if (unlikely(__pyx_v_glyphs == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 897; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_3 = __pyx_v_glyphs; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
   for (;;) {
     if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_5); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 897; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 897; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     #endif
-    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5renpy_4text_11textsupport_Glyph))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 897; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF_SET(__pyx_v_g, ((struct __pyx_obj_5renpy_4text_11textsupport_Glyph *)__pyx_t_5));
     __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":872
+    /* "renpy/text/textsupport.pyx":899
  *     for g in glyphs:
  * 
  *         x_offset = int(dx * g.x / w)             # <<<<<<<<<<<<<<
@@ -10525,95 +10809,95 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
     __pyx_t_6 = (__pyx_v_dx * __pyx_v_g->x);
     if (unlikely(__pyx_v_w == 0)) {
       PyErr_SetString(PyExc_ZeroDivisionError, "float division");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 899; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_5 = PyFloat_FromDouble((__pyx_t_6 / __pyx_v_w)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyFloat_FromDouble((__pyx_t_6 / __pyx_v_w)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 899; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 899; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_GIVEREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_7, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_7, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 899; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __Pyx_XDECREF_SET(__pyx_v_x_offset, __pyx_t_5);
     __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":874
+    /* "renpy/text/textsupport.pyx":901
  *         x_offset = int(dx * g.x / w)
  * 
  *         g.x += x_offset             # <<<<<<<<<<<<<<
  *         g.y += int(dy * g.y / h)
  * 
  */
-    __pyx_t_5 = __Pyx_PyInt_From_short(__pyx_v_g->x); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyInt_From_short(__pyx_v_g->x); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 901; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = PyNumber_InPlaceAdd(__pyx_t_5, __pyx_v_x_offset); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyNumber_InPlaceAdd(__pyx_t_5, __pyx_v_x_offset); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 901; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_7); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_7); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 901; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __pyx_v_g->x = __pyx_t_8;
 
-    /* "renpy/text/textsupport.pyx":875
+    /* "renpy/text/textsupport.pyx":902
  * 
  *         g.x += x_offset
  *         g.y += int(dy * g.y / h)             # <<<<<<<<<<<<<<
  * 
  *         if x_offset > old_x_offset:
  */
-    __pyx_t_7 = __Pyx_PyInt_From_short(__pyx_v_g->y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = __Pyx_PyInt_From_short(__pyx_v_g->y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __pyx_t_6 = (__pyx_v_dy * __pyx_v_g->y);
     if (unlikely(__pyx_v_h == 0)) {
       PyErr_SetString(PyExc_ZeroDivisionError, "float division");
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_5 = PyFloat_FromDouble((__pyx_t_6 / __pyx_v_h)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyFloat_FromDouble((__pyx_t_6 / __pyx_v_h)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_GIVEREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_9, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_9, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    __pyx_t_9 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_9); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_9); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
     __pyx_v_g->y = __pyx_t_8;
 
-    /* "renpy/text/textsupport.pyx":877
+    /* "renpy/text/textsupport.pyx":904
  *         g.y += int(dy * g.y / h)
  * 
  *         if x_offset > old_x_offset:             # <<<<<<<<<<<<<<
  *             g.delta_x_offset = x_offset - old_x_offset
  * 
  */
-    __pyx_t_9 = PyObject_RichCompare(__pyx_v_x_offset, __pyx_v_old_x_offset, Py_GT); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyObject_RichCompare(__pyx_v_x_offset, __pyx_v_old_x_offset, Py_GT); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 904; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 904; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
     if (__pyx_t_1) {
 
-      /* "renpy/text/textsupport.pyx":878
+      /* "renpy/text/textsupport.pyx":905
  * 
  *         if x_offset > old_x_offset:
  *             g.delta_x_offset = x_offset - old_x_offset             # <<<<<<<<<<<<<<
  * 
  *         old_x_offset = x_offset
  */
-      __pyx_t_9 = PyNumber_Subtract(__pyx_v_x_offset, __pyx_v_old_x_offset); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 878; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyNumber_Subtract(__pyx_v_x_offset, __pyx_v_old_x_offset); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_9); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 878; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = __Pyx_PyInt_As_short(__pyx_t_9); if (unlikely((__pyx_t_8 == (short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
       __pyx_v_g->delta_x_offset = __pyx_t_8;
 
-      /* "renpy/text/textsupport.pyx":877
+      /* "renpy/text/textsupport.pyx":904
  *         g.y += int(dy * g.y / h)
  * 
  *         if x_offset > old_x_offset:             # <<<<<<<<<<<<<<
@@ -10622,7 +10906,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
  */
     }
 
-    /* "renpy/text/textsupport.pyx":880
+    /* "renpy/text/textsupport.pyx":907
  *             g.delta_x_offset = x_offset - old_x_offset
  * 
  *         old_x_offset = x_offset             # <<<<<<<<<<<<<<
@@ -10632,7 +10916,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
     __Pyx_INCREF(__pyx_v_x_offset);
     __Pyx_DECREF_SET(__pyx_v_old_x_offset, __pyx_v_x_offset);
 
-    /* "renpy/text/textsupport.pyx":870
+    /* "renpy/text/textsupport.pyx":897
  *     old_x_offset = 0
  * 
  *     for g in glyphs:             # <<<<<<<<<<<<<<
@@ -10642,7 +10926,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
   }
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/text/textsupport.pyx":882
+  /* "renpy/text/textsupport.pyx":909
  *         old_x_offset = x_offset
  * 
  *     for l in lines:             # <<<<<<<<<<<<<<
@@ -10651,112 +10935,112 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
  */
   if (unlikely(__pyx_v_lines == Py_None)) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 909; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_3 = __pyx_v_lines; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
   for (;;) {
     if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_9 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_9); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_9); __pyx_t_4++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 909; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 909; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     #endif
     __Pyx_XDECREF_SET(__pyx_v_l, __pyx_t_9);
     __pyx_t_9 = 0;
 
-    /* "renpy/text/textsupport.pyx":883
+    /* "renpy/text/textsupport.pyx":910
  * 
  *     for l in lines:
  *         end = l.y + l.height             # <<<<<<<<<<<<<<
  * 
  *         l.y += int(dy * l.y / h)
  */
-    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 910; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_height); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_height); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 910; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = PyNumber_Add(__pyx_t_9, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyNumber_Add(__pyx_t_9, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 910; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_XDECREF_SET(__pyx_v_end, __pyx_t_7);
     __pyx_t_7 = 0;
 
-    /* "renpy/text/textsupport.pyx":885
+    /* "renpy/text/textsupport.pyx":912
  *         end = l.y + l.height
  * 
  *         l.y += int(dy * l.y / h)             # <<<<<<<<<<<<<<
  *         end += int(dy * end / h)
  * 
  */
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_dy); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_dy); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
-    __pyx_t_10 = PyNumber_Multiply(__pyx_t_5, __pyx_t_9); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_10 = PyNumber_Multiply(__pyx_t_5, __pyx_t_9); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_10);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    __pyx_t_9 = PyFloat_FromDouble(__pyx_v_h); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyFloat_FromDouble(__pyx_v_h); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
-    __pyx_t_5 = __Pyx_PyNumber_Divide(__pyx_t_10, __pyx_t_9); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyNumber_Divide(__pyx_t_10, __pyx_t_9); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    __pyx_t_9 = PyNumber_Int(__pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyNumber_Int(__pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_9); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_t_7, __pyx_t_9); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    if (__Pyx_PyObject_SetAttrStr(__pyx_v_l, __pyx_n_s_y, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 885; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__Pyx_PyObject_SetAttrStr(__pyx_v_l, __pyx_n_s_y, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 912; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":886
+    /* "renpy/text/textsupport.pyx":913
  * 
  *         l.y += int(dy * l.y / h)
  *         end += int(dy * end / h)             # <<<<<<<<<<<<<<
  * 
  *         l.height = end - l.y
  */
-    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_dy); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_dy); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_9 = PyNumber_Multiply(__pyx_t_5, __pyx_v_end); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyNumber_Multiply(__pyx_t_5, __pyx_v_end); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_h); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_h); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = __Pyx_PyNumber_Divide(__pyx_t_9, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = __Pyx_PyNumber_Divide(__pyx_t_9, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyNumber_Int(__pyx_t_7); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Int(__pyx_t_7); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_7 = PyNumber_InPlaceAdd(__pyx_v_end, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 886; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyNumber_InPlaceAdd(__pyx_v_end, __pyx_t_5); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 913; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_DECREF_SET(__pyx_v_end, __pyx_t_7);
     __pyx_t_7 = 0;
 
-    /* "renpy/text/textsupport.pyx":888
+    /* "renpy/text/textsupport.pyx":915
  *         end += int(dy * end / h)
  * 
  *         l.height = end - l.y             # <<<<<<<<<<<<<<
  */
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_l, __pyx_n_s_y); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 915; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_5 = PyNumber_Subtract(__pyx_v_end, __pyx_t_7); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_end, __pyx_t_7); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 915; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    if (__Pyx_PyObject_SetAttrStr(__pyx_v_l, __pyx_n_s_height, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__Pyx_PyObject_SetAttrStr(__pyx_v_l, __pyx_n_s_height, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 915; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-    /* "renpy/text/textsupport.pyx":882
+    /* "renpy/text/textsupport.pyx":909
  *         old_x_offset = x_offset
  * 
  *     for l in lines:             # <<<<<<<<<<<<<<
@@ -10766,7 +11050,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_38tweak_glyph_spacing(CYTHO
   }
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "renpy/text/textsupport.pyx":861
+  /* "renpy/text/textsupport.pyx":888
  *         d.split = s.split
  * 
  * def tweak_glyph_spacing(list glyphs, list lines, double dx, double dy, double w, double h):             # <<<<<<<<<<<<<<
@@ -11351,6 +11635,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_line_spacing, __pyx_k_line_spacing, sizeof(__pyx_k_line_spacing), 0, 0, 1, 1},
   {&__pyx_n_s_linebreak_debug, __pyx_k_linebreak_debug, sizeof(__pyx_k_linebreak_debug), 0, 0, 1, 1},
   {&__pyx_n_s_linebreak_greedy, __pyx_k_linebreak_greedy, sizeof(__pyx_k_linebreak_greedy), 0, 0, 1, 1},
+  {&__pyx_n_s_linebreak_list, __pyx_k_linebreak_list, sizeof(__pyx_k_linebreak_list), 0, 0, 1, 1},
   {&__pyx_n_s_linebreak_nobreak, __pyx_k_linebreak_nobreak, sizeof(__pyx_k_linebreak_nobreak), 0, 0, 1, 1},
   {&__pyx_n_s_lines, __pyx_k_lines, sizeof(__pyx_k_lines), 0, 0, 1, 1},
   {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
@@ -11518,158 +11803,170 @@ static int __Pyx_InitCachedConstants(void) {
   /* "renpy/text/textsupport.pyx":402
  * 
  * 
- * def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):             # <<<<<<<<<<<<<<
+ * def linebreak_list(list glyphs):             # <<<<<<<<<<<<<<
  *     """
- *     Place the glyphs horizontally, without taking into account the indentation
+ *     Returns a list of unicode strings, one per broken line.
  */
-  __pyx_tuple__24 = PyTuple_Pack(8, __pyx_n_s_glyphs, __pyx_n_s_start_x, __pyx_n_s_first_indent, __pyx_n_s_rest_indent, __pyx_n_s_g, __pyx_n_s_old_g, __pyx_n_s_x, __pyx_n_s_maxx); if (unlikely(!__pyx_tuple__24)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__24 = PyTuple_Pack(4, __pyx_n_s_glyphs, __pyx_n_s_g, __pyx_n_s_rv, __pyx_n_s_line); if (unlikely(!__pyx_tuple__24)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_tuple__24);
   __Pyx_GIVEREF(__pyx_tuple__24);
-  __pyx_codeobj__25 = (PyObject*)__Pyx_PyCode_New(4, 0, 8, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__24, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_horizontal, 402, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_codeobj__25 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__24, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_linebreak_list, 402, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "renpy/text/textsupport.pyx":429
+ * 
+ * 
+ * def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):             # <<<<<<<<<<<<<<
+ *     """
+ *     Place the glyphs horizontally, without taking into account the indentation
+ */
+  __pyx_tuple__26 = PyTuple_Pack(8, __pyx_n_s_glyphs, __pyx_n_s_start_x, __pyx_n_s_first_indent, __pyx_n_s_rest_indent, __pyx_n_s_g, __pyx_n_s_old_g, __pyx_n_s_x, __pyx_n_s_maxx); if (unlikely(!__pyx_tuple__26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__26);
+  __Pyx_GIVEREF(__pyx_tuple__26);
+  __pyx_codeobj__27 = (PyObject*)__Pyx_PyCode_New(4, 0, 8, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_horizontal, 429, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__27)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":453
+  /* "renpy/text/textsupport.pyx":480
  *     return maxx
  * 
  * def place_vertical(list glyphs, int y, int spacing, int leading):             # <<<<<<<<<<<<<<
  *     """
  *     Vertically places the non-ruby glyphs. Returns a list of line end heights,
  */
-  __pyx_tuple__26 = PyTuple_Pack(15, __pyx_n_s_glyphs, __pyx_n_s_y, __pyx_n_s_spacing, __pyx_n_s_leading, __pyx_n_s_g, __pyx_n_s_gg, __pyx_n_s_pos, __pyx_n_s_sol, __pyx_n_s_len_glyphs, __pyx_n_s_i, __pyx_n_s_ascent, __pyx_n_s_line_spacing, __pyx_n_s_end_line, __pyx_n_s_rv, __pyx_n_s_l); if (unlikely(!__pyx_tuple__26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__26);
-  __Pyx_GIVEREF(__pyx_tuple__26);
-  __pyx_codeobj__27 = (PyObject*)__Pyx_PyCode_New(4, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_vertical, 453, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__27)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__28 = PyTuple_Pack(15, __pyx_n_s_glyphs, __pyx_n_s_y, __pyx_n_s_spacing, __pyx_n_s_leading, __pyx_n_s_g, __pyx_n_s_gg, __pyx_n_s_pos, __pyx_n_s_sol, __pyx_n_s_len_glyphs, __pyx_n_s_i, __pyx_n_s_ascent, __pyx_n_s_line_spacing, __pyx_n_s_end_line, __pyx_n_s_rv, __pyx_n_s_l); if (unlikely(!__pyx_tuple__28)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__28);
+  __Pyx_GIVEREF(__pyx_tuple__28);
+  __pyx_codeobj__29 = (PyObject*)__Pyx_PyCode_New(4, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__28, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_vertical, 480, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__29)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":541
+  /* "renpy/text/textsupport.pyx":568
  *     return rv, y - leading
  * 
  * def kerning(list glyphs, float amount):             # <<<<<<<<<<<<<<
  *     cdef Glyph g
  * 
  */
-  __pyx_tuple__28 = PyTuple_Pack(3, __pyx_n_s_glyphs, __pyx_n_s_amount, __pyx_n_s_g); if (unlikely(!__pyx_tuple__28)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__28);
-  __Pyx_GIVEREF(__pyx_tuple__28);
-  __pyx_codeobj__29 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__28, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_kerning, 541, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__29)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__30 = PyTuple_Pack(3, __pyx_n_s_glyphs, __pyx_n_s_amount, __pyx_n_s_g); if (unlikely(!__pyx_tuple__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__30);
+  __Pyx_GIVEREF(__pyx_tuple__30);
+  __pyx_codeobj__31 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__30, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_kerning, 568, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__31)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":548
+  /* "renpy/text/textsupport.pyx":575
  * 
  * 
  * def assign_times(float t, float gps, list glyphs):             # <<<<<<<<<<<<<<
  *     """
  *     Assign a display time to each glyph.
  */
-  __pyx_tuple__30 = PyTuple_Pack(5, __pyx_n_s_t, __pyx_n_s_gps, __pyx_n_s_glyphs, __pyx_n_s_tpg, __pyx_n_s_g); if (unlikely(!__pyx_tuple__30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__30);
-  __Pyx_GIVEREF(__pyx_tuple__30);
-  __pyx_codeobj__31 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__30, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_assign_times, 548, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__31)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__32 = PyTuple_Pack(5, __pyx_n_s_t, __pyx_n_s_gps, __pyx_n_s_glyphs, __pyx_n_s_tpg, __pyx_n_s_g); if (unlikely(!__pyx_tuple__32)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__32);
+  __Pyx_GIVEREF(__pyx_tuple__32);
+  __pyx_codeobj__33 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__32, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_assign_times, 575, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__33)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":584
+  /* "renpy/text/textsupport.pyx":611
  * 
  * 
  * def max_times(list l):             # <<<<<<<<<<<<<<
  *     """
  *     Set the max_time filed on each line.
  */
-  __pyx_tuple__32 = PyTuple_Pack(4, __pyx_n_s_l, __pyx_n_s_line, __pyx_n_s_g, __pyx_n_s_max_time); if (unlikely(!__pyx_tuple__32)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 584; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__32);
-  __Pyx_GIVEREF(__pyx_tuple__32);
-  __pyx_codeobj__33 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__32, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_max_times, 584, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__33)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 584; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__34 = PyTuple_Pack(4, __pyx_n_s_l, __pyx_n_s_line, __pyx_n_s_g, __pyx_n_s_max_time); if (unlikely(!__pyx_tuple__34)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 611; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__34);
+  __Pyx_GIVEREF(__pyx_tuple__34);
+  __pyx_codeobj__35 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__34, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_max_times, 611, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__35)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 611; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":605
+  /* "renpy/text/textsupport.pyx":632
  * 
  * 
  * def hyperlink_areas(list l):             # <<<<<<<<<<<<<<
  *     """
  *     Returns a list of (hyperlink, x, y, w, h) tuples, where each entry in
  */
-  __pyx_tuple__34 = PyTuple_Pack(10, __pyx_n_s_l, __pyx_n_s_line, __pyx_n_s_g, __pyx_n_s_gl, __pyx_n_s_len_gl, __pyx_n_s_pos, __pyx_n_s_max_x, __pyx_n_s_min_x, __pyx_n_s_hyperlink, __pyx_n_s_rv); if (unlikely(!__pyx_tuple__34)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 605; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__34);
-  __Pyx_GIVEREF(__pyx_tuple__34);
-  __pyx_codeobj__35 = (PyObject*)__Pyx_PyCode_New(1, 0, 10, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__34, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_hyperlink_areas, 605, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__35)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 605; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__36 = PyTuple_Pack(10, __pyx_n_s_l, __pyx_n_s_line, __pyx_n_s_g, __pyx_n_s_gl, __pyx_n_s_len_gl, __pyx_n_s_pos, __pyx_n_s_max_x, __pyx_n_s_min_x, __pyx_n_s_hyperlink, __pyx_n_s_rv); if (unlikely(!__pyx_tuple__36)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 632; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__36);
+  __Pyx_GIVEREF(__pyx_tuple__36);
+  __pyx_codeobj__37 = (PyObject*)__Pyx_PyCode_New(1, 0, 10, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__36, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_hyperlink_areas, 632, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__37)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 632; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":661
+  /* "renpy/text/textsupport.pyx":688
  * 
  * 
  * def mark_ruby_top(list l):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_tuple__36 = PyTuple_Pack(2, __pyx_n_s_l, __pyx_n_s_g); if (unlikely(!__pyx_tuple__36)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 661; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__36);
-  __Pyx_GIVEREF(__pyx_tuple__36);
-  __pyx_codeobj__37 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__36, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_mark_ruby_top, 661, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__37)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 661; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__38 = PyTuple_Pack(2, __pyx_n_s_l, __pyx_n_s_g); if (unlikely(!__pyx_tuple__38)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 688; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__38);
+  __Pyx_GIVEREF(__pyx_tuple__38);
+  __pyx_codeobj__39 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__38, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_mark_ruby_top, 688, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__39)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 688; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":668
+  /* "renpy/text/textsupport.pyx":695
  *         g.ruby = RUBY_TOP
  * 
  * def mark_ruby_bottom(list l):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_tuple__38 = PyTuple_Pack(2, __pyx_n_s_l, __pyx_n_s_g); if (unlikely(!__pyx_tuple__38)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 668; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__38);
-  __Pyx_GIVEREF(__pyx_tuple__38);
-  __pyx_codeobj__39 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__38, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_mark_ruby_bottom, 668, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__39)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 668; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__40 = PyTuple_Pack(2, __pyx_n_s_l, __pyx_n_s_g); if (unlikely(!__pyx_tuple__40)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 695; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__40);
+  __Pyx_GIVEREF(__pyx_tuple__40);
+  __pyx_codeobj__41 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__40, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_mark_ruby_bottom, 695, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__41)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 695; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":676
+  /* "renpy/text/textsupport.pyx":703
  * 
  * 
  * def place_ruby(list glyphs, int ruby_offset, int surf_width, int surf_height):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_tuple__40 = PyTuple_Pack(15, __pyx_n_s_glyphs, __pyx_n_s_ruby_offset, __pyx_n_s_surf_width, __pyx_n_s_surf_height, __pyx_n_s_g, __pyx_n_s_last_ruby, __pyx_n_s_len_glyphs, __pyx_n_s_x, __pyx_n_s_width, __pyx_n_s_min_x, __pyx_n_s_max_x, __pyx_n_s_y, __pyx_n_s_start_top, __pyx_n_s_pos, __pyx_n_s_i); if (unlikely(!__pyx_tuple__40)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__40);
-  __Pyx_GIVEREF(__pyx_tuple__40);
-  __pyx_codeobj__41 = (PyObject*)__Pyx_PyCode_New(4, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__40, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_ruby, 676, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__41)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__42 = PyTuple_Pack(15, __pyx_n_s_glyphs, __pyx_n_s_ruby_offset, __pyx_n_s_surf_width, __pyx_n_s_surf_height, __pyx_n_s_g, __pyx_n_s_last_ruby, __pyx_n_s_len_glyphs, __pyx_n_s_x, __pyx_n_s_width, __pyx_n_s_min_x, __pyx_n_s_max_x, __pyx_n_s_y, __pyx_n_s_start_top, __pyx_n_s_pos, __pyx_n_s_i); if (unlikely(!__pyx_tuple__42)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__42);
+  __Pyx_GIVEREF(__pyx_tuple__42);
+  __pyx_codeobj__43 = (PyObject*)__Pyx_PyCode_New(4, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__42, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_place_ruby, 703, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__43)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":751
+  /* "renpy/text/textsupport.pyx":778
  *         last_ruby = RUBY_TOP
  * 
  * def align_and_justify(list lines, int width, float text_align, bint justify):             # <<<<<<<<<<<<<<
  *     """
  *     Handle text alignment and justification.
  */
-  __pyx_tuple__42 = PyTuple_Pack(11, __pyx_n_s_lines, __pyx_n_s_width, __pyx_n_s_text_align, __pyx_n_s_justify, __pyx_n_s_l, __pyx_n_s_g, __pyx_n_s_max_x, __pyx_n_s_spaces, __pyx_n_s_justify_offset, __pyx_n_s_justify_per_space, __pyx_n_s_offset); if (unlikely(!__pyx_tuple__42)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__42);
-  __Pyx_GIVEREF(__pyx_tuple__42);
-  __pyx_codeobj__43 = (PyObject*)__Pyx_PyCode_New(4, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__42, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_align_and_justify, 751, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__43)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__44 = PyTuple_Pack(11, __pyx_n_s_lines, __pyx_n_s_width, __pyx_n_s_text_align, __pyx_n_s_justify, __pyx_n_s_l, __pyx_n_s_g, __pyx_n_s_max_x, __pyx_n_s_spaces, __pyx_n_s_justify_offset, __pyx_n_s_justify_per_space, __pyx_n_s_offset); if (unlikely(!__pyx_tuple__44)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__44);
+  __Pyx_GIVEREF(__pyx_tuple__44);
+  __pyx_codeobj__45 = (PyObject*)__Pyx_PyCode_New(4, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__44, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_align_and_justify, 778, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__45)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":815
+  /* "renpy/text/textsupport.pyx":842
  *                 g.x += offset
  * 
  * def reverse_lines(list glyphs):             # <<<<<<<<<<<<<<
  *     """
  *     Reverses each line in glyphs, while keeping the lines themselves in
  */
-  __pyx_tuple__44 = PyTuple_Pack(4, __pyx_n_s_glyphs, __pyx_n_s_rv, __pyx_n_s_block, __pyx_n_s_g); if (unlikely(!__pyx_tuple__44)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__44);
-  __Pyx_GIVEREF(__pyx_tuple__44);
-  __pyx_codeobj__45 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__44, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_reverse_lines, 815, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__45)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__46 = PyTuple_Pack(4, __pyx_n_s_glyphs, __pyx_n_s_rv, __pyx_n_s_block, __pyx_n_s_g); if (unlikely(!__pyx_tuple__46)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__46);
+  __Pyx_GIVEREF(__pyx_tuple__46);
+  __pyx_codeobj__47 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__46, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_reverse_lines, 842, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__47)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":845
+  /* "renpy/text/textsupport.pyx":872
  *     return rv
  * 
  * def copy_splits(list source, list dest):             # <<<<<<<<<<<<<<
  *     """
  *     Copies break and timing information from one list of glyphs
  */
-  __pyx_tuple__46 = PyTuple_Pack(5, __pyx_n_s_source, __pyx_n_s_dest, __pyx_n_s_s, __pyx_n_s_d, __pyx_n_s_i); if (unlikely(!__pyx_tuple__46)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__46);
-  __Pyx_GIVEREF(__pyx_tuple__46);
-  __pyx_codeobj__47 = (PyObject*)__Pyx_PyCode_New(2, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__46, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_copy_splits, 845, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__47)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__48 = PyTuple_Pack(5, __pyx_n_s_source, __pyx_n_s_dest, __pyx_n_s_s, __pyx_n_s_d, __pyx_n_s_i); if (unlikely(!__pyx_tuple__48)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__48);
+  __Pyx_GIVEREF(__pyx_tuple__48);
+  __pyx_codeobj__49 = (PyObject*)__Pyx_PyCode_New(2, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__48, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_copy_splits, 872, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__49)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "renpy/text/textsupport.pyx":861
+  /* "renpy/text/textsupport.pyx":888
  *         d.split = s.split
  * 
  * def tweak_glyph_spacing(list glyphs, list lines, double dx, double dy, double w, double h):             # <<<<<<<<<<<<<<
  *     cdef Glyph g
  * 
  */
-  __pyx_tuple__48 = PyTuple_Pack(11, __pyx_n_s_glyphs, __pyx_n_s_lines, __pyx_n_s_dx, __pyx_n_s_dy, __pyx_n_s_w, __pyx_n_s_h, __pyx_n_s_g, __pyx_n_s_old_x_offset, __pyx_n_s_x_offset, __pyx_n_s_l, __pyx_n_s_end); if (unlikely(!__pyx_tuple__48)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_tuple__48);
-  __Pyx_GIVEREF(__pyx_tuple__48);
-  __pyx_codeobj__49 = (PyObject*)__Pyx_PyCode_New(6, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__48, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_tweak_glyph_spacing, 861, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__49)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_tuple__50 = PyTuple_Pack(11, __pyx_n_s_glyphs, __pyx_n_s_lines, __pyx_n_s_dx, __pyx_n_s_dy, __pyx_n_s_w, __pyx_n_s_h, __pyx_n_s_g, __pyx_n_s_old_x_offset, __pyx_n_s_x_offset, __pyx_n_s_l, __pyx_n_s_end); if (unlikely(!__pyx_tuple__50)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__50);
+  __Pyx_GIVEREF(__pyx_tuple__50);
+  __pyx_codeobj__51 = (PyObject*)__Pyx_PyCode_New(6, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__50, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_tom_ab_renpy_renpy_text_te, __pyx_n_s_tweak_glyph_spacing, 888, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__51)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -12503,157 +12800,169 @@ PyMODINIT_FUNC PyInit_textsupport(void)
   /* "renpy/text/textsupport.pyx":402
  * 
  * 
+ * def linebreak_list(list glyphs):             # <<<<<<<<<<<<<<
+ *     """
+ *     Returns a list of unicode strings, one per broken line.
+ */
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_15linebreak_list, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_linebreak_list, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "renpy/text/textsupport.pyx":429
+ * 
+ * 
  * def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):             # <<<<<<<<<<<<<<
  *     """
  *     Place the glyphs horizontally, without taking into account the indentation
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_15place_horizontal, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_17place_horizontal, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_horizontal, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_horizontal, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":453
+  /* "renpy/text/textsupport.pyx":480
  *     return maxx
  * 
  * def place_vertical(list glyphs, int y, int spacing, int leading):             # <<<<<<<<<<<<<<
  *     """
  *     Vertically places the non-ruby glyphs. Returns a list of line end heights,
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_17place_vertical, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_19place_vertical, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_vertical, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_vertical, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":541
+  /* "renpy/text/textsupport.pyx":568
  *     return rv, y - leading
  * 
  * def kerning(list glyphs, float amount):             # <<<<<<<<<<<<<<
  *     cdef Glyph g
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_19kerning, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_21kerning, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_kerning, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_kerning, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 568; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":548
+  /* "renpy/text/textsupport.pyx":575
  * 
  * 
  * def assign_times(float t, float gps, list glyphs):             # <<<<<<<<<<<<<<
  *     """
  *     Assign a display time to each glyph.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_21assign_times, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_23assign_times, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_assign_times, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 548; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_assign_times, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":584
+  /* "renpy/text/textsupport.pyx":611
  * 
  * 
  * def max_times(list l):             # <<<<<<<<<<<<<<
  *     """
  *     Set the max_time filed on each line.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_23max_times, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 584; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_25max_times, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 611; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_max_times, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 584; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_max_times, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 611; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":605
+  /* "renpy/text/textsupport.pyx":632
  * 
  * 
  * def hyperlink_areas(list l):             # <<<<<<<<<<<<<<
  *     """
  *     Returns a list of (hyperlink, x, y, w, h) tuples, where each entry in
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_25hyperlink_areas, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 605; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_27hyperlink_areas, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 632; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_hyperlink_areas, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 605; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_hyperlink_areas, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 632; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":661
+  /* "renpy/text/textsupport.pyx":688
  * 
  * 
  * def mark_ruby_top(list l):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_27mark_ruby_top, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 661; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_29mark_ruby_top, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 688; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_mark_ruby_top, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 661; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_mark_ruby_top, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 688; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":668
+  /* "renpy/text/textsupport.pyx":695
  *         g.ruby = RUBY_TOP
  * 
  * def mark_ruby_bottom(list l):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_29mark_ruby_bottom, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 668; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_31mark_ruby_bottom, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 695; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_mark_ruby_bottom, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 668; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_mark_ruby_bottom, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 695; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":676
+  /* "renpy/text/textsupport.pyx":703
  * 
  * 
  * def place_ruby(list glyphs, int ruby_offset, int surf_width, int surf_height):             # <<<<<<<<<<<<<<
  * 
  *     cdef Glyph g
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_31place_ruby, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_33place_ruby, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_ruby, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_place_ruby, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":751
+  /* "renpy/text/textsupport.pyx":778
  *         last_ruby = RUBY_TOP
  * 
  * def align_and_justify(list lines, int width, float text_align, bint justify):             # <<<<<<<<<<<<<<
  *     """
  *     Handle text alignment and justification.
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_33align_and_justify, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_35align_and_justify, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_align_and_justify, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 751; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_align_and_justify, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 778; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":815
+  /* "renpy/text/textsupport.pyx":842
  *                 g.x += offset
  * 
  * def reverse_lines(list glyphs):             # <<<<<<<<<<<<<<
  *     """
  *     Reverses each line in glyphs, while keeping the lines themselves in
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_35reverse_lines, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_37reverse_lines, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_reverse_lines, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_reverse_lines, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":845
+  /* "renpy/text/textsupport.pyx":872
  *     return rv
  * 
  * def copy_splits(list source, list dest):             # <<<<<<<<<<<<<<
  *     """
  *     Copies break and timing information from one list of glyphs
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_37copy_splits, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_39copy_splits, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_copy_splits, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_copy_splits, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "renpy/text/textsupport.pyx":861
+  /* "renpy/text/textsupport.pyx":888
  *         d.split = s.split
  * 
  * def tweak_glyph_spacing(list glyphs, list lines, double dx, double dy, double w, double h):             # <<<<<<<<<<<<<<
  *     cdef Glyph g
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_39tweak_glyph_spacing, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_5renpy_4text_11textsupport_41tweak_glyph_spacing, NULL, __pyx_n_s_renpy_text_textsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_tweak_glyph_spacing, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 861; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_tweak_glyph_spacing, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 888; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "renpy/text/textsupport.pyx":1
diff --git a/module/generate_linebreak.py b/module/generate_linebreak.py
index 670adb7..614dadb 100644
--- a/module/generate_linebreak.py
+++ b/module/generate_linebreak.py
@@ -3,6 +3,8 @@
 # Based on: http://www.unicode.org/Public/UNIDATA/LineBreak.txt
 # Based on: http://unicode.org/reports/tr14/#PairBasedImplementation
 
+from __future__ import print_function
+
 import re
 
 breaking = """OP    CL    CP    QU    GL    NS    EX    SY    IS    PR    PO    NU    AL    HL    ID    IN    HY    BA    BB    B2    ZW    CM    WJ    H2    H3    JL    JV    JT    RI
@@ -41,24 +43,24 @@ other_classes = " PITCH AI BK CB CJ CR LF NL SA SG SP XX"
 
 lines = breaking.split("\n")
 
-print "# This is generated code. Do not edit."
-print
+print("# This is generated code. Do not edit.")
+print()
 
 # A map from character class to the number that represents it.
 cl = { }
 
 
 for i, j in enumerate((lines[0] + other_classes).split()):
-    print "cdef char BC_{} = {}".format(j, i)
+    print(("cdef char BC_{} = {}".format(j, i)))
     cl[j] = i
 
-print "CLASSES = {"
+print("CLASSES = {")
 
 for i, j in enumerate((lines[0] + other_classes).split()):
-    print "    \"{}\" : {},".format(j, i)
+    print(("    \"{}\" : {},".format(j, i)))
     cl[j] = i
 
-print "}"
+print("}")
 
 rules = [ ]
 
@@ -66,8 +68,8 @@ for l in lines[1:]:
     for c in l.split()[1:]:
         rules.append(c)
 
-print
-print "cdef char *break_rules = \"" + "".join(rules) + "\""
+print()
+print(("cdef char *break_rules = \"" + "".join(rules) + "\""))
 
 cc = [ 'XX' ] * 65536
 
@@ -98,6 +100,7 @@ for l in file("LineBreak.txt"):
         cc[start] = m.group(2)
         continue
 
+
 def generate(name, func):
 
     ncc = [ ]
@@ -108,7 +111,8 @@ def generate(name, func):
     assert "CJ" not in ncc
     assert "AI" not in ncc
 
-    print "cdef char *break_" + name + " = \"" + "".join("\\x%02x" % cl[i] for i in ncc) + "\""
+    print(("cdef char *break_" + name + " = \"" + "".join("\\x%02x" % cl[i] for i in ncc) + "\""))
+
 
 def western(i, cl):
     if cl == "CJ":
@@ -127,6 +131,7 @@ centered = [ 0x003A, 0x003B, 0x30FB, 0xff1a, 0xff1b, 0xff65, 0x0021, 0x003f, 0x2
 postfixes = [ 0x0025, 0x00A2, 0x00B0, 0x2030, 0x2032, 0x2033, 0x2103, 0xff05, 0xffe0 ]
 prefixes = [ 0x0024, 0x00a3, 0x00a5, 0x20ac, 0x2116, 0xff04, 0xffe1, 0xffe5 ]
 
+
 def cjk_strict(i, cl):
 
     if cl == "CJ":
@@ -136,6 +141,7 @@ def cjk_strict(i, cl):
 
     return cl
 
+
 def cjk_normal(i, cl):
 
     if i in hyphens:
@@ -148,6 +154,7 @@ def cjk_normal(i, cl):
 
     return cl
 
+
 def cjk_loose(i, cl):
 
     if i in hyphens:
diff --git a/module/generate_styles.py b/module/generate_styles.py
index bba5b46..4e6efca 100644
--- a/module/generate_styles.py
+++ b/module/generate_styles.py
@@ -21,15 +21,15 @@
 
 from __future__ import print_function, unicode_literals, division, absolute_import
 
-str = unicode # @ReservedAssignment
+str = unicode  # @ReservedAssignment
 
 import collections
 import os
 
 try:
-    from io import StringIO # @UnusedImport
+    from io import StringIO  # @UnusedImport
 except:
-    from StringIO import StringIO # @Reimport
+    from StringIO import StringIO  # @Reimport
 
 # Paths
 BASE = os.path.dirname(os.path.abspath(__file__))
@@ -54,7 +54,9 @@ def sorted_dict(**kwargs):
 # A map from prefix name to Prefix object.
 prefixes = collections.OrderedDict()
 
+
 class Prefix(object):
+
     def __init__(self, index, name, priority, alts):
 
         # The index of where this prefix is stored in memory, or -1 if this
@@ -122,97 +124,97 @@ PREFIX_SEARCH = {
 # to a function that is called when it is set, or None if no such function
 # is needed.
 style_properties = sorted_dict(
-    activate_sound = None,
-    adjust_spacing = None,
-    aft_bar = 'none_is_null',
-    aft_gutter = None,
-    alt = None,
-    antialias = None,
-    vertical = None,
-    background = 'renpy.easy.displayable_or_none',
-    bar_invert = None,
-    bar_resizing = None,
-    unscrollable = None,
-    bar_vertical = None,
-    black_color = 'renpy.easy.color',
-    bold = None,
-    bottom_margin = None,
-    bottom_padding = None,
-    box_layout = None,
-    box_reverse = None,
-    box_wrap = None,
-    caret = 'renpy.easy.displayable_or_none',
-    child = 'renpy.easy.displayable_or_none',
-    clipping = None,
-    color = 'renpy.easy.color',
-    debug = None,
-    drop_shadow = None,
-    drop_shadow_color = 'renpy.easy.color',
-    first_indent = None,
-    first_spacing = None,
-    fit_first = None,
-    focus_mask = 'expand_focus_mask',
-    focus_rect = None,
-    font = None,
-    fore_bar = 'none_is_null',
-    fore_gutter = None,
-    foreground = 'renpy.easy.displayable_or_none',
-    hinting = None,
-    hover_sound = None,
+    activate_sound=None,
+    adjust_spacing=None,
+    aft_bar='none_is_null',
+    aft_gutter=None,
+    alt=None,
+    antialias=None,
+    vertical=None,
+    background='renpy.easy.displayable_or_none',
+    bar_invert=None,
+    bar_resizing=None,
+    unscrollable=None,
+    bar_vertical=None,
+    black_color='renpy.easy.color',
+    bold=None,
+    bottom_margin=None,
+    bottom_padding=None,
+    box_layout=None,
+    box_reverse=None,
+    box_wrap=None,
+    caret='renpy.easy.displayable_or_none',
+    child='renpy.easy.displayable_or_none',
+    clipping=None,
+    color='renpy.easy.color',
+    debug=None,
+    drop_shadow=None,
+    drop_shadow_color='renpy.easy.color',
+    first_indent=None,
+    first_spacing=None,
+    fit_first=None,
+    focus_mask='expand_focus_mask',
+    focus_rect=None,
+    font=None,
+    fore_bar='none_is_null',
+    fore_gutter=None,
+    foreground='renpy.easy.displayable_or_none',
+    hinting=None,
+    hover_sound=None,
     hyperlink_functions=None,
-    italic = None,
-    justify = None,
-    kerning = None,
-    key_events = None,
-    keyboard_focus = None,
-    language = None,
-    layout = None,
-    line_leading = None,
-    left_margin = None,
+    italic=None,
+    justify=None,
+    kerning=None,
+    key_events=None,
+    keyboard_focus=None,
+    language=None,
+    layout=None,
+    line_leading=None,
+    left_margin=None,
     line_overlap_split=None,
-    left_padding = None,
-    line_spacing = None,
-    mouse = None,
-    min_width = None,
-    newline_indent = None,
-    order_reverse = None,
-    outlines = 'expand_outlines',
-    rest_indent = None,
-    right_margin = None,
-    right_padding = None,
-    ruby_style = None,
-    size = None,
-    size_group = None,
-    slow_abortable = None,
-    slow_cps = None,
-    slow_cps_multiplier = None,
-    spacing = None,
-    strikethrough = None,
-    subtitle_width = None,
-    subpixel = None,
-    text_y_fudge = None,
-    text_align = None,
-    thumb = 'none_is_null',
-    thumb_offset = None,
-    thumb_shadow = 'none_is_null',
-    time_policy = None,
-    top_margin = None,
-    top_padding = None,
-    underline = None,
-    xanchor = 'expand_anchor',
-    xfill = None,
-    xfit = None,
-    xmaximum = None,
-    xminimum = None,
-    xoffset = None,
-    xpos = None,
-    yanchor = 'expand_anchor',
-    yfill = None,
-    yfit = None,
-    ymaximum = None,
-    yminimum = None,
-    yoffset = None,
-    ypos = None,
+    left_padding=None,
+    line_spacing=None,
+    mouse=None,
+    min_width=None,
+    newline_indent=None,
+    order_reverse=None,
+    outlines='expand_outlines',
+    rest_indent=None,
+    right_margin=None,
+    right_padding=None,
+    ruby_style=None,
+    size=None,
+    size_group=None,
+    slow_abortable=None,
+    slow_cps=None,
+    slow_cps_multiplier=None,
+    spacing=None,
+    strikethrough=None,
+    subtitle_width=None,
+    subpixel=None,
+    text_y_fudge=None,
+    text_align=None,
+    thumb='none_is_null',
+    thumb_offset=None,
+    thumb_shadow='none_is_null',
+    time_policy=None,
+    top_margin=None,
+    top_padding=None,
+    underline=None,
+    xanchor='expand_anchor',
+    xfill=None,
+    xfit=None,
+    xmaximum=None,
+    xminimum=None,
+    xoffset=None,
+    xpos=None,
+    yanchor='expand_anchor',
+    yfill=None,
+    yfit=None,
+    ymaximum=None,
+    yminimum=None,
+    yoffset=None,
+    ypos=None,
     )
 
 # Properties that take displayables that should be given the right set
@@ -246,123 +248,123 @@ style_property_count = len(style_properties)
 #   numeric value, or None to not change the argument.
 synthetic_properties = sorted_dict(
 
-    margin = [
+    margin=[
         ('left_margin', 'index_0'),
         ('top_margin', 'index_1'),
         ('right_margin', 'index_2_or_0'),
         ('bottom_margin', 'index_3_or_1'),
         ],
 
-    xmargin = [
+    xmargin=[
         ('left_margin', None),
         ('right_margin', None)
         ],
 
-    ymargin = [
+    ymargin=[
         ('top_margin', None),
         ('bottom_margin', None),
         ],
 
-    xalign = [
+    xalign=[
         ('xpos', None),
         ('xanchor', None),
         ],
 
-    yalign = [
+    yalign=[
         ('ypos', None),
         ('yanchor', None),
         ],
 
-    padding = [
+    padding=[
         ('left_padding', 'index_0'),
         ('top_padding', 'index_1'),
         ('right_padding', 'index_2_or_0'),
         ('bottom_padding', 'index_3_or_1'),
         ],
 
-    xpadding = [
+    xpadding=[
         ('left_padding', None),
         ('right_padding', None),
         ],
 
-    ypadding = [
+    ypadding=[
         ('top_padding', None),
         ('bottom_padding', None),
         ],
 
-    minwidth = [ ('min_width', None) ],
-    textalign = [ ('text_align', None) ],
-    slow_speed = [ ('slow_cps', None) ],
-    enable_hover = [ ],
+    minwidth=[ ('min_width', None) ],
+    textalign=[ ('text_align', None) ],
+    slow_speed=[ ('slow_cps', None) ],
+    enable_hover=[ ],
 
-    left_gutter = [ ('fore_gutter', None) ],
-    right_gutter = [ ('aft_gutter', None) ],
-    top_gutter = [ ('fore_gutter', None) ],
-    bottom_gutter = [ ('aft_gutter', None) ],
+    left_gutter=[ ('fore_gutter', None) ],
+    right_gutter=[ ('aft_gutter', None) ],
+    top_gutter=[ ('fore_gutter', None) ],
+    bottom_gutter=[ ('aft_gutter', None) ],
 
-    left_bar = [ ('fore_bar', None) ],
-    right_bar = [ ('aft_bar', None) ],
-    top_bar = [ ('fore_bar', None) ],
-    bottom_bar = [ ('aft_bar', None) ],
+    left_bar=[ ('fore_bar', None) ],
+    right_bar=[ ('aft_bar', None) ],
+    top_bar=[ ('fore_bar', None) ],
+    bottom_bar=[ ('aft_bar', None) ],
 
-    base_bar = [
+    base_bar=[
         ('fore_bar', None),
         ('aft_bar', None),
         ],
 
-    box_spacing = [ ( 'spacing', None ) ],
-    box_first_spacing = [ ( 'first_spacing', None) ],
+    box_spacing=[ ( 'spacing', None ) ],
+    box_first_spacing=[ ( 'first_spacing', None) ],
 
-    pos = [
+    pos=[
         ('xpos', 'index_0'),
         ('ypos', 'index_1'),
         ],
 
-    anchor = [
+    anchor=[
         ('xanchor', 'index_0'),
         ('yanchor', 'index_1'),
         ],
 
-    offset = [
+    offset=[
         ('xoffset', 'index_0'),
         ('yoffset', 'index_1'),
         ],
 
-    align = [
+    align=[
         ('xpos', 'index_0'),
         ('ypos', 'index_1'),
         ('xanchor', 'index_0'),
         ('yanchor', 'index_1'),
         ],
 
-    maximum = [
+    maximum=[
         ('xmaximum', 'index_0'),
         ('ymaximum', 'index_1'),
         ],
 
-    minimum = [
+    minimum=[
         ('xminimum', 'index_0'),
         ('yminimum', 'index_1'),
         ],
 
-    xsize = [
+    xsize=[
         ('xminimum', None),
         ('xmaximum', None),
         ],
 
-    ysize = [
+    ysize=[
         ('yminimum', None),
         ('ymaximum', None),
         ],
 
-    xysize = [
+    xysize=[
         ('xminimum', 'index_0'),
         ('xmaximum', 'index_0'),
         ('yminimum', 'index_1'),
         ('ymaximum', 'index_1'),
         ],
 
-    area = [
+    area=[
         ('xpos', 'index_0'),
         ('ypos', 'index_1'),
         ('xanchor', 0),
@@ -375,12 +377,12 @@ synthetic_properties = sorted_dict(
         ('yminimum', 'index_3'),
         ],
 
-    xcenter = [
+    xcenter=[
         ('xpos', None),
         ('xanchor', 0.5),
         ],
 
-    ycenter = [
+    ycenter=[
         ('ypos', None),
         ('yanchor', 0.5),
         ],
@@ -397,6 +399,7 @@ all_properties.update(synthetic_properties)
 # Code Generation
 ################################################################################
 
+
 class CodeGen(object):
     """
     Utility class for code generation.
@@ -467,6 +470,7 @@ def generate_constants():
 
     g.close()
 
+
 def generate_property_function(g, prefix, propname, properties):
 
     name = prefix.name + propname
@@ -498,14 +502,12 @@ def generate_property_function(g, prefix, propname, properties):
 
             if stylepropname in displayable_properties:
                 g.write("assign_prefixed({}, cache, cache_priorities, priority, {}, '{}') # {}{}",
-                    alt * len(style_properties) + style_property_index[stylepropname],
-                    value, alt_name, alt_name, stylepropname)
+                        alt * len(style_properties) + style_property_index[stylepropname],
+                        value, alt_name, alt_name, stylepropname)
             else:
                 g.write("assign({}, cache, cache_priorities, priority, <PyObject *> {}) # {}{}",
-                    alt * len(style_properties) + style_property_index[stylepropname],
-                    value, alt_name, stylepropname)
-
-
+                        alt * len(style_properties) + style_property_index[stylepropname],
+                        value, alt_name, stylepropname)
 
     g.write("return 0")
     g.dedent()
@@ -516,6 +518,7 @@ def generate_property_function(g, prefix, propname, properties):
 
     pass
 
+
 def generate_property_functions():
     """
     This generates code that defines the property functions.
@@ -532,6 +535,7 @@ def generate_property_functions():
 
         g.close()
 
+
 def generate_property(g, propname):
     """
     This generates the code for a single property on the style object.
@@ -561,6 +565,7 @@ def generate_property(g, propname):
     g.dedent()
     g.write("")
 
+
 def generate_properties():
 
     g = CodeGen(module_gen + "/styleclass.pxi")
@@ -576,6 +581,7 @@ def generate_properties():
     g.dedent()
     g.close()
 
+
 def generate_sets():
     """
     Generates code for sets of properties.
diff --git a/module/renpysound_core.c b/module/renpysound_core.c
index 3c055e7..c6f1edd 100644
--- a/module/renpysound_core.c
+++ b/module/renpysound_core.c
@@ -52,6 +52,7 @@ int media_video_ready(struct MediaState *ms);
 SDL_Surface *media_read_video(struct MediaState *ms);
 
 double media_duration(struct MediaState *ms);
+void media_wait_ready(struct MediaState *ms);
 
 /* The current Python. */
 PyInterpreterState* interp;
@@ -921,6 +922,13 @@ void RPS_unpause_all(void) {
     ENTER();
 
     for (i = 0; i < num_channels; i++) {
+        if (channels[i].playing && channels[i].paused) {
+            media_wait_ready(channels[i].playing);
+        }
+    }
+
+
+    for (i = 0; i < num_channels; i++) {
         channels[i].paused = 0;
     }
 
diff --git a/module/setup.py b/module/setup.py
index ed909a1..8fbf2d5 100644
--- a/module/setup.py
+++ b/module/setup.py
@@ -21,6 +21,8 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
+
 import platform
 import sys
 import os
@@ -69,10 +71,10 @@ include("png.h")
 include("SDL.h", directory="SDL2")
 include("ft2build.h")
 include("freetype/freetype.h", directory="freetype2", optional=True) or include("freetype.h", directory="freetype2")
-include("libavutil/avstring.h",   directory="ffmpeg", optional=True) or include("libavutil/avstring.h")
+include("libavutil/avstring.h", directory="ffmpeg", optional=True) or include("libavutil/avstring.h")
 include("libavformat/avformat.h", directory="ffmpeg", optional=True) or include("libavformat/avformat.h")
-include("libavcodec/avcodec.h",   directory="ffmpeg", optional=True) or include("libavcodec/avcodec.h")
-include("libswscale/swscale.h",   directory="ffmpeg", optional=True) or include("libswscale/swscale.h")
+include("libavcodec/avcodec.h", directory="ffmpeg", optional=True) or include("libavcodec/avcodec.h")
+include("libswscale/swscale.h", directory="ffmpeg", optional=True) or include("libswscale/swscale.h")
 include("GL/glew.h")
 include("pygame_sdl2/pygame_sdl2.h", directory="python{}.{}".format(sys.version_info.major, sys.version_info.minor))
 
@@ -148,7 +150,7 @@ if has_swscale:
 cython(
     "renpy.audio.renpysound",
     [ "renpysound_core.c", "ffmedia.c" ],
-    libs = sdl + sound,
+    libs=sdl + sound,
     define_macros=macros)
 
 # renpy
@@ -223,7 +225,7 @@ cython("renpy.text.texwrap")
 cython(
     "renpy.text.ftfont",
     [ "ftsupport.c", "ttgsubtable.c" ],
-    libs = sdl + [ 'freetype', 'z', 'm' ])
+    libs=sdl + [ 'freetype', 'z', 'm' ])
 
 find_unnecessary_gen()
 
@@ -232,7 +234,7 @@ sys.path.insert(0, '..')
 
 import renpy
 
-setuplib.setup("Ren'Py", renpy.version[7:]) # @UndefinedVariable
+setuplib.setup("Ren'Py", renpy.version[7:])  # @UndefinedVariable
 
 if not has_fribidi:
-    print "Warning: Did not include fribidi."
+    print("Warning: Did not include fribidi.")
diff --git a/module/setuplib.py b/module/setuplib.py
index 79ce5cc..f08964f 100644
--- a/module/setuplib.py
+++ b/module/setuplib.py
@@ -22,6 +22,8 @@
 # This file encapsulates much of the complexity of the Ren'Py build process,
 # so setup.py can be clean by comparison.
 
+from __future__ import print_function
+
 import os
 import sys
 import re
@@ -105,9 +107,9 @@ def include(header, directory=None, optional=True):
         return False
 
     if directory is None:
-        print "Could not find required header {0}.".format(header)
+        print("Could not find required header {0}.".format(header))
     else:
-        print "Could not find required header {0}/{1}.".format(directory, header)
+        print("Could not find required header {0}/{1}.".format(directory, header))
 
     sys.exit(-1)
 
@@ -142,7 +144,7 @@ def library(name, optional=False):
     if optional:
         return False
 
-    print "Could not find required library {0}.".format(name)
+    print("Could not find required library {0}.".format(name))
     sys.exit(-1)
 
 # A list of extension objects that we use.
@@ -151,6 +153,7 @@ extensions = [ ]
 # A list of macros that are defined for all modules.
 global_macros = [ ]
 
+
 def cmodule(name, source, libs=[], define_macros=[], language="c"):
     """
     Compiles the python module `name` from the files given in
@@ -177,6 +180,7 @@ def cmodule(name, source, libs=[], define_macros=[], language="c"):
 
 necessary_gen = [ ]
 
+
 def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None, language="c"):
     """
     Compiles a cython module. This takes care of regenerating it as necessary
@@ -198,7 +202,7 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None
     elif os.path.exists(fn):
         pass
     else:
-        print "Could not find {0}.".format(fn)
+        print("Could not find {0}.".format(fn))
         sys.exit(-1)
 
     module_dir = os.path.dirname(fn)
@@ -259,19 +263,19 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None
         elif os.path.exists(dep_fn):
             pass
         else:
-            print "{0} depends on {1}, which can't be found.".format(fn, dep_fn)
+            print("{0} depends on {1}, which can't be found.".format(fn, dep_fn))
             sys.exit(-1)
 
         if os.path.getmtime(dep_fn) > c_mtime:
             out_of_date = True
 
     if out_of_date and not cython_command:
-        print "WARNING:", name, "is out of date, but RENPY_CYTHON isn't set."
+        print("WARNING:", name, "is out of date, but RENPY_CYTHON isn't set.")
         out_of_date = False
 
     # If the file is out of date, regenerate it.
     if out_of_date:
-        print name, "is out of date."
+        print(name, "is out of date.")
 
         try:
             import subprocess
@@ -302,9 +306,9 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None
                 c_fn])
 
         except subprocess.CalledProcessError, e:
-            print
-            print str(e)
-            print
+            print()
+            print(str(e))
+            print()
             sys.exit(-1)
 
     # Build the module normally once we have the c file.
@@ -315,6 +319,7 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None
 
         cmodule(name, [ c_fn ] + source, libs=libs, define_macros=define_macros, language=language)
 
+
 def find_unnecessary_gen():
 
     for i in os.listdir(gen):
@@ -324,11 +329,12 @@ def find_unnecessary_gen():
         if i in necessary_gen:
             continue
 
-        print "Unnecessary file", os.path.join(gen, i)
+        print("Unnecessary file", os.path.join(gen, i))
 
 
 py_modules = [ ]
 
+
 def pymodule(name):
     """
     Causes a python module to be included in the build.
@@ -336,6 +342,7 @@ def pymodule(name):
 
     py_modules.append(name)
 
+
 def copyfile(source, dest, replace=None, replace_with=None):
     """
     Copy `source` to `dest`, preserving the modification time.
@@ -367,16 +374,17 @@ def copyfile(source, dest, replace=None, replace_with=None):
     import shutil
     shutil.copystat(sfn, dfn)
 
+
 def setup(name, version):
     """
     Calls the distutils setup function.
     """
 
     distutils.core.setup(
-        name = name,
-        version = version,
-        ext_modules = extensions,
-        py_modules = py_modules,
+        name=name,
+        version=version,
+        ext_modules=extensions,
+        py_modules=py_modules,
         )
 
 # Ensure the gen directory exists.
diff --git a/renpy.py b/renpy.py
index e077c0d..f081778 100755
--- a/renpy.py
+++ b/renpy.py
@@ -25,6 +25,8 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
+
 import os
 import sys
 import warnings
@@ -33,16 +35,21 @@ import warnings
 
 # Given the Ren'Py base directory (usually the directory containing
 # this file), this is expected to return the path to the common directory.
+
+
 def path_to_common(renpy_base):
     return renpy_base + "/renpy/common"
 
 # Given a directory holding a Ren'Py game, this is expected to return
 # the path to a directory that will hold save files.
+
+
 def path_to_saves(gamedir, save_directory=None):
-    import renpy #@UnresolvedImport
+    import renpy  # @UnresolvedImport
 
     if save_directory is None:
         save_directory = renpy.config.save_directory
+        save_directory = renpy.exports.fsencode(save_directory)
 
     # Makes sure the permissions are right on the save directory.
     def test_writable(d):
@@ -55,7 +62,6 @@ def path_to_saves(gamedir, save_directory=None):
         except:
             return False
 
-
     # Android.
     if renpy.android:
         paths = [
@@ -68,7 +74,7 @@ def path_to_saves(gamedir, save_directory=None):
             if os.path.isdir(rv) and test_writable(rv):
                 break
 
-        print "Saving to", rv
+        print("Saving to", rv)
 
         # We return the last path as the default.
 
@@ -94,7 +100,7 @@ def path_to_saves(gamedir, save_directory=None):
         except:
             rv = url.path.UTF8String().decode("utf-8")
 
-        print "Saving to", rv
+        print("Saving to", rv)
         return rv
 
     # No save directory given.
@@ -147,7 +153,7 @@ try:
     import ast; ast
 except:
     raise
-    print "Ren'Py requires at least python 2.6."
+    print("Ren'Py requires at least python 2.6.")
     sys.exit(0)
 
 android = ("ANDROID_PRIVATE" in os.environ)
@@ -161,6 +167,7 @@ if android:
     __main__.path_to_saves = path_to_saves
     os.environ["RENPY_RENDERER"] = "gl"
 
+
 def main():
 
     renpy_base = path_to_renpy_base()
@@ -182,8 +189,8 @@ def main():
     try:
         import renpy.bootstrap
     except ImportError:
-        print >>sys.stderr, "Could not import renpy.bootstrap. Please ensure you decompressed Ren'Py"
-        print >>sys.stderr, "correctly, preserving the directory structure."
+        print("Could not import renpy.bootstrap. Please ensure you decompressed Ren'Py", file=sys.stderr)
+        print("correctly, preserving the directory structure.", file=sys.stderr)
         raise
 
     renpy.bootstrap.bootstrap(renpy_base)
diff --git a/renpy/__init__.py b/renpy/__init__.py
index d267928..ed60205 100644
--- a/renpy/__init__.py
+++ b/renpy/__init__.py
@@ -22,6 +22,7 @@
 # This file ensures that renpy packages will be imported in the right
 # order.
 
+from __future__ import print_function
 import sys
 import os
 import copy
@@ -40,11 +41,11 @@ except ImportError:
     vc_version = 0
 
 # The tuple giving the version number.
-version_tuple = (6, 99, 11, vc_version)
+version_tuple = (6, 99, 12, vc_version)
 
 # The name of this version.
 # version_name = "We came in peace..."
-version_name = "Who tells your story?"
+version_name = "We get the job done."
 
 # A string giving the version number only (7.0.1.123).
 version_only = ".".join(str(i) for i in version_tuple)
@@ -73,6 +74,7 @@ ios = False
 
 import platform
 
+
 def get_windows_version():
     """
     When called on windows, returns the windows version.
@@ -123,6 +125,9 @@ else:
 # A flag that's true if we're on a smartphone or tablet-like platform.
 mobile = android or ios
 
+# A flag that's set to true if the game directory is bundled inside a mac app.
+macapp = False
+
 
 ################################################################################
 # Backup Data for Reload
@@ -184,6 +189,7 @@ name_blacklist = {
     "renpy.display.screen.cprof",
     }
 
+
 class Backup():
     """
     This represents a backup of all of the fields in the python modules
@@ -262,8 +268,8 @@ class Backup():
             try:
                 cPickle.dumps(v, cPickle.HIGHEST_PROTOCOL)
             except:
-                print "Cannot pickle", name + "." + k, "=", repr(v)
-                print "Reduce Ex is:", repr(v.__reduce_ex__(cPickle.HIGHEST_PROTOCOL))
+                print("Cannot pickle", name + "." + k, "=", repr(v))
+                print("Reduce Ex is:", repr(v.__reduce_ex__(cPickle.HIGHEST_PROTOCOL)))
 
     def restore(self):
         """
@@ -280,7 +286,6 @@ class Backup():
             for name in set(modvars.keys()) - names:
                 del modvars[name]
 
-
         objects = cPickle.loads(self.objects_pickle)
 
         for k, v in self.variables.iteritems():
@@ -294,6 +299,7 @@ backup = None
 # Import
 ################################################################################
 
+
 def update_path(package):
     """
     Update the __path__ of package, to import binary modules from a libexec
@@ -311,16 +317,17 @@ def update_path(package):
     libexec = os.path.dirname(encodings.__path__[0])
     package.__path__.append(os.path.join(libexec, *name))
 
+
 def import_all():
 
     # Note: If we add a new update_path, we have to add an equivalent
     # hook in the renpython hooks dir.
 
-    import renpy # @UnresolvedImport
+    import renpy  # @UnresolvedImport
 
     update_path(renpy)
 
-    import renpy.arguments # @UnresolvedImport
+    import renpy.arguments  # @UnresolvedImport
 
     import renpy.log
 
@@ -352,7 +359,7 @@ def import_all():
     import renpy.script
     import renpy.statements
 
-    import renpy.styledata # @UnresolvedImport
+    import renpy.styledata  # @UnresolvedImport
     update_path(renpy.styledata)
 
     import renpy.style
@@ -362,12 +369,13 @@ def import_all():
 
     import renpy.substitutions
     import renpy.translation
+    import renpy.translation.scanstrings
     import renpy.translation.generation
     import renpy.translation.dialogue
     import renpy.translation.extract
     import renpy.translation.merge
 
-    import renpy.display # @UnresolvedImport @Reimport
+    import renpy.display  # @UnresolvedImport @Reimport
 
     update_path(renpy.display)
 
@@ -375,8 +383,8 @@ def import_all():
     import renpy.display.pgrender
     import renpy.display.scale
     import renpy.display.module
-    import renpy.display.render # Most display stuff depends on this. @UnresolvedImport
-    import renpy.display.core # object @UnresolvedImport
+    import renpy.display.render  # Most display stuff depends on this. @UnresolvedImport
+    import renpy.display.core  # object @UnresolvedImport
 
     import renpy.text
 
@@ -400,13 +408,13 @@ def import_all():
     import renpy.display.layout
     import renpy.display.viewport
     import renpy.display.transform
-    import renpy.display.motion # layout @UnresolvedImport
-    import renpy.display.behavior # layout @UnresolvedImport
-    import renpy.display.transition # core, layout @UnresolvedImport
-    import renpy.display.movetransition # core @UnresolvedImport
+    import renpy.display.motion  # layout @UnresolvedImport
+    import renpy.display.behavior  # layout @UnresolvedImport
+    import renpy.display.transition  # core, layout @UnresolvedImport
+    import renpy.display.movetransition  # core @UnresolvedImport
     import renpy.display.im
     import renpy.display.imagelike
-    import renpy.display.image # core, behavior, im, imagelike @UnresolvedImport
+    import renpy.display.image  # core, behavior, im, imagelike @UnresolvedImport
     import renpy.display.video
     import renpy.display.focus
     import renpy.display.anim
@@ -453,13 +461,13 @@ def import_all():
     import renpy.memory
 
     import renpy.exports
-    import renpy.character # depends on exports. @UnresolvedImport
+    import renpy.character  # depends on exports. @UnresolvedImport
 
     import renpy.add_from
     import renpy.dump
 
-    import renpy.config # depends on lots. @UnresolvedImport
-    import renpy.minstore # depends on lots. @UnresolvedImport
+    import renpy.config  # depends on lots. @UnresolvedImport
+    import renpy.minstore  # depends on lots. @UnresolvedImport
     import renpy.defaultstore  # depends on everything. @UnresolvedImport
 
     import renpy.test
@@ -472,7 +480,6 @@ def import_all():
 
     import renpy.main
 
-
     # Back up the Ren'Py modules.
 
     global backup
@@ -489,7 +496,7 @@ def post_import():
     of various modules.
     """
 
-    import renpy # @UnresolvedImport
+    import renpy  # @UnresolvedImport
 
     # Create the store.
     renpy.python.create_store("store")
@@ -528,7 +535,7 @@ def reload_all():
     sys.exc_clear()
 
     # Reset the styles.
-    renpy.style.reset() # @UndefinedVariable
+    renpy.style.reset()  # @UndefinedVariable
 
     # Shut down the cache thread.
     renpy.display.im.cache.quit()
@@ -619,8 +626,5 @@ def import_cython():
     import renpy.angle.gltexture
 
 
-
 if False:
     import renpy.defaultstore as store
-
-
diff --git a/renpy/add_from.py b/renpy/add_from.py
index 8f0ee11..f188ab3 100644
--- a/renpy/add_from.py
+++ b/renpy/add_from.py
@@ -27,6 +27,7 @@ import codecs
 # A map from filename to position, target label pairs.
 missing = collections.defaultdict(list)
 
+
 def report_missing(target, filename, position):
     """
     Reports that the call statement ending at `position` in `filename`
@@ -42,6 +43,7 @@ def report_missing(target, filename, position):
 # Labels that we've created while running add_from.
 new_labels = set()
 
+
 def generate_label(target):
     """
     Generate a reasonable and unique new label for a call to `target`.
@@ -103,6 +105,7 @@ def process_file(fn):
     os.rename(fn, fn + ".bak")
     os.rename(fn + ".new", fn)
 
+
 def add_from():
 
     renpy.arguments.takes_no_arguments("Adds from clauses to call statements that are missing them.")
@@ -114,4 +117,3 @@ def add_from():
     return False
 
 renpy.arguments.register_command("add_from", add_from)
-
diff --git a/renpy/angle/__init__.py b/renpy/angle/__init__.py
index 579eed2..528143e 100644
--- a/renpy/angle/__init__.py
+++ b/renpy/angle/__init__.py
@@ -1,3 +1,2 @@
 # This file was automatically generated from renpy/gl/__init__.py
 # Modifications will be automatically overwritten.
-
diff --git a/renpy/angle/gldraw.pyx b/renpy/angle/gldraw.pyx
index 47e343f..73addfd 100644
--- a/renpy/angle/gldraw.pyx
+++ b/renpy/angle/gldraw.pyx
@@ -982,7 +982,7 @@ cdef class GLDraw:
             # Non-aligned clipping uses RTT.
             if reverse.ydx != 0 or reverse.xdy != 0:
                 tex = what.render_to_texture(True)
-                self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+                self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
                 return 0
 
             minx, miny, maxx, maxy = clip
diff --git a/renpy/arguments.py b/renpy/arguments.py
index e6b8e63..397727d 100644
--- a/renpy/arguments.py
+++ b/renpy/arguments.py
@@ -31,7 +31,7 @@ import renpy
 
 try:
     import site
-    site._renpy_argv_emulation() # @UndefinedVariable
+    site._renpy_argv_emulation()  # @UndefinedVariable
 except:
     pass
 
@@ -43,6 +43,7 @@ commands = { }
 # Commands that force compile to be set.
 compile_commands = { "compile", "add_from", "merge_strings" }
 
+
 class ArgumentParser(argparse.ArgumentParser):
     """
     Creates an argument parser that is capable of parsing the standard Ren'Py
@@ -74,7 +75,6 @@ class ArgumentParser(argparse.ArgumentParser):
                 "basedir",
                 help="The base directory containing of the project to run. This defaults to the directory containing the Ren'Py executable.")
 
-
             self.add_argument(
                 "command",
                 help="The command to execute. Available commands are: " + command_names + ". Defaults to 'run'.")
@@ -87,7 +87,6 @@ class ArgumentParser(argparse.ArgumentParser):
                 nargs='?',
                 help="The base directory containing of the project to run. This defaults to the directory containing the Ren'Py executable.")
 
-
             self.add_argument(
                 "command",
                 help="The command to execute. Available commands are: " + command_names + ". Defaults to 'run'.",
@@ -126,7 +125,7 @@ class ArgumentParser(argparse.ArgumentParser):
         if second_pass:
             self.add_argument("-h", "--help", action="help", help="Displays this help message, then exits.")
 
-            command = renpy.game.args.command #@UndefinedVariable
+            command = renpy.game.args.command  # @UndefinedVariable
             self.group = self.add_argument_group("{0} command arguments".format(command), description)
 
     def add_argument(self, *args, **kwargs):
@@ -157,6 +156,7 @@ class ArgumentParser(argparse.ArgumentParser):
 
         return args, rest
 
+
 def run():
     """
     The default command, that (when called) leads to normal game startup.
@@ -181,7 +181,7 @@ def run():
     if args.warp:
         renpy.warp.warp_spec = args.warp
 
-    if args.profile_display: #@UndefinedVariable
+    if args.profile_display:  # @UndefinedVariable
         renpy.config.profile = True
 
     if args.debug_image_cache:
@@ -189,7 +189,8 @@ def run():
 
     return True
 
-def compile(): #@ReservedAssignment
+
+def compile():  # @ReservedAssignment
     """
     This command forces the game script to be recompiled.
     """
@@ -199,7 +200,7 @@ def compile(): #@ReservedAssignment
     return False
 
 
-def quit(): #@ReservedAssignment
+def quit():  # @ReservedAssignment
     """
     This command is used to quit without doing anything.
     """
@@ -208,6 +209,7 @@ def quit(): #@ReservedAssignment
 
     return False
 
+
 def rmpersistent():
     """
     This command is used to delete the persistent data.
@@ -236,6 +238,7 @@ def register_command(name, function):
 
     commands[name] = function
 
+
 def bootstrap():
     """
     Called during bootstrap to perform an initial parse of the arguments, ignoring
@@ -249,6 +252,7 @@ def bootstrap():
 
     return args
 
+
 def pre_init():
     """
     Called before init, to set up argument parsing.
@@ -270,9 +274,9 @@ def post_init():
     if execution should continue and False otherwise.
     """
 
-    command = renpy.game.args.command #@UndefinedVariable
+    command = renpy.game.args.command  # @UndefinedVariable
 
-    if command == "run" and renpy.game.args.lint: # @UndefinedVariable
+    if command == "run" and renpy.game.args.lint:  # @UndefinedVariable
         command = "lint"
 
     if command not in commands:
@@ -280,6 +284,7 @@ def post_init():
 
     return commands[command]()
 
+
 def takes_no_arguments(description=None):
     """
     Used to report that a command takes no arguments.
diff --git a/renpy/ast.py b/renpy/ast.py
index 0205d22..0f6b166 100644
--- a/renpy/ast.py
+++ b/renpy/ast.py
@@ -29,9 +29,10 @@
 import renpy.display
 import renpy.test
 
+import hashlib
 import re
 import time
-import md5
+
 
 def statement_name(name):
     """
@@ -41,6 +42,7 @@ def statement_name(name):
     for i in renpy.config.statement_callbacks:
         i(name)
 
+
 def next_node(n):
     """
     Indicates the next node that should be executed. When a statement
@@ -50,11 +52,13 @@ def next_node(n):
 
     renpy.game.context().next_node = n
 
+
 class ParameterInfo(object):
     """
     This class is used to store information about parameters to a
     label.
     """
+
     def __init__(self, parameters, positional, extrapos, extrakw):
 
         # A list of parameter name, default value pairs.
@@ -72,7 +76,6 @@ class ParameterInfo(object):
         # any. None if no such variable exists.
         self.extrakw = extrakw
 
-
     def apply(self, args, kwargs, ignore_errors=False):
         """
         Applies `args` and `kwargs` to these parameters. Returns
@@ -137,6 +140,7 @@ class ParameterInfo(object):
 
         return rv
 
+
 def apply_arguments(parameters, args, kwargs, ignore_errors=False):
 
     if parameters is None:
@@ -192,6 +196,8 @@ def __newobj__(cls, *args):
     return cls.__new__(cls, *args)
 
 # This represents a string containing python code.
+
+
 class PyExpr(unicode):
 
     __slots__ = [
@@ -207,7 +213,8 @@ class PyExpr(unicode):
         return self
 
     def __getnewargs__(self):
-        return (unicode(self), self.filename, self.linenumber) # E1101
+        return (unicode(self), self.filename, self.linenumber)  # E1101
+
 
 class PyCode(object):
 
@@ -258,14 +265,14 @@ class PyCode(object):
             pass
 
         code = self.source
-        if isinstance(code, renpy.python.ast.AST): #@UndefinedVariable
-            code = renpy.python.ast.dump(code) #@UndefinedVariable
+        if isinstance(code, renpy.python.ast.AST):  # @UndefinedVariable
+            code = renpy.python.ast.dump(code)  # @UndefinedVariable
 
-        self.hash = chr(renpy.bytecode_version) + md5.md5(repr(self.location) + code.encode("utf-8")).digest()
+        self.hash = chr(renpy.bytecode_version) + hashlib.md5(repr(self.location) + code.encode("utf-8")).digest()
         return self.hash
 
 
-def chain_block(block, next): #@ReservedAssignment
+def chain_block(block, next):  # @ReservedAssignment
     """
     This is called to chain together all of the nodes in a block. Node
     n is chained with node n+1, while the last node is chained with
@@ -291,7 +298,7 @@ class Scry(object):
     def __getattr__(self, name):
         return None
 
-    def next(self): #@ReservedAssignment
+    def next(self):  # @ReservedAssignment
         if self._next is None:
             return None
         else:
@@ -365,7 +372,7 @@ class Node(object):
     # get_init is only present on statements that define it.
     get_init = None
 
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         """
         This is called with the Node node that should be followed after
         executing this node, and all nodes that this node
@@ -421,7 +428,7 @@ class Node(object):
         """
 
         rv = Scry()
-        rv._next = self.next # W0201
+        rv._next = self.next  # W0201
         return rv
 
     def restructure(self, callback):
@@ -456,6 +463,7 @@ class Node(object):
         # Does nothing by default.
         return
 
+
 def say_menu_with(expression, callback):
     """
     This handles the with clause of a say or menu statement.
@@ -475,6 +483,7 @@ def say_menu_with(expression, callback):
         # renpy.game.interface.set_transition(what)
         callback(what)
 
+
 def eval_who(who, fast=None):
     """
     Evaluates the `who` parameter to a say statement.
@@ -503,6 +512,7 @@ def eval_who(who, fast=None):
 
     return renpy.python.py_eval(who)
 
+
 class Say(Node):
 
     __slots__ = [
@@ -583,15 +593,15 @@ class Say(Node):
             who = eval_who(self.who, self.who_fast)
 
             if not (
-                (who is None) or
-                callable(who) or
-                isinstance(who, basestring) ):
+                    (who is None) or
+                    callable(who) or
+                    isinstance(who, basestring) ):
 
                 raise Exception("Sayer %s is not a function or string." % self.who.encode("utf-8"))
 
             what = self.what
             if renpy.config.say_menu_text_filter:
-                what = renpy.config.say_menu_text_filter(what) # E1102
+                what = renpy.config.say_menu_text_filter(what)  # E1102
 
             renpy.store._last_raw_what = what
 
@@ -605,7 +615,6 @@ class Say(Node):
         finally:
             renpy.game.context().say_attributes = None
 
-
     def predict(self):
 
         old_attributes = renpy.game.context().say_attributes
@@ -651,7 +660,8 @@ class Say(Node):
         return rv
 
 # Copy the descriptor.
-setattr(Say, "with", Say.with_) # E1101
+setattr(Say, "with", Say.with_)  # E1101
+
 
 class Init(Node):
 
@@ -666,7 +676,6 @@ class Init(Node):
         self.block = block
         self.priority = priority
 
-
     def get_children(self, f):
         f(self)
 
@@ -679,7 +688,7 @@ class Init(Node):
     # We handle chaining specially. We want to chain together the nodes in
     # the block, but we want that chain to end in None, and we also want
     # this node to just continue on to the next node in normal execution.
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = next
 
         chain_block(self.block, None)
@@ -734,7 +743,7 @@ class Label(Node):
         for i in self.block:
             i.get_children(f)
 
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
 
         if self.block:
             self.next = self.block[0]
@@ -814,6 +823,7 @@ class Python(Node):
         rv.interacts = True
         return rv
 
+
 class EarlyPython(Node):
 
     __slots__ = [
@@ -854,6 +864,7 @@ class EarlyPython(Node):
         if self.code.bytecode:
             renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
 
+
 class Image(Node):
 
     __slots__ = [
@@ -1196,7 +1207,6 @@ class Hide(Node):
         elif len(self.imspec) == 7:
             name, _expression, tag, _at_list, layer, _zorder, _behind = self.imspec
 
-
         if tag is None:
             tag = name[0]
 
@@ -1275,7 +1285,6 @@ class With(Node):
         except:
             pass
 
-
         return [ self.next ]
 
 
@@ -1351,7 +1360,7 @@ class Return(Node):
         return (Return, )
 
     # We don't care what the next node is.
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = None
         return
 
@@ -1387,7 +1396,7 @@ class Menu(Node):
         'with_',
         ]
 
-    def __init__(self, loc, items, set, with_): #@ReservedAssignment
+    def __init__(self, loc, items, set, with_):  # @ReservedAssignment
         super(Menu, self).__init__(loc)
 
         self.items = items
@@ -1406,7 +1415,7 @@ class Menu(Node):
                     i.get_children(f)
 
     # Blocks of statements in a choice continue after the menu.
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
 
         self.next = next
 
@@ -1454,7 +1463,6 @@ class Menu(Node):
         else:
             next_node(self.next)
 
-
     def predict(self):
         rv = [ ]
 
@@ -1482,7 +1490,7 @@ class Menu(Node):
             if block is not None:
                 callback(block)
 
-setattr(Menu, "with", Menu.with_) # E1101
+setattr(Menu, "with", Menu.with_)  # E1101
 
 
 # Goto is considered harmful. So we decided to name it "jump"
@@ -1494,7 +1502,7 @@ class Jump(Node):
         'expression',
         ]
 
-    def  __init__(self, loc, target, expression):
+    def __init__(self, loc, target, expression):
         super(Jump, self).__init__(loc)
 
         self.target = target
@@ -1504,7 +1512,7 @@ class Jump(Node):
         return (Jump, self.target, self.expression)
 
     # We don't care what our next node is.
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = None
         return
 
@@ -1573,7 +1581,7 @@ class While(Node):
         for i in self.block:
             i.get_children(f)
 
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = next
         chain_block(self.block, self)
 
@@ -1602,6 +1610,7 @@ class While(Node):
     def restructure(self, callback):
         callback(self.block)
 
+
 class If(Node):
 
     __slots__ = [ 'entries' ]
@@ -1625,7 +1634,7 @@ class If(Node):
             for i in block:
                 i.get_children(f)
 
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = next
 
         for _condition, block in self.entries:
@@ -1662,6 +1671,7 @@ class If(Node):
         for _condition, block in self.entries:
             callback(block)
 
+
 class UserStatement(Node):
 
     __slots__ = [
@@ -1737,17 +1747,21 @@ class UserStatement(Node):
     def get_code(self, dialogue_filter=None):
         return self.line
 
+
 def create_store(name):
     if name not in renpy.config.special_namespaces:
         renpy.python.create_store(name)
 
+
 class StoreNamespace(object):
+
     def __init__(self, store):
         self.store = store
 
     def set(self, name, value):
         renpy.python.store_dicts[self.store][name] = value
 
+
 def get_namespace(store):
     """
     Returns the namespace object for `store`, and a flag that is true if the
@@ -1763,6 +1777,7 @@ def get_namespace(store):
 # and then again at init time.
 EARLY_CONFIG = { "save_directory" }
 
+
 class Define(Node):
 
     __slots__ = [
@@ -1813,6 +1828,7 @@ class Define(Node):
 # All the default statements, in the order they were registered.
 default_statements = [ ]
 
+
 class Default(Node):
 
     __slots__ = [
@@ -1944,7 +1960,7 @@ class Translate(Node):
     def diff_info(self):
         return (Translate, self.identifier, self.language)
 
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         if self.block:
             self.next = self.block[0]
             chain_block(self.block, next)
@@ -1970,8 +1986,8 @@ class Translate(Node):
             next_node(self.next)
             raise Exception("Translation nodes cannot be run directly.")
 
-        if self.identifier not in renpy.game.persistent._seen_translates: # @UndefinedVariable
-            renpy.game.persistent._seen_translates.add(self.identifier) # @UndefinedVariable
+        if self.identifier not in renpy.game.persistent._seen_translates:  # @UndefinedVariable
+            renpy.game.persistent._seen_translates.add(self.identifier)  # @UndefinedVariable
             renpy.game.seen_translates_count += 1
             renpy.game.new_translates_count += 1
 
@@ -2051,6 +2067,7 @@ class TranslateString(Node):
         newloc = getattr(self, "newloc", (self.filename, self.linenumber + 1))
         renpy.translation.add_string_translation(self.language, self.old, self.new, newloc)
 
+
 class TranslatePython(Node):
     """
     Runs python code when changing the language.
@@ -2117,7 +2134,7 @@ class TranslateBlock(Node):
     # We handle chaining specially. We want to chain together the nodes in
     # the block, but we want that chain to end in None, and we also want
     # this node to just continue on to the next node in normal execution.
-    def chain(self, next): #@ReservedAssignment
+    def chain(self, next):  # @ReservedAssignment
         self.next = next
         chain_block(self.block, None)
 
@@ -2128,6 +2145,14 @@ class TranslateBlock(Node):
     def restructure(self, callback):
         callback(self.block)
 
+
+class TranslateEarlyBlock(TranslateBlock):
+    """
+    This is similar to the TranslateBlock, except it runs before deferred
+    styles do.
+    """
+
+
 class Style(Node):
 
     __slots__ = [
@@ -2177,7 +2202,7 @@ class Style(Node):
             if not renpy.exports.variant(variant):
                 return
 
-        s = renpy.style.get_or_create_style(self.style_name) # @UndefinedVariable
+        s = renpy.style.get_or_create_style(self.style_name)  # @UndefinedVariable
 
         if self.clear:
             s.clear()
diff --git a/renpy/atl.py b/renpy/atl.py
index 914d8d1..660cca3 100644
--- a/renpy/atl.py
+++ b/renpy/atl.py
@@ -24,13 +24,15 @@ import renpy.pyanalysis
 
 import random
 
+
 def compiling(loc):
-    file, number = loc #@ReservedAssignment
+    file, number = loc  # @ReservedAssignment
 
     renpy.game.exception_info = "Compiling ATL code at %s:%d" % (file, number)
 
+
 def executing(loc):
-    file, number = loc #@ReservedAssignment
+    file, number = loc  # @ReservedAssignment
 
     renpy.game.exception_info = "Executing ATL code at %s:%d" % (file, number)
 
@@ -38,6 +40,7 @@ def executing(loc):
 # A map from the name of a time warp function to the function itself.
 warpers = { }
 
+
 def atl_warper(f):
     name = f.func_name
     warpers[name] = f
@@ -45,6 +48,8 @@ def atl_warper(f):
 
 # The pause warper is used internally when no other warper is
 # specified.
+
+
 @atl_warper
 def pause(t):
     if t < 1.0:
@@ -54,14 +59,17 @@ def pause(t):
 
 position = renpy.object.Sentinel("position")
 
+
 def any_object(x):
     return x
 
+
 def bool_or_none(x):
     if x is None:
         return x
     return bool(x)
 
+
 def float_or_none(x):
     if x is None:
         return x
@@ -70,51 +78,51 @@ def float_or_none(x):
 # A dictionary giving property names and the corresponding default
 # values.
 PROPERTIES = {
-        "pos" : (position, position),
-        "xpos" : position,
-        "ypos" : position,
-        "anchor" : (position, position),
-        "xanchor" : position,
-        "yanchor" : position,
-        "xaround" : position,
-        "yaround" : position,
-        "xanchoraround" : float,
-        "yanchoraround" : float,
-        "align" : (float, float),
-        "xalign" : float,
-        "yalign" : float,
-        "rotate" : float,
-        "rotate_pad" : bool,
-        "transform_anchor" : bool,
-        "xzoom" : float,
-        "yzoom" : float,
-        "zoom" : float,
-        "nearest" : bool_or_none,
-        "alpha" : float,
-        "additive" : float,
-        "around" : (position, position),
-        "alignaround" : (float, float),
-        "angle" : float,
-        "radius" : float,
-        "crop" : (float, float, float, float),
-        "crop_relative" : bool,
-        "size" : (int, int),
-        "corner1" : (float, float),
-        "corner2" : (float, float),
-        "subpixel" : bool,
-        "delay" : float,
-        "xoffset" : float,
-        "yoffset" : float,
-        "offset" : (int, int),
-        "xcenter" : position,
-        "ycenter" : position,
-        "debug" : any_object,
-        "events" : bool,
-        "xpan" : float_or_none,
-        "ypan" : float_or_none,
-        "xtile" : int,
-        "ytile" : int,
-        }
+    "pos" : (position, position),
+    "xpos" : position,
+    "ypos" : position,
+    "anchor" : (position, position),
+    "xanchor" : position,
+    "yanchor" : position,
+    "xaround" : position,
+    "yaround" : position,
+    "xanchoraround" : float,
+    "yanchoraround" : float,
+    "align" : (float, float),
+    "xalign" : float,
+    "yalign" : float,
+    "rotate" : float,
+    "rotate_pad" : bool,
+    "transform_anchor" : bool,
+    "xzoom" : float,
+    "yzoom" : float,
+    "zoom" : float,
+    "nearest" : bool_or_none,
+    "alpha" : float,
+    "additive" : float,
+    "around" : (position, position),
+    "alignaround" : (float, float),
+    "angle" : float,
+    "radius" : float,
+    "crop" : (float, float, float, float),
+    "crop_relative" : bool,
+    "size" : (int, int),
+    "corner1" : (float, float),
+    "corner2" : (float, float),
+    "subpixel" : bool,
+    "delay" : float,
+    "xoffset" : float,
+    "yoffset" : float,
+    "offset" : (int, int),
+    "xcenter" : position,
+    "ycenter" : position,
+    "debug" : any_object,
+    "events" : bool,
+    "xpan" : float_or_none,
+    "ypan" : float_or_none,
+    "xtile" : int,
+    "ytile" : int,
+    }
 
 
 def correct_type(v, b, ty):
@@ -131,7 +139,7 @@ def correct_type(v, b, ty):
         return ty(v)
 
 
-def interpolate(t, a, b, type): #@ReservedAssignment
+def interpolate(t, a, b, type):  # @ReservedAssignment
     """
     Linearly interpolate the arguments.
     """
@@ -159,6 +167,8 @@ def interpolate(t, a, b, type): #@ReservedAssignment
 
 # Interpolate the value of a spline. This code is based on Aenakume's code,
 # from 00splines.rpy.
+
+
 def interpolate_spline(t, spline):
 
     if isinstance(spline[-1], tuple):
@@ -196,6 +206,7 @@ def interpolate_spline(t, spline):
 # A list of atl transforms that may need to be compile.
 compile_queue = [ ]
 
+
 def compile_all():
     """
     Called after the init phase is finished and transforms are compiled,
@@ -215,12 +226,13 @@ def compile_all():
 # scopes that are used to evaluate the various expressions in the statement,
 # and has a method to do the evaluation and return a result.
 class Context(object):
+
     def __init__(self, context):
         self.context = context
 
-    def eval(self, expr): #@ReservedAssignment
+    def eval(self, expr):  # @ReservedAssignment
         expr = renpy.python.escape_unicode(expr)
-        return eval(expr, renpy.store.__dict__, self.context) #@UndefinedVariable
+        return eval(expr, renpy.store.__dict__, self.context)  # @UndefinedVariable
 
     def __eq__(self, other):
         if not isinstance(other, Context):
@@ -231,6 +243,8 @@ class Context(object):
 # This is intended to be subclassed by ATLTransform. It takes care of
 # managing ATL execution, which allows ATLTransform itself to not care
 # much about the contents of this file.
+
+
 class ATLTransformBase(renpy.object.Object):
 
     # Compatibility with older saves.
@@ -421,8 +435,7 @@ class ATLTransformBase(renpy.object.Object):
 
         return rv
 
-
-    def compile(self): #@ReservedAssignment
+    def compile(self):  # @ReservedAssignment
         """
         Compiles the ATL code into a block. As necessary, updates the
         properties.
@@ -472,7 +485,6 @@ class ATLTransformBase(renpy.object.Object):
 
         return block
 
-
     def execute(self, trans, st, at):
 
         if self.done:
@@ -539,6 +551,8 @@ is_constant_expr = renpy.pyanalysis.Analysis().is_constant_expr
 GLOBAL_CONST = renpy.pyanalysis.GLOBAL_CONST
 
 # The base class for raw ATL statements.
+
+
 class RawStatement(object):
 
     constant = None
@@ -549,7 +563,7 @@ class RawStatement(object):
 
     # Compiles this RawStatement into a Statement, by using ctx to
     # evaluate expressions as necessary.
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         raise Exception("Compile not implemented.")
 
     # Predicts the images used by this statement.
@@ -565,6 +579,8 @@ class RawStatement(object):
         self.constant = 0
 
 # The base class for compiled ATL Statements.
+
+
 class Statement(renpy.object.Object):
 
     def __init__(self, loc):
@@ -604,6 +620,8 @@ class Statement(renpy.object.Object):
         return [ ]
 
 # This represents a Raw ATL block.
+
+
 class RawBlock(RawStatement):
 
     # Should we use the animation timebase or the showing timebase?
@@ -618,7 +636,7 @@ class RawBlock(RawStatement):
 
         self.animation = animation
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         compiling(self.loc)
 
         statements = [ i.compile(ctx) for i in self.statements ]
@@ -642,6 +660,7 @@ class RawBlock(RawStatement):
 
 # A compiled ATL block.
 class Block(Statement):
+
     def __init__(self, loc, statements):
 
         super(Block, self).__init__(loc)
@@ -697,7 +716,6 @@ class Block(Statement):
                 if index >= len(self.statements):
                     return "next", target - start, None
 
-
                 # Find the statement and try to run it.
                 stmt = self.statements[index]
                 action, arg, pause = stmt.execute(trans, target - start, child_state, event)
@@ -773,6 +791,8 @@ class Block(Statement):
 #
 # We won't decide which it is until runtime, as we need the
 # values of the variables here.
+
+
 class RawMultipurpose(RawStatement):
 
     warp_function = None
@@ -809,7 +829,7 @@ class RawMultipurpose(RawStatement):
     def add_spline(self, name, exprs):
         self.splines.append((name, exprs))
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
 
         compiling(self.loc)
 
@@ -820,7 +840,7 @@ class RawMultipurpose(RawStatement):
             self.warp_function is None and
             not self.properties and
             not self.splines and
-            len(self.expressions) == 1):
+                len(self.expressions) == 1):
 
             expr, withexpr = self.expressions[0]
 
@@ -886,7 +906,6 @@ class RawMultipurpose(RawStatement):
             if value.properties is None:
                 raise Exception("ATL transform %r is too complicated to be included in interpolation." % expr)
 
-
             properties.extend(value.properties)
 
         duration = ctx.eval(self.duration)
@@ -914,7 +933,6 @@ class RawMultipurpose(RawStatement):
 
         self.constant = constant
 
-
     def predict(self, ctx):
 
         for i, _j in self.expressions:
@@ -934,6 +952,8 @@ class RawMultipurpose(RawStatement):
                 continue
 
 # This lets us have an ATL transform as our child.
+
+
 class RawContainsExpr(RawStatement):
 
     def __init__(self, loc, expr):
@@ -942,7 +962,7 @@ class RawContainsExpr(RawStatement):
 
         self.expression = expr
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         compiling(self.loc)
         child = ctx.eval(self.expression)
         return Child(self.loc, child, None)
@@ -960,7 +980,7 @@ class RawChild(RawStatement):
 
         self.children = [ child ]
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
 
         children = [ ]
 
@@ -974,7 +994,6 @@ class RawChild(RawStatement):
 
         return Child(self.loc, box, None)
 
-
     def mark_constant(self):
 
         constant = GLOBAL_CONST
@@ -1141,7 +1160,6 @@ class Interpolation(Statement):
             trans.state.angle = interpolate(complete, startangle, endangle, float)
             trans.state.radius = interpolate(complete, startradius, endradius, float)
 
-
         # Handle any splines we might have.
         for name, values in splines:
             value = interpolate_spline(complete, values)
@@ -1165,7 +1183,7 @@ class RawRepeat(RawStatement):
 
         self.repeats = repeats
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
 
         compiling(self.loc)
 
@@ -1179,6 +1197,7 @@ class RawRepeat(RawStatement):
     def mark_constant(self):
         self.constant = is_constant_expr(self.repeats)
 
+
 class Repeat(Statement):
 
     def __init__(self, loc, repeats):
@@ -1200,7 +1219,7 @@ class RawParallel(RawStatement):
         super(RawParallel, self).__init__(loc)
         self.blocks = [ block ]
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         return Parallel(self.loc, [i.compile(ctx) for i in self.blocks])
 
     def predict(self, ctx):
@@ -1216,6 +1235,7 @@ class RawParallel(RawStatement):
 
         self.constant = constant
 
+
 class Parallel(Statement):
 
     def __init__(self, loc, blocks):
@@ -1270,7 +1290,7 @@ class RawChoice(RawStatement):
 
         self.choices = [ (chance, block) ]
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         compiling(self.loc)
         return Choice(self.loc, [ (ctx.eval(chance), block.compile(ctx)) for chance, block in self.choices])
 
@@ -1287,6 +1307,7 @@ class RawChoice(RawStatement):
 
         self.constant = constant
 
+
 class Choice(Statement):
 
     def __init__(self, loc, choices):
@@ -1337,13 +1358,14 @@ class RawTime(RawStatement):
         super(RawTime, self).__init__(loc)
         self.time = time
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         compiling(self.loc)
         return Time(self.loc, ctx.eval(self.time))
 
     def mark_constant(self):
         self.constant = is_constant_expr(self.time)
 
+
 class Time(Statement):
 
     def __init__(self, loc, time):
@@ -1367,7 +1389,7 @@ class RawOn(RawStatement):
         for i in names:
             self.handlers[i] = block
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
 
         compiling(self.loc)
 
@@ -1479,12 +1501,13 @@ class RawEvent(RawStatement):
 
         self.name = name
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         return Event(self.loc, self.name)
 
     def mark_constant(self):
         self.constant = GLOBAL_CONST
 
+
 class Event(Statement):
 
     def __init__(self, loc, name):
@@ -1503,13 +1526,14 @@ class RawFunction(RawStatement):
 
         self.expr = expr
 
-    def compile(self, ctx): #@ReservedAssignment
+    def compile(self, ctx):  # @ReservedAssignment
         compiling(self.loc)
         return Function(self.loc, ctx.eval(self.expr))
 
     def mark_constant(self):
         self.constant = is_constant_expr(self.expr)
 
+
 class Function(Statement):
 
     def __init__(self, loc, function):
@@ -1656,7 +1680,6 @@ def parse_atl(l):
             cp = l.checkpoint()
             warper = l.name()
 
-
             if warper in warpers:
                 duration = l.require(l.simple_expression)
                 warp_function = None
@@ -1750,14 +1773,12 @@ def parse_atl(l):
 
             statements.append(rm)
 
-
         if l.eol():
             l.advance()
             continue
 
         l.require(",", "comma or end of line")
 
-
     # Merge together statements that need to be merged together.
 
     merged = [ ]
diff --git a/renpy/audio/__init__.py b/renpy/audio/__init__.py
index d7fbe15..2c0b224 100644
--- a/renpy/audio/__init__.py
+++ b/renpy/audio/__init__.py
@@ -20,4 +20,3 @@
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 # This file intentionally left blank.
-
diff --git a/renpy/audio/androidhw.py b/renpy/audio/androidhw.py
index 1c3b6ed..85eb670 100644
--- a/renpy/audio/androidhw.py
+++ b/renpy/audio/androidhw.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import renpy
 import jnius  # @UnresolvedImport
 
@@ -5,6 +6,7 @@ from renpy.audio.audio import MusicContext
 
 VideoPlayer = jnius.autoclass("org.renpy.android.VideoPlayer")
 
+
 class AndroidVideoChannel(object):
 
     def __init__(self, name, file_prefix="", file_suffix="", default_loop=None):
@@ -51,7 +53,6 @@ class AndroidVideoChannel(object):
             self.default_loop = default_loop
             self.default_loop_set = True
 
-
     def get_context(self):
         """
         Returns the MusicContext corresponding to this channel, taken from
@@ -68,7 +69,6 @@ class AndroidVideoChannel(object):
 
     context = property(get_context)
 
-
     def start(self):
         """
         Starts playing the first video in the queue.
@@ -79,7 +79,7 @@ class AndroidVideoChannel(object):
 
         filename = self.queue.pop(0)
 
-        print "Playing", filename
+        print("Playing", filename)
 
         f = renpy.loader.load(filename)
 
@@ -123,7 +123,6 @@ class AndroidVideoChannel(object):
         if self.queue:
             self.start()
 
-
     def dequeue(self, even_tight=False):
         """
         Clears the queued music, except for a first item that has
@@ -135,7 +134,6 @@ class AndroidVideoChannel(object):
         else:
             self.queue = self.queue[:1]
 
-
     def interact(self):
         """
         Called (mostly) once per interaction.
@@ -143,7 +141,6 @@ class AndroidVideoChannel(object):
 
         self.periodic()
 
-
     def fadeout(self, secs):
         """
         Causes the playing music to be faded out for the given number
diff --git a/renpy/audio/audio.py b/renpy/audio/audio.py
index 9267c62..58da592 100644
--- a/renpy/audio/audio.py
+++ b/renpy/audio/audio.py
@@ -48,6 +48,7 @@ pcm_ok = None
 unique = time.time()
 serial = 0
 
+
 def get_serial():
     """
     Gets a globally unique serial number for each music change.
@@ -134,6 +135,7 @@ class MusicContext(renpy.python.RevertableObject):
 # The next channel number to be assigned.
 next_channel_number = 0
 
+
 class Channel(object):
     """
     This stores information about the currently-playing music.
@@ -324,7 +326,6 @@ class Channel(object):
             renpysound.set_volume(self.number, vol)
             self.actual_volume = vol
 
-
         # This should be set from something that checks to see if our
         # mixer is muted.
         force_stop = self.context.force_stop or (renpy.game.preferences.mute[self.mixer] and self.stop_on_mute)
@@ -344,6 +345,8 @@ class Channel(object):
         # Should we do the callback?
         do_callback = False
 
+        topq = None
+
         # This has been modified so we only queue a single sound file
         # per call, to prevent memory leaks with really short sound
         # files. So this loop will only execute once, in practice.
@@ -424,14 +427,18 @@ class Channel(object):
 
         if self.loop and not self.queue:
             for i in self.loop:
-                newq = QueueEntry(i, 0, topq.tight, True)
+                if topq is not None:
+                    newq = QueueEntry(i, 0, topq.tight, True)
+                else:
+                    newq = QueueEntry(i, 0, False, True)
+
                 self.queue.append(newq)
         else:
             do_callback = True
 
         # Queue empty callback.
         if do_callback and self.callback:
-            self.callback() # E1102
+            self.callback()  # E1102
 
         want_pause = self.context.pause or global_pause
 
@@ -444,7 +451,6 @@ class Channel(object):
 
             self.paused = want_pause
 
-
     def dequeue(self, even_tight=False):
         """
         Clears the queued music.
@@ -474,19 +480,17 @@ class Channel(object):
             if self.pan_time != self.context.pan_time:
                 self.pan_time = self.context.pan_time
                 renpysound.set_pan(self.number,
-                            self.context.pan,
-                            0)
-
+                                   self.context.pan,
+                                   0)
 
             if self.secondary_volume_time != self.context.secondary_volume_time:
                 self.secondary_volume_time = self.context.secondary_volume_time
                 renpysound.set_secondary_volume(self.number,
-                                         self.context.secondary_volume,
-                                         0)
+                                                self.context.secondary_volume,
+                                                0)
 
         if not self.queue and self.callback:
-            self.callback() # E1102
-
+            self.callback()  # E1102
 
     def fadeout(self, secs):
         """
@@ -505,7 +509,7 @@ class Channel(object):
         else:
             renpysound.fadeout(self.number, int(secs * 1000))
 
-    def enqueue(self, filenames, loop=True, synchro_start=False, fadein=0, tight=None):
+    def enqueue(self, filenames, loop=True, synchro_start=False, fadein=0, tight=None, loop_only=False):
 
         for filename in filenames:
             filename, _, _ = self.split_filename(filename, False)
@@ -514,26 +518,28 @@ class Channel(object):
         if not pcm_ok:
             return
 
-        if tight is None:
-            tight = self.tight
+        if not loop_only:
 
-        self.keep_queue += 1
+            if tight is None:
+                tight = self.tight
 
-        for filename in filenames:
-            qe = QueueEntry(filename, int(fadein * 1000), tight, False)
-            self.queue.append(qe)
+            self.keep_queue += 1
+
+            for filename in filenames:
+                qe = QueueEntry(filename, int(fadein * 1000), tight, False)
+                self.queue.append(qe)
+
+                # Only fade the first thing in.
+                fadein = 0
 
-            # Only fade the first thing in.
-            fadein = 0
+            self.wait_stop = synchro_start
+            self.synchro_start = synchro_start
 
         if loop:
             self.loop = list(filenames)
         else:
             self.loop = [ ]
 
-        self.wait_stop = synchro_start
-        self.synchro_start = synchro_start
-
     def get_playing(self):
 
         if not pcm_ok:
@@ -735,9 +741,11 @@ def get_channel(name):
 
     return rv
 
+
 def set_force_stop(name, value):
     get_channel(name).context.force_stop = value
 
+
 def init():
 
     global pcm_ok
@@ -776,7 +784,7 @@ def init():
         renpy.game.preferences.mute.setdefault(m, False)
 
 
-def quit(): #@ReservedAssignment
+def quit():  # @ReservedAssignment
 
     global pcm_ok
     global mix_ok
@@ -805,6 +813,7 @@ pcm_volume = None
 
 old_emphasized = False
 
+
 def periodic():
     """
     The periodic sound callback. This is called at around 20hz, and is
@@ -819,7 +828,6 @@ def periodic():
     if not pcm_ok:
         return False
 
-
     try:
 
         # A list of emphasized channels.
@@ -921,6 +929,7 @@ def interact():
 
     periodic()
 
+
 def rollback():
     """
     On rollback, we want to stop all the channels with non-empty sounds.
@@ -932,6 +941,7 @@ def rollback():
 
 global_pause = False
 
+
 def pause_all():
     """
     Pause all playback channels.
@@ -942,6 +952,7 @@ def pause_all():
 
     periodic()
 
+
 def unpause_all():
     """
     Unpause all playback channels.
@@ -952,15 +963,16 @@ def unpause_all():
 
     periodic()
 
+
 def sample_surfaces(rgb, rgba):
     if not renpysound:
         return
 
     renpysound.sample_surfaces(rgb, rgba)
 
+
 def advance_time():
     if not renpysound:
         return
 
     renpysound.advance_time()
-
diff --git a/renpy/audio/ioshw.py b/renpy/audio/ioshw.py
index 905b585..91b1b18 100644
--- a/renpy/audio/ioshw.py
+++ b/renpy/audio/ioshw.py
@@ -1,10 +1,11 @@
 import renpy
-import pyobjus # @UnresolvedImport
+import pyobjus  # @UnresolvedImport
 
 from renpy.audio.audio import MusicContext
 
 VideoPlayer = pyobjus.autoclass("VideoPlayer")
 
+
 class IOSVideoChannel(object):
 
     def __init__(self, name, file_prefix="", file_suffix="", default_loop=None):
@@ -51,7 +52,6 @@ class IOSVideoChannel(object):
             self.default_loop = default_loop
             self.default_loop_set = True
 
-
     def get_context(self):
         """
         Returns the MusicContext corresponding to this channel, taken from
@@ -68,7 +68,6 @@ class IOSVideoChannel(object):
 
     context = property(get_context)
 
-
     def start(self):
         """
         Starts playing the first video in the queue.
@@ -118,7 +117,6 @@ class IOSVideoChannel(object):
         if self.queue:
             self.start()
 
-
     def dequeue(self, even_tight=False):
         """
         Clears the queued music, except for a first item that has
@@ -130,7 +128,6 @@ class IOSVideoChannel(object):
         else:
             self.queue = self.queue[:1]
 
-
     def interact(self):
         """
         Called (mostly) once per interaction.
@@ -138,7 +135,6 @@ class IOSVideoChannel(object):
 
         self.periodic()
 
-
     def fadeout(self, secs):
         """
         Causes the playing music to be faded out for the given number
@@ -172,4 +168,3 @@ class IOSVideoChannel(object):
 
     def set_secondary_volume(self, volume, delay):
         pass
-
diff --git a/renpy/audio/music.py b/renpy/audio/music.py
index 9d0ac3a..5c14a91 100644
--- a/renpy/audio/music.py
+++ b/renpy/audio/music.py
@@ -29,6 +29,7 @@ from renpy.audio.audio import get_channel, get_serial
 from renpy.audio.audio import register_channel, alias_channel
 register_channel; alias_channel
 
+
 def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=False, fadein=0, tight=None, if_changed=False):
     """
     :doc: audio
@@ -88,6 +89,8 @@ def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=Fals
         if loop is None:
             loop = c.default_loop
 
+        loop_is_filenames = (c.loop == filenames)
+
         c.dequeue()
 
         if fadeout is None:
@@ -95,10 +98,12 @@ def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=Fals
 
         if if_changed and c.get_playing() in filenames:
             fadein = 0
+            loop_only = loop_is_filenames
         else:
             c.fadeout(fadeout)
+            loop_only = False
 
-        c.enqueue(filenames, loop=loop, synchro_start=synchro_start, fadein=fadein, tight=tight)
+        c.enqueue(filenames, loop=loop, synchro_start=synchro_start, fadein=fadein, tight=tight, loop_only=loop_only)
 
         t = get_serial()
         ctx.last_changed = t
@@ -190,6 +195,7 @@ def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tig
         if renpy.config.debug_sound:
             raise
 
+
 def playable(filename, channel="music"):
     """
     Return true if the given filename is playable on the channel. This
@@ -323,6 +329,7 @@ def get_pos(channel="music"):
 
         return None
 
+
 def get_duration(channel="music"):
     """
     :doc: audio
@@ -359,6 +366,7 @@ def get_playing(channel="music"):
 
         return None
 
+
 def is_playing(channel="music"):
     """
     :doc: audio
@@ -369,6 +377,7 @@ def is_playing(channel="music"):
 
     return (get_playing(channel=channel) is not None)
 
+
 def set_volume(volume, delay=0, channel="music"):
     """
     :doc: audio
@@ -396,6 +405,7 @@ def set_volume(volume, delay=0, channel="music"):
         if renpy.config.debug_sound:
             raise
 
+
 def set_pan(pan, delay, channel="music"):
     """
     :doc: audio
@@ -423,6 +433,7 @@ def set_pan(pan, delay, channel="music"):
         if renpy.config.debug_sound:
             raise
 
+
 def set_queue_empty_callback(callback, channel="music"):
     """
     :doc: audio
@@ -443,6 +454,7 @@ def set_queue_empty_callback(callback, channel="music"):
         if renpy.config.debug_sound:
             raise
 
+
 def set_pause(value, channel="music"):
     """
     :doc: audio
@@ -457,6 +469,7 @@ def set_pause(value, channel="music"):
         if renpy.config.debug_sound:
             raise
 
+
 def get_pause(channel="music"):
     """
     :doc: audio
@@ -493,6 +506,7 @@ def set_mixer(channel, mixer, default=False):
         if renpy.config.debug_sound:
             raise
 
+
 def get_all_mixers():
     """
     This gets all mixers in use.
@@ -505,6 +519,7 @@ def get_all_mixers():
 
     return list(rv)
 
+
 def channel_defined(channel):
     """
     Returns True if the channel exists, or False otherwise.
@@ -538,4 +553,3 @@ def channel_defined(channel):
 
 # if m_loop:
 #     queue m_filenames looping
-
diff --git a/renpy/audio/sound.py b/renpy/audio/sound.py
index d94d76f..6fed2db 100644
--- a/renpy/audio/sound.py
+++ b/renpy/audio/sound.py
@@ -32,35 +32,41 @@ import renpy.audio
 
 def play(filename, channel="sound", fadeout=0, fadein=0, tight=False, loop=False):
     renpy.audio.music.play(filename,
-                     channel=channel,
-                     fadeout=fadeout,
-                     fadein=fadein,
-                     tight=tight,
-                     loop=loop)
+                           channel=channel,
+                           fadeout=fadeout,
+                           fadein=fadein,
+                           tight=tight,
+                           loop=loop)
+
 
 def queue(filename, channel="sound", clear_queue=True, fadein=0, tight=False, loop=False):
     renpy.audio.music.queue(filename,
-                      channel=channel,
-                      clear_queue=clear_queue,
-                      fadein=fadein,
-                      tight=tight,
-                      loop=loop)
+                            channel=channel,
+                            clear_queue=clear_queue,
+                            fadein=fadein,
+                            tight=tight,
+                            loop=loop)
+
 
 def stop(channel="sound", fadeout=0):
     renpy.audio.music.stop(channel=channel,
-                     fadeout=fadeout)
+                           fadeout=fadeout)
 
 set_mixer = renpy.audio.music.set_mixer
 set_queue_empty_callback = renpy.audio.music.set_queue_empty_callback
 
+
 def set_volume(volume, channel="sound"):
     renpy.audio.music.set_volume(volume, 0, channel=channel)
 
+
 def set_pan(pan, delay, channel="sound"):
     renpy.audio.music.set_pan(pan, delay, channel=channel)
 
+
 def is_playing(channel="sound"):
     return renpy.audio.music.is_playing(channel=channel)
 
+
 def get_playing(channel="sound"):
     return renpy.audio.music.get_playing(channel=channel)
diff --git a/renpy/bootstrap.py b/renpy/bootstrap.py
index 77fd037..e496539 100644
--- a/renpy/bootstrap.py
+++ b/renpy/bootstrap.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
 import os.path
 import sys
 import subprocess
@@ -29,6 +30,8 @@ import renpy.error
 FSENCODING = sys.getfilesystemencoding() or "utf-8"
 
 # Extra things used for distribution.
+
+
 def extra_imports():
     import datetime; datetime
     import encodings.ascii; encodings.ascii
@@ -45,6 +48,7 @@ def extra_imports():
     import encodings.latin_1; encodings.latin_1
     import encodings.hex_codec; encodings.hex_codec
     import encodings.base64_codec; encodings.base64_codec
+    import encodings.idna; encodings.idna
     import math; math
     import glob; glob
     import pickle; pickle
@@ -69,6 +73,7 @@ def extra_imports():
     import _renpysteam; _renpysteam
     import compileall; compileall
 
+
 class NullFile(io.IOBase):
     """
     This file raises an error on input, and IOError on read.
@@ -80,6 +85,7 @@ class NullFile(io.IOBase):
     def read(self, length=None):
         raise IOError("Not implemented.")
 
+
 def null_files():
     try:
         if sys.stderr.fileno() < 0:
@@ -96,11 +102,13 @@ null_files()
 trace_file = None
 trace_local = None
 
+
 def trace_function(frame, event, arg):
     fn = os.path.basename(frame.f_code.co_filename)
-    print >>trace_file, fn, frame.f_lineno, frame.f_code.co_name, event
+    print(fn, frame.f_lineno, frame.f_code.co_name, event, file=trace_file)
     return trace_local
 
+
 def enable_trace(level):
     global trace_file
     global trace_local
@@ -114,24 +122,26 @@ def enable_trace(level):
 
     sys.settrace(trace_function)
 
+
 def mac_start(fn):
     os.system("open " + fn)
 
 # This code fixes a bug in subprocess.Popen.__del__
+
+
 def popen_del(self, *args, **kwargs):
     return
 
-def bootstrap(renpy_base):
 
-    global renpy # W0602
+def bootstrap(renpy_base):
 
-    import renpy.log #@UnusedImport
+    global renpy  # W0602
 
-    os.environ["RENPY_BASE"] = os.path.abspath(renpy_base)
+    import renpy.log  # @UnusedImport
 
     # Remove a legacy environment setting.
-    if os.environ.get("SDL_VIDEODRIVER", "") == "windib":
-        del os.environ["SDL_VIDEODRIVER"]
+    if os.environ.get(b"SDL_VIDEODRIVER", "") == "windib":
+        del os.environ[b"SDL_VIDEODRIVER"]
 
     renpy_base = unicode(renpy_base, FSENCODING, "replace")
 
@@ -178,7 +188,6 @@ def bootstrap(renpy_base):
         sys.stderr.write("Base directory %r does not exist. Giving up.\n" % (basedir,))
         sys.exit(1)
 
-
     gamedirs = [ name ]
     game_name = name
 
@@ -204,10 +213,14 @@ def bootstrap(renpy_base):
 
     sys.path.insert(0, basedir)
 
-    # If we're on a mac, install our own os.start.
     if renpy.macintosh:
+        # If we're on a mac, install our own os.start.
         os.startfile = mac_start
 
+        # Are we starting from inside a mac app resources directory?
+        if basedir.endswith("Contents/Resources/autorun"):
+            renpy.macapp = True
+
     # Check that we have installed pygame properly. This also deals with
     # weird cases on Windows and Linux where we can't import modules. (On
     # windows ";" is a directory separator in PATH, so if it's in a parent
@@ -217,38 +230,38 @@ def bootstrap(renpy_base):
         import pygame_sdl2
         pygame_sdl2.import_as_pygame()
     except:
-        print >>sys.stderr, """\
+        print("""\
 Could not import pygame_sdl2. Please ensure that this program has been built
 and unpacked properly. Also, make sure that the directories containing
 this program do not contain : or ; in their names.
 
 You may be using a system install of python. Please run {0}.sh,
 {0}.exe, or {0}.app instead.
-""".format(name)
+""".format(name), file=sys.stderr)
 
         raise
 
     # If we're not given a command, show the presplash.
     if args.command == "run" and not renpy.mobile:
-        import renpy.display.presplash #@Reimport
+        import renpy.display.presplash  # @Reimport
         renpy.display.presplash.start(basedir, gamedir)
 
     # Ditto for the Ren'Py module.
     try:
         import _renpy; _renpy
     except:
-        print >>sys.stderr, """\
+        print("""\
 Could not import _renpy. Please ensure that this program has been built
 and unpacked properly.
 
 You may be using a system install of python. Please run {0}.sh,
 {0}.exe, or {0}.app instead.
-""".format(name)
+""".format(name), file=sys.stderr)
         raise
 
     # Load up all of Ren'Py, in the right order.
 
-    import renpy #@Reimport
+    import renpy  # @Reimport
     renpy.import_all()
 
     renpy.loader.init_importer()
@@ -272,7 +285,7 @@ You may be using a system install of python. Please run {0}.sh,
                     renpy.config.logdir = basedir
 
                 if not os.path.exists(renpy.config.logdir):
-                    os.makedirs(renpy.config.logdir, 0777)
+                    os.makedirs(renpy.config.logdir, 0o777)
 
                 renpy.main.main()
 
@@ -300,7 +313,7 @@ You may be using a system install of python. Please run {0}.sh,
             except renpy.game.ParseErrorException:
                 pass
 
-            except Exception, e:
+            except Exception as e:
                 renpy.error.report_exception(e)
                 pass
 
diff --git a/renpy/character.py b/renpy/character.py
index fea4f23..e82007e 100644
--- a/renpy/character.py
+++ b/renpy/character.py
@@ -31,6 +31,7 @@ TAG_RE = re.compile(r'(\{\{)|(\{(p|w|nw|fast)(?:\=([^}]*))?\})', re.S)
 
 less_pauses = ("RENPY_LESS_PAUSES" in os.environ)
 
+
 class DialogueTextTags(object):
     """
     This object parses the text tags that only make sense in dialogue,
@@ -143,7 +144,7 @@ def compute_widget_properties(who_args, what_args, window_args, variant=None):
 
     def style_args(d):
 
-        if not "style" in d:
+        if "style" not in d:
             return d
 
         in_rollback = renpy.exports.in_rollback()
@@ -270,8 +271,8 @@ def show_display_say(who, what, who_args={}, what_args={}, window_args={},
         renpy.display.screen.show_screen(
             screen,
             _widget_properties=props,
-            _transient = True,
-            _tag = tag,
+            _transient=True,
+            _tag=tag,
             who=who,
             what=what,
             _layer=layer,
@@ -281,7 +282,6 @@ def show_display_say(who, what, who_args={}, what_args={}, window_args={},
 
         return renpy.display.screen.get_widget(screen, "what", layer)
 
-
     # Apply the transform.
     if transform:
         renpy.ui.at(transform)
@@ -318,11 +318,10 @@ def show_display_say(who, what, who_args={}, what_args={}, window_args={},
     return rv
 
 
-
 class SlowDone(object):
     delay = None
 
-    def __init__(self, ctc, ctc_position, callback, interact, type, cb_args, delay): #@ReservedAssignment
+    def __init__(self, ctc, ctc_position, callback, interact, type, cb_args, delay):  # @ReservedAssignment
         self.ctc = ctc
         self.ctc_position = ctc_position
         self.callback = callback
@@ -358,23 +357,23 @@ class SlowDone(object):
 # This function takes care of repeatably showing the screen as part of
 # an interaction.
 def display_say(
-    who,
-    what,
-    show_function,
-    interact,
-    slow,
-    afm,
-    ctc,
-    ctc_pause,
-    ctc_position,
-    all_at_once,
-    cb_args,
-    with_none,
-    callback,
-    type, #@ReservedAssignment
-    checkpoint=True,
-    ctc_timedpause=None,
-    ctc_force=False):
+        who,
+        what,
+        show_function,
+        interact,
+        slow,
+        afm,
+        ctc,
+        ctc_pause,
+        ctc_position,
+        all_at_once,
+        cb_args,
+        with_none,
+        callback,
+        type,  # @ReservedAssignment
+        checkpoint=True,
+        ctc_timedpause=None,
+        ctc_force=False):
 
     if interact and (not renpy.game.preferences.skip_unseen) and (not renpy.game.context().seen_current(True)) and renpy.config.skipping == "fast":
         renpy.config.skipping = None
@@ -437,7 +436,6 @@ def display_say(
         pause_end = dtt.pause_end
         pause_delay = dtt.pause_delay
 
-
     for i, (start, end, delay) in enumerate(zip(pause_start, pause_end, pause_delay)):
 
         last_pause = (i == len(pause_start) - 1)
@@ -449,7 +447,6 @@ def display_say(
         else:
             behavior = None
 
-
         # The string to show.
         what_string = dtt.text
 
@@ -483,7 +480,7 @@ def display_say(
         # Show the text.
         what_text = show_function(who, what_string)
 
-        if not isinstance(what_text, renpy.text.text.Text): #@UndefinedVariable
+        if not isinstance(what_text, renpy.text.text.Text):  # @UndefinedVariable
             raise Exception("The say screen (or show_function) must return a Text object.")
 
         if what_ctc and ctc_position == "nestled":
@@ -551,6 +548,7 @@ class HistoryEntry(renpy.object.Object):
 # This is used to flag values that haven't been set by the user.
 NotSet = renpy.object.Sentinel("NotSet")
 
+
 class ADVCharacter(object):
     """
     The character object contains information about a character. When
@@ -574,10 +572,10 @@ class ADVCharacter(object):
 
     # When adding a new argument here, remember to add it to copy below.
     def __init__(
-        self,
-        name=NotSet,
-        kind=None,
-        **properties):
+            self,
+            name=NotSet,
+            kind=None,
+            **properties):
 
         if kind is None:
             kind = renpy.store.adv
@@ -593,7 +591,6 @@ class ADVCharacter(object):
             else:
                 return getattr(kind, n)
 
-
         # Similar, but it grabs the value out of kind.display_args instead.
         def d(n):
             if n in properties:
@@ -626,17 +623,17 @@ class ADVCharacter(object):
             self.image_tag = None
 
         self.display_args = dict(
-            interact = d('interact'),
-            slow = d('slow'),
-            afm = d('afm'),
-            ctc = renpy.easy.displayable_or_none(d('ctc')),
-            ctc_pause = renpy.easy.displayable_or_none(d('ctc_pause')),
-            ctc_timedpause = renpy.easy.displayable_or_none(d('ctc_timedpause')),
-            ctc_position = d('ctc_position'),
-            all_at_once = d('all_at_once'),
-            with_none = d('with_none'),
-            callback = d('callback'),
-            type = d('type'),
+            interact=d('interact'),
+            slow=d('slow'),
+            afm=d('afm'),
+            ctc=renpy.easy.displayable_or_none(d('ctc')),
+            ctc_pause=renpy.easy.displayable_or_none(d('ctc_pause')),
+            ctc_timedpause=renpy.easy.displayable_or_none(d('ctc_timedpause')),
+            ctc_position=d('ctc_position'),
+            all_at_once=d('all_at_once'),
+            with_none=d('with_none'),
+            callback=d('callback'),
+            type=d('type'),
             )
 
         if kind:
@@ -705,7 +702,6 @@ class ADVCharacter(object):
     def do_done(self, who, what):
         self.add_history("adv", who, what)
 
-
     # This is called when an extend occurs, before the usual add/show
     # cycel.
     def do_extend(self):
@@ -718,7 +714,6 @@ class ADVCharacter(object):
                     self.do_show,
                     **display_args)
 
-
     # This is called to predict images that will be used by this
     # statement.
     def do_predict(self, who, what):
@@ -785,19 +780,27 @@ class ADVCharacter(object):
             # Otherwise, just record the attributes of the image.
             images.predict_show("master", tagged_attrs, show=False)
 
-    def __str__(self):
+    def __unicode__(self):
+
         who = self.name
 
-        # If dynamic is set, evaluate the name expression.
         if self.dynamic:
             who = renpy.python.py_eval(who)
 
-        return who
+        return renpy.substitutions.substitute(who)[0]
+
+    def __str__(self):
+        return unicode(self).encode("utf-8")
+
+    def __format__(self, spec):
+        return format(unicode(self), spec)
+
+    def __repr__(self):
+        return "<Character: {!r}>".format(self.name)
 
     def empty_window(self):
         self("", interact=False, _call_done=False)
 
-
     def __call__(self, what, interact=True, _call_done=True, **kwargs):
 
         # Check self.condition to see if we should show this line at all.
@@ -889,7 +892,6 @@ class ADVCharacter(object):
 
                 self.resolve_say_attributes(False, remove=speaking)
 
-
     def predict(self, what):
 
         self.resolve_say_attributes(True)
@@ -936,10 +938,10 @@ class ADVCharacter(object):
         if history_length is None:
             return
 
-        if not renpy.store._history: # @UndefinedVariable
+        if not renpy.store._history:  # @UndefinedVariable
             return
 
-        history = renpy.store._history_list # @UndefinedVariable
+        history = renpy.store._history_list  # @UndefinedVariable
 
         h = HistoryEntry()
 
@@ -982,10 +984,10 @@ class ADVCharacter(object):
         if history_length is None:
             return
 
-        if not renpy.store._history: # @UndefinedVariable
+        if not renpy.store._history:  # @UndefinedVariable
             return
 
-        renpy.store._history_list.pop() # @UndefinedVariable
+        renpy.store._history_list.pop()  # @UndefinedVariable
 
 
 def Character(name=NotSet, kind=None, **properties):
@@ -1115,22 +1117,11 @@ def Character(name=NotSet, kind=None, **properties):
 
     Keyword arguments beginning with ``show_`` have the prefix
     stripped off, and are passed to the screen as arguments. For
-    example, the value of ``show_side_image`` will become the
-    value of the ``side_image`` variable in the screen.
-
-    Some useful ``show_`` variables implemented by the default screens are:
+    example, the value of ``show_myflag`` will become the value of
+    the ``myflag`` variable in the screen. (The myflag variable isn't
+    used by default, but can be used by a custom say screen.)
 
-    `show_side_image`
-        When given a Displayable, shows that displayable when the
-        dialogue is shown. The position of that displayable is
-        controlled by its position properties. This is often used
-        to show an image of the speaking character to the side
-        of the dialogue.
-
-    `show_two_window`
-        If true, restructures the layout so that the name of the
-        character is placed in one window, and the dialogue text in a
-        second window.
+    One show variable is, for historical reasons, handled by Ren'Py itself:
 
     `show_layer`
         If given, this should be a string giving the name of the layer
@@ -1161,4 +1152,3 @@ def Character(name=NotSet, kind=None, **properties):
 
 def DynamicCharacter(name_expr, **properties):
     return Character(name_expr, dynamic=True, **properties)
-
diff --git a/renpy/color.py b/renpy/color.py
index 7fb4cec..c3cd103 100644
--- a/renpy/color.py
+++ b/renpy/color.py
@@ -23,6 +23,7 @@
 import renpy.display
 import colorsys
 
+
 class Color(tuple):
     """
     :doc: color class
@@ -189,7 +190,6 @@ class Color(tuple):
         else:
             return "#{self[0]:02x}{self[1]:02x}{self[2]:02x}".format(self=self)
 
-
     def __repr__(self):
         return "<Color {}>".format(self.hexcode)
 
@@ -320,7 +320,6 @@ class Color(tuple):
         elif not isinstance(other, Color):
             other = Color(hsv=other, alpha=self.alpha)
 
-
         hsv = self.interpolate_core(self.hsv, other.hsv, fraction)
         alpha = self.interpolate_core(self.alpha, other.alpha, fraction)
 
@@ -342,7 +341,6 @@ class Color(tuple):
         elif not isinstance(other, Color):
             other = Color(hls=other, alpha=self.alpha)
 
-
         hls = self.interpolate_core(self.hls, other.hls, fraction)
         alpha = self.interpolate_core(self.alpha, other.alpha, fraction)
 
diff --git a/renpy/common/000window.rpy b/renpy/common/000window.rpy
index cbdc7fb..47a413b 100644
--- a/renpy/common/000window.rpy
+++ b/renpy/common/000window.rpy
@@ -37,6 +37,17 @@ init -1200 python:
     _window_auto = False
 
     def _window_show(trans=False):
+        """
+        :doc: window
+
+        The python equivalent of the "window show" statement.
+
+        `trans`
+            If False, the default window show transition is used. If None,
+            no transition is used. Otherwise, the specified transition is
+            used.
+        """
+
         if store._window:
             return
 
@@ -51,6 +62,17 @@ init -1200 python:
             store._window = True
 
     def _window_hide(trans=False):
+        """
+        :doc: window
+
+        The python equivalent of the "window hide" statement.
+
+        `trans`
+            If False, the default window hide transition is used. If None,
+            no transition is used. Otherwise, the specified transition is
+            used.
+        """
+
         if not store._window:
             return
 
diff --git a/renpy/common/00action_file.rpy b/renpy/common/00action_file.rpy
index 9e8c448..60ac1a4 100644
--- a/renpy/common/00action_file.rpy
+++ b/renpy/common/00action_file.rpy
@@ -85,10 +85,10 @@ init -1500 python:
         month = t[1] - 1
         wday = t[6]
 
-        rv.replace("%a", __(_weekday_name_short[wday]))
-        rv.replace("%A", __(_weekday_name_long[wday]))
-        rv.replace("%b", __(_month_name_short[month]))
-        rv.replace("%B", __(_month_name_long[month]))
+        rv = rv.replace("%a", __(_weekday_name_short[wday]))
+        rv = rv.replace("%A", __(_weekday_name_long[wday]))
+        rv = rv.replace("%b", __(_month_name_short[month]))
+        rv = rv.replace("%B", __(_month_name_long[month]))
 
         if "%" in rv:
             import time
@@ -545,6 +545,25 @@ init -1500 python:
     class FilePageNameInputValue(InputValue, DictEquality):
         """
         :doc: input_value
+
+        An input value that updates the name of a file page.
+
+        `pattern`
+            This is used for the default name of a page. Python-style substition
+            is performed, such that {} is replaced with the number of the page.
+
+        `auto`
+            The name of the autosave page.
+
+        `quick`
+            The name of the quicksave page.
+
+        `page`
+            If given, the number of the page to display. This should usually
+            be left as None, to give the current page.
+
+        `default`
+            If true, this input can be editable by default.
         """
 
         def __init__(self, pattern=_("Page {}"), auto=_("Automatic saves"), quick=_("Quick saves"), page=None, default=False):
@@ -584,7 +603,7 @@ init -1500 python:
             else:
 
                 page = int(page)
-                default = self.pattern.format(page)
+                default = __(self.pattern).format(page)
                 rv = persistent._file_page_name.get(page, default)
 
                 if not rv.strip():
@@ -603,8 +622,16 @@ init -1500 python:
             if page == "auto" or page =="quick":
                 return
 
+            default = __(self.pattern).format(page)
+
             page = int(page)
-            persistent._file_page_name[page] = s
+
+            fnp = persistent._file_page_name
+
+            if s == default:
+                fnp.pop(page, None)
+            else:
+                fnp[page] = s
 
         def enter(self):
             renpy.run(self.Disable())
diff --git a/renpy/common/00action_other.rpy b/renpy/common/00action_other.rpy
index 788ddd2..ca18be6 100644
--- a/renpy/common/00action_other.rpy
+++ b/renpy/common/00action_other.rpy
@@ -431,6 +431,23 @@ init -1500 python:
             if _preferences.mouse_move:
                 renpy.set_mouse_pos(self.x, self.y, self.duration)
 
+
+    @renpy.pure
+    class QueueEvent(Action, DictEquality):
+        """
+        :doc: other_action
+
+        Queues the given event using :func:`renpy.queue_event`.
+        """
+
+        def __init__(self, event, up=False):
+            self.event = event
+            self.up = up
+
+        def __call__(self):
+            renpy.queue_event(self.event, up=self.up)
+
+
     class Function(Action, DictEquality):
         """
         :doc: other_action
diff --git a/renpy/common/00build.rpy b/renpy/common/00build.rpy
index 2e29836..e882d07 100644
--- a/renpy/common/00build.rpy
+++ b/renpy/common/00build.rpy
@@ -221,11 +221,18 @@ init -1500 python in build:
         "**/*.so.*",
         "**/*.so",
         "**/*.dylib",
-        "**.app/Contents/MacOS/*",
+
         "lib/**/python",
         "lib/**/pythonw",
         "lib/**/zsync",
         "lib/**/zsyncmake",
+
+        "**.app/Contents/MacOS/*",
+
+        "**.app/Contents/MacOS/lib/**/python",
+        "**.app/Contents/MacOS/lib/**/pythonw",
+        "**.app/Contents/MacOS/lib/**/zsync",
+        "**.app/Contents/MacOS/lib/**/zsyncmake",
         ]
 
     def executable(pattern):
@@ -258,10 +265,18 @@ init -1500 python in build:
 
             zip
                 A zip file.
-            app-zip
-                A zip file containing a macintosh application.
             tar.bz2
                 A tar.bz2 file.
+            directory
+                A directory containing the files.
+            dmg
+                A Macintosh DMG containing the files.
+            app-zip
+                A zip file containing a macintosh application.
+            app-directory
+                A directory containing the mac app.
+            app-dmg
+                A macintosh drive image containing a dmg. (Mac only.)
 
             The empty string will not build any package formats (this
             makes dlc possible).
@@ -289,7 +304,7 @@ init -1500 python in build:
         formats = format.split()
 
         for i in formats:
-            if i not in [ "zip", "app-zip", "tar.bz2", "directory" ]:
+            if i not in [ "zip", "app-zip", "tar.bz2", "directory", "dmg", "app-directory", "app-dmg" ]:
                 raise Exception("Format {} not known.".format(i))
 
         if description is None:
@@ -307,10 +322,11 @@ init -1500 python in build:
 
         packages.append(d)
 
-    package("all", "zip", "windows mac linux renpy all", "All Desktop Platforms")
+    package("pc", "zip", "windows linux renpy all", "PC: Windows and Linux")
     package("linux", "tar.bz2", "linux renpy all", "Linux x86/x86_64")
-    package("mac", "app-zip", "mac renpy all", "Macintosh x86")
+    package("mac", "app-zip app-dmg", "mac renpy all", "Macintosh x86_64")
     package("win", "zip", "windows renpy all", "Windows x86")
+    package("steam", "zip", "windows linux mac renpy all", "Windows, Mac, Linux for Steam")
     package("android", "directory", "android renpy all", hidden=True, update=False, dlc=True)
     package("ios", "directory", "ios renpy all", hidden=True, update=False, dlc=True)
 
@@ -359,13 +375,25 @@ init -1500 python in build:
     # Should we include the old Ren'Py themes?
     include_old_themes = True
 
+    # The identity used for codesigning and dmg building.
+    mac_identity = None
+
+    # The command used for mac codesigning.
+    mac_codesign_command = [ "/usr/bin/codesign", "-s", "{identity}", "-f", "--deep", "--no-strict", "{app}" ]
+
+    # The command used to build a dmg.
+    mac_create_dmg_command = [ "/usr/bin/hdiutil", "create", "-format", "UDBZ", "-volname", "{volname}", "-sourcedir", "{sourcedir}", "-ov", "{dmg}" ]
+
+    # The command used to sign a dmg.
+    mac_codesign_dmg_command = [ "/usr/bin/codesign", "-s", "{identity}", "-f", "{dmg}" ]
+
+
     # This function is called by the json_dump command to dump the build data
     # into the json file.
     def dump():
 
         rv = { }
 
-
         if not include_old_themes:
             exclude_old_themes = [
                 ( "renpy/common/_compat/**", None),
@@ -376,8 +404,6 @@ init -1500 python in build:
         else:
             exclude_old_themes = [ ]
 
-
-
         rv["directory_name"] = directory_name
         rv["executable_name"] = executable_name
         rv["include_update"] = include_update
@@ -413,6 +439,12 @@ init -1500 python in build:
         if itch_project:
             rv["itch_project"] = itch_project
 
+        if mac_identity:
+            rv["mac_identity"] = mac_identity
+            rv["mac_codesign_command"] = mac_codesign_command
+            rv["mac_create_dmg_command"] = mac_create_dmg_command
+            rv["mac_codesign_dmg_command"] = mac_codesign_dmg_command
+
         return rv
 
 init 1500 python in build:
diff --git a/renpy/common/00console.rpy b/renpy/common/00console.rpy
index a76088c..ae62fcc 100644
--- a/renpy/common/00console.rpy
+++ b/renpy/common/00console.rpy
@@ -179,7 +179,6 @@ init -1500 python in _console:
             message = ""
 
             if self.first_time:
-                message += __("%(version)s console, originally by Shiz, C, and delta.\n") % {"version": renpy.version()}
                 message += __("Press <esc> to exit console. Type help for help.\n")
                 self.first_time = False
 
@@ -349,6 +348,9 @@ init -1500 python in _console:
                 raise
 
             except:
+                import traceback
+                traceback.print_exc()
+
                 he.result = self.format_exception()
                 he.is_error = True
 
diff --git a/renpy/common/00gamemenu.rpy b/renpy/common/00gamemenu.rpy
index bc96255..5cb0dfd 100644
--- a/renpy/common/00gamemenu.rpy
+++ b/renpy/common/00gamemenu.rpy
@@ -157,7 +157,7 @@ label _enter_game_menu:
     return
 
 # Entry points from the game into menu-space.
-label _game_menu(_game_menu_screen=_game_menu_screen, *args, **kwargs):
+label _game_menu(*args, _game_menu_screen=_game_menu_screen, **kwargs):
     if not _game_menu_screen:
         return
 
diff --git a/renpy/common/00gamepad.rpy b/renpy/common/00gamepad.rpy
index cddacf2..33aca2a 100644
--- a/renpy/common/00gamepad.rpy
+++ b/renpy/common/00gamepad.rpy
@@ -231,8 +231,8 @@ init -1200 python in _gamepad:
         for k, v in sorted(mappings.items()):
             mapping += ",{}:{}".format(k, v)
 
-        print "Controller mapping for", name, "is:"
-        print mapping
+        print("Controller mapping for", name, "is:")
+        print(mapping)
 
         try:
             with open(os.path.join(renpy.config.renpy_base, "gamecontrollerdb.txt"), "a") as f:
diff --git a/renpy/common/00gui.rpy b/renpy/common/00gui.rpy
index c7f5f71..8495dd5 100644
--- a/renpy/common/00gui.rpy
+++ b/renpy/common/00gui.rpy
@@ -224,16 +224,16 @@ init -1100 python in gui:
     ############################################################################
     # Strings used by the confirm screen.
 
-    ARE_YOU_SURE = layout.ARE_YOU_SURE
-    DELETE_SAVE = layout.DELETE_SAVE
-    OVERWRITE_SAVE = layout.OVERWRITE_SAVE
-    LOADING = layout.LOADING
-    QUIT = layout.QUIT
-    MAIN_MENU = layout.MAIN_MENU
-    END_REPLAY = layout.END_REPLAY
-    SLOW_SKIP = layout.SLOW_SKIP
-    FAST_SKIP_UNSEEN = layout.FAST_SKIP_UNSEEN
-    FAST_SKIP_SEEN = layout.FAST_SKIP_SEEN
+    ARE_YOU_SURE = _("Are you sure?")
+    DELETE_SAVE = _("Are you sure you want to delete this save?")
+    OVERWRITE_SAVE = _("Are you sure you want to overwrite your save?")
+    LOADING = _("Loading will lose unsaved progress.\nAre you sure you want to do this?")
+    QUIT = _("Are you sure you want to quit?")
+    MAIN_MENU = _("Are you sure you want to return to the main menu?\nThis will lose unsaved progress.")
+    END_REPLAY = _("Are you sure you want to end the replay?")
+    SLOW_SKIP = _("Are you sure you want to begin skipping?")
+    FAST_SKIP_SEEN = _("Are you sure you want to skip to the next choice?")
+    FAST_SKIP_UNSEEN = _("Are you sure you want to skip unseen dialogue to the next choice?")
 
     ############################################################################
     # Image generation. This lives here since it wants to read data from
diff --git a/renpy/common/00iap.rpy b/renpy/common/00iap.rpy
index 2b36678..5f19f5d 100644
--- a/renpy/common/00iap.rpy
+++ b/renpy/common/00iap.rpy
@@ -184,8 +184,8 @@ init -1500 python in iap:
 
     if renpy.ios:
         import pyobjus
-        IAPHelper = pyobjus.autoclass("IAPHelper")
-        NSMutableArray = pyobjus.autoclass("NSMutableArray")
+        IAPHelper = pyobjus.autoclass(b"IAPHelper")
+        NSMutableArray = pyobjus.autoclass(b"NSMutableArray")
 
         from pyobjus import objc_str, objc_arr
 
@@ -212,6 +212,10 @@ init -1500 python in iap:
             else:
                 return None
 
+
+        def set_title(self):
+            self.helper.dialogTitle = __("Contacting App Store\nPlease Wait...")
+
         def identifier(self, p):
             """
             Returns the identifier for a store purchase.
@@ -246,6 +250,7 @@ init -1500 python in iap:
             self.validated_products = True
 
         def purchase(self, p, interact=True):
+            self.set_title()
             self.validate_products(interact)
 
             identifier = objc_str(self.identifier(p))
@@ -253,6 +258,7 @@ init -1500 python in iap:
             self.wait_for_result(interact=interact)
 
         def restore_purchases(self, interact=True):
+            self.set_title()
             self.validate_products(interact)
 
             self.helper.restorePurchases()
@@ -275,8 +281,6 @@ init -1500 python in iap:
             if renpy.predicting():
                 return None
 
-            self.validate_products(False)
-
             identifier = objc_str(self.identifier(p))
             rv = self.helper.formatPrice_(identifier)
 
@@ -286,7 +290,7 @@ init -1500 python in iap:
             return rv
 
         def init(self):
-            return
+            self.helper.validateProductIdentifiersInBackground()
 
 
     # The backend we're using.
@@ -527,8 +531,8 @@ init -1500 python in iap:
         :doc: iap
 
         Returns the name of the enabled store for in-app purchase. This
-        currently returns one of "amazon", "google", "ios" or None if no store
-        is available.
+        currently returns one of "amazon", "play" (for Google Play), "ios"
+        or None if no store is available.
         """
 
         return backend.get_store_name()
@@ -550,7 +554,7 @@ init -1500 python in iap:
         """
 
         from jnius import autoclass
-        Store = autoclass('org.renpy.iap.Store')
+        Store = autoclass(b'org.renpy.iap.Store')
         store = Store.getStore()
 
         store_name = store.getStoreName()
diff --git a/renpy/common/00images.rpy b/renpy/common/00images.rpy
index 0f6ce94..a75f187 100644
--- a/renpy/common/00images.rpy
+++ b/renpy/common/00images.rpy
@@ -41,7 +41,7 @@ init 1900 python hide:
             basename = os.path.basename(fn)
             base, ext = os.path.splitext(basename)
 
-            if not ext.lower() in [ ".jpg", ".png" ]:
+            if not ext.lower() in [ ".jpg", ".png", ".webp" ]:
                 continue
 
             base = base.lower()
diff --git a/renpy/common/00inputvalues.rpy b/renpy/common/00inputvalues.rpy
index 6bccb82..0f117f6 100644
--- a/renpy/common/00inputvalues.rpy
+++ b/renpy/common/00inputvalues.rpy
@@ -64,6 +64,20 @@ init -1510 python:
             return rv
 
     @renpy.pure
+    class DisableAllInputValues(Action):
+        """
+        :doc: other_action
+
+        Disables all active InputValue. This will re-focus the default
+        InputValue, if there is one. Otherwise, no InputValue will be
+        focused.
+        """
+
+        def __call__(self):
+            renpy.set_editable_input_value(None, False)
+            renpy.restart_interaction()
+
+    @renpy.pure
     class InputValue(renpy.object.Object):
 
         default = True
diff --git a/renpy/common/00keymap.rpy b/renpy/common/00keymap.rpy
index e194aeb..a87de67 100644
--- a/renpy/common/00keymap.rpy
+++ b/renpy/common/00keymap.rpy
@@ -50,6 +50,7 @@ init -1600 python:
         # Say.
         rollforward = [ 'mousedown_5', 'K_PAGEDOWN', 'repeat_K_PAGEDOWN' ],
         dismiss = [ 'mouseup_1', 'K_RETURN', 'K_SPACE', 'K_KP_ENTER', 'K_SELECT' ],
+        dismiss_unfocused = [ ],
 
         # Pause.
         dismiss_hard_pause = [ ],
@@ -89,6 +90,7 @@ init -1600 python:
 
         # These keys control skipping.
         skip = [ 'K_LCTRL', 'K_RCTRL' ],
+        stop_skipping = [ ],
         toggle_skip = [ 'K_TAB' ],
         fast_skip = [ '>' ],
 
@@ -215,7 +217,7 @@ init -1600 python:
             pass
 
     import os
-    config.screenshot_pattern = os.environ.get("RENPY_SCREENSHOT_PATTERN", "screenshot%04d.png")
+    config.screenshot_pattern = os.environ.get(b"RENPY_SCREENSHOT_PATTERN", b"screenshot%04d.png")
     del os
 
     # Called to make a screenshot happen.
@@ -224,16 +226,10 @@ init -1600 python:
         import os
         import __main__
 
-        # Pick the directory to save into.
-        dest = config.renpy_base.rstrip("/")
+        dest = config.renpy_base
 
-        # Guess if we're an OSX App.
-        if dest.endswith("/Contents/Resources/autorun"):
-            # Go up 4 directories.
-            dest = os.path.dirname(dest)
-            dest = os.path.dirname(dest)
-            dest = os.path.dirname(dest)
-            dest = os.path.dirname(dest)
+        if renpy.macapp:
+            dest = os.path.expanduser(b"~/Desktop")
 
         # Try to pick a filename.
         i = 1
@@ -380,6 +376,7 @@ label _hide_windows:
 
     python:
         _windows_hidden = True
+        voice_sustain()
         ui.saybehavior(dismiss=['dismiss', 'hide_windows'])
         ui.interact(suppress_overlay=True, suppress_window=True)
         _windows_hidden = False
diff --git a/renpy/common/00layout.rpy b/renpy/common/00layout.rpy
index d0688b3..03aa3da 100644
--- a/renpy/common/00layout.rpy
+++ b/renpy/common/00layout.rpy
@@ -447,16 +447,16 @@ init -1400 python hide:
     def screen_yesno_prompt():
         renpy.load_module("_layout/screen_yesno_prompt")
 
-    layout.ARE_YOU_SURE = _("Are you sure?")
-    layout.DELETE_SAVE = _("Are you sure you want to delete this save?")
-    layout.OVERWRITE_SAVE = _("Are you sure you want to overwrite your save?")
-    layout.LOADING = _("Loading will lose unsaved progress.\nAre you sure you want to do this?")
-    layout.QUIT = _("Are you sure you want to quit?")
-    layout.MAIN_MENU = _("Are you sure you want to return to the main menu?\nThis will lose unsaved progress.")
-    layout.END_REPLAY = _("Are you sure you want to end the replay?")
-    layout.SLOW_SKIP = _("Are you sure you want to begin skipping?")
-    layout.FAST_SKIP_SEEN = _("Are you sure you want to skip to the next choice?")
-    layout.FAST_SKIP_UNSEEN = _("Are you sure you want to skip unseen dialogue to the next choice?")
+    layout.ARE_YOU_SURE = "Are you sure?"
+    layout.DELETE_SAVE = "Are you sure you want to delete this save?"
+    layout.OVERWRITE_SAVE = "Are you sure you want to overwrite your save?"
+    layout.LOADING = "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    layout.QUIT = "Are you sure you want to quit?"
+    layout.MAIN_MENU = "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    layout.END_REPLAY = "Are you sure you want to end the replay?"
+    layout.SLOW_SKIP = "Are you sure you want to begin skipping?"
+    layout.FAST_SKIP_SEEN = "Are you sure you want to skip to the next choice?"
+    layout.FAST_SKIP_UNSEEN = "Are you sure you want to skip unseen dialogue to the next choice?"
 
     config.enter_yesno_transition = None
     config.exit_yesno_transition = None
diff --git a/renpy/common/00library.rpy b/renpy/common/00library.rpy
index de0573e..364ca2b 100644
--- a/renpy/common/00library.rpy
+++ b/renpy/common/00library.rpy
@@ -175,12 +175,9 @@ init -1700 python:
 
         if config.skip_indicator is True:
 
-            if config.skipping == "slow" and config.skip_indicator:
+            if config.skipping:
                 ui.text(_(u"Skip Mode"), style='skip_indicator')
 
-            if config.skipping == "fast" and config.skip_indicator:
-                ui.text(_(u"Fast Skip Mode"), style='skip_indicator')
-
             return
 
         if not config.skip_indicator:
@@ -277,6 +274,8 @@ init -1000 python:
 # After init, make some changes based on if config.developer is True.
 init 1700 python hide:
 
+    config.original_developer = config.developer
+
     if config.developer == "auto":
         if config.script_version:
             config.developer = False
@@ -292,7 +291,7 @@ init 1700 python hide:
         renpy.load_module("_developer/inspector")
 
     if config.window_title is None:
-        config.window_title = config.name or _("A Ren'Py Game")
+        config.window_title = config.name or "A Ren'Py Game"
 
 
 # Used by renpy.return() to return.
diff --git a/renpy/common/00musicroom.rpy b/renpy/common/00musicroom.rpy
index 6031acb..36ec097 100644
--- a/renpy/common/00musicroom.rpy
+++ b/renpy/common/00musicroom.rpy
@@ -35,7 +35,6 @@ init -1500 python:
         identity_fields = [ "mr" ]
         equality_fields = [ "filename" ]
 
-
         def __init__(self, mr, filename):
             self.mr = mr
             self.filename = filename
@@ -101,6 +100,34 @@ init -1500 python:
             return renpy.music.get_playing(self.mr.channel) is not None
 
 
+    @renpy.pure
+    class __MusicRoomStop(Action, FieldEquality):
+        """
+        The action returned by MusicRoom.Stop.
+        """
+
+        identity_fields = [ "mr" ]
+
+        def __init__(self, mr):
+            self.mr = mr
+            self.selected = self.get_selected()
+
+        def __call__(self):
+            self.mr.stop()
+
+        def get_selected(self):
+            return renpy.music.get_playing() is None
+
+        def periodic(self, st):
+            if self.selected != self.get_selected():
+                self.selected = self.get_selected()
+                renpy.restart_interaction()
+
+            self.mr.periodic(st)
+
+            return .1
+
+
     class MusicRoom(object):
         """
         :doc: music_room class
@@ -417,8 +444,7 @@ init -1500 python:
             This action stops the music.
             """
 
-            return self.stop
-
+            return __MusicRoomStop(self)
 
         def Next(self):
             """
diff --git a/renpy/common/00placeholder.rpy b/renpy/common/00placeholder.rpy
index 49d09e4..fdc1a84 100644
--- a/renpy/common/00placeholder.rpy
+++ b/renpy/common/00placeholder.rpy
@@ -143,6 +143,7 @@ init -1500 python:
                 rv = Fixed(
                     Solid("#aaa"),
                     Text(" ".join(self.name), style="_default", color="#333333", text_align=0.5, xalign=0.5, ypos=5),
+                    alt="",
                 )
 
                 self.child = rv
@@ -182,6 +183,7 @@ init -1500 python:
                 Transform(image, crop=crop, size=size, xzoom=xzoom),
                 Text(text, pos=textpos, xanchor=0.5, yanchor=0.5, style="_default", color="#aaa", text_align=0.5),
                 xysize=size,
+                alt="",
             )
 
             self.child = rv
@@ -190,6 +192,8 @@ init -1500 python:
         _duplicatable = True
 
         def _duplicate(self, args):
+            args = args or self._args
+
             rv = Placeholder(self.base, self.full, self.flip)
             rv.name = list(args.name) + list(args.args)
             return rv
diff --git a/renpy/common/00start.rpy b/renpy/common/00start.rpy
index 275bd3d..5937cf4 100644
--- a/renpy/common/00start.rpy
+++ b/renpy/common/00start.rpy
@@ -86,6 +86,7 @@ label _after_load:
         _in_replay = None
 
         renpy.execute_default_statement(False)
+        _init_language()
 
     python hide:
 
@@ -150,6 +151,7 @@ label _start_replay:
     else:
         scene
 
+    $ _init_language()
     $ renpy.block_rollback()
 
     jump expression _in_replay
@@ -244,6 +246,8 @@ label _start:
             renpy.transition(config.end_splash_transition)
         else:
             renpy.transition(_restart[0])
+
+            renpy.game.context().force_checkpoint = True
             renpy.jump(_restart[1])
 
 label _invoke_main_menu:
@@ -257,7 +261,10 @@ label _invoke_main_menu:
 
 
     # If the main menu returns, then start the game.
-    jump start
+
+    python:
+        renpy.game.context().force_checkpoint = True
+        renpy.jump("start")
 
 # At this point, we've been switched into a new context. So we
 # initialize it.
diff --git a/renpy/common/00stylepreferences.rpy b/renpy/common/00stylepreferences.rpy
index 11cb81a..0467878 100644
--- a/renpy/common/00stylepreferences.rpy
+++ b/renpy/common/00stylepreferences.rpy
@@ -93,17 +93,22 @@ init -1500 python:
         if not __spdirty.flag:
             return
 
+        renpy.style.rebuild()
+
+        __spdirty.flag = False
+
+    def __apply_styles():
+        """
+        Called to apply the style preferences
+        """
+
         for preference, alternatives in __preferences.iteritems():
 
             alt = persistent._style_preferences.get(preference, None)
 
-            for alternative, style, property, value in alternatives:
+            for alternative, s, property, value in alternatives:
                 if alternative == alt:
-                    setattr(style, property, value)
-
-        renpy.style.rebuild()
-
-        __spdirty.flag = False
+                    setattr(s, property, value)
 
     def __check(preference, alternative=None):
 
@@ -187,6 +192,7 @@ init -1500 python:
 
     config.interact_callbacks.append(__update)
     config.change_language_callbacks.append(__change_language)
+    config.build_styles_callbacks.append(__apply_styles)
 
 init 1500 python:
     __init()
diff --git a/renpy/common/00updater.rpy b/renpy/common/00updater.rpy
index f5598c0..3b877bd 100644
--- a/renpy/common/00updater.rpy
+++ b/renpy/common/00updater.rpy
@@ -132,7 +132,9 @@ init -1500 python in updater:
         else:
             suffix = ""
 
-        rv = os.path.join(os.path.dirname(sys.executable), command + suffix)
+        executable = renpy.fsdecode(sys.executable)
+
+        rv = os.path.join(os.path.dirname(executable), command + suffix)
 
         if os.path.exists(rv):
             return rv
@@ -222,6 +224,10 @@ init -1500 python in updater:
 
             threading.Thread.__init__(self)
 
+            import os
+            if "RENPY_FORCE_UPDATE" in os.environ:
+                force = True
+
             # The main state.
             self.state = Updater.CHECKING
 
@@ -1128,7 +1134,7 @@ init -1500 python in updater:
                 self.unlink(i)
 
                 if os.path.exists(i):
-                    self.log.write("could not delete file %s" % path.encode("utf-8"))
+                    self.log.write("could not delete file %s" % i.encode("utf-8"))
                     with open(DEFERRED_UPDATE_FILE, "wb") as f:
                         f.write("D " + i.encode("utf-8") + "\n")
 
@@ -1354,13 +1360,13 @@ init -1500 python in updater:
 
             state = u.state
 
-            print "State:", state
+            print("State:", state)
 
             if u.progress:
-                print "Progress: {:.1%}".format(u.progress)
+                print("Progress: {:.1%}".format(u.progress))
 
             if u.message:
-                print "Message:", u.message
+                print("Message:", u.message)
 
             if state == u.ERROR:
                 break
diff --git a/renpy/common/00voice.rpy b/renpy/common/00voice.rpy
index 0a53408..5da3ded 100644
--- a/renpy/common/00voice.rpy
+++ b/renpy/common/00voice.rpy
@@ -381,7 +381,9 @@ init -1500 python hide:
 
         elif not _voice.sustain:
             renpy.sound.stop(channel="voice")
-            store._last_voice_play = None
+
+            if not getattr(renpy.context(), "_menu", False):
+                store._last_voice_play = None
 
         _voice.play = None
         _voice.sustain = False
@@ -462,8 +464,8 @@ python early hide:
         except:
             return
 
-        if not renpy.loadable(fn):
-            renpy.error('voice file %r is not loadable' % fn)
+        if not renpy.music.playable(fn, 'voice'):
+            renpy.error('voice file %r is not playable' % fn)
 
     renpy.statements.register('voice',
                               parse=parse_voice,
diff --git a/renpy/common/_developer/developer.rpym b/renpy/common/_developer/developer.rpym
index 0668970..184042b 100644
--- a/renpy/common/_developer/developer.rpym
+++ b/renpy/common/_developer/developer.rpym
@@ -520,19 +520,39 @@ init python:
 
         for when, filename, preload in ill:
             if preload:
-                color="#ffffff"
+                color="#ccffcc"
+                prefix=__("✔ ")
             else:
                 color="#ffcccc"
+                prefix=__("✘ ")
 
-            vbox.add(Text(filename.replace("{", "{{").replace("[", "[["), size=12, color=color, style="_default"))
+            vbox.add(Text(prefix + filename.replace("{", "{{").replace("[", "[["), size=14, color=color, style="_default"))
 
-        rv = Window(vbox, style="_frame", background="#0004", xpadding=5, ypadding=5, xminimum=200)
-        return rv, .25
+        if at < 10.0:
+            vbox.add(Text(
+            _("\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"),
+            size=14, style="_default"))
+
+        return vbox, .25
 
 screen _image_load_log:
+
     zorder 1000
 
-    add DynamicDisplayable(_image_load_log_function)
+    drag:
+        draggable True
+        focus_mask None
+        xpos 0
+        ypos 0
+
+        frame:
+            style "empty"
+            background "#0004"
+            xpadding 5
+            ypadding 5
+            xminimum 200
+
+            add DynamicDisplayable(_image_load_log_function)
 
 
 
diff --git a/renpy/common/_errorhandling.rpym b/renpy/common/_errorhandling.rpym
index 520315d..7997400 100644
--- a/renpy/common/_errorhandling.rpym
+++ b/renpy/common/_errorhandling.rpym
@@ -24,6 +24,9 @@
 # that it is fully loaded or run before any other Ren'Py code runs.
 
 
+init python in gui:
+    system_font = None
+
 init python:
     style._default = Style(None)
 
@@ -32,6 +35,12 @@ init python hide:
     if renpy.loadable("gui.rpy") or renpy.loadable("gui.rpyc"):
         config.screen_width, config.screen_height = 1280, 720
 
+    def init_system_styles():
+        if gui.system_font is not None:
+            style._default.font = gui.system_font
+
+    config.init_system_styles = init_system_styles
+
 init label _errorhandling:
 
     python in gui:
@@ -522,6 +531,7 @@ screen _exception:
             id "viewport"
             child_size (4000, None)
             mousewheel True
+            draggable True
             scrollbars "both"
 
             has vbox
@@ -584,6 +594,7 @@ screen _parse_errors:
             id "viewport"
             child_size (4000, None)
             mousewheel True
+            draggable True
             scrollbars "both"
             xfill True
             yfill True
diff --git a/renpy/config.py b/renpy/config.py
index f20e5cd..13964c4 100644
--- a/renpy/config.py
+++ b/renpy/config.py
@@ -25,13 +25,15 @@
 
 # This will be deleted by the end of this file.
 import renpy.display
+
+import collections
 import os
 
 # Can we add more config variables?
 locked = False
 
 # Contains help for config variables.
-help = [ ] #@ReservedAssignment
+help = [ ]  # @ReservedAssignment
 
 # The title of the game window.
 window_title = None
@@ -232,17 +234,20 @@ frames = 0
 
 # NOT USED: A text editor that is launched at the location of the current
 # statement.
-editor = None # os.environ.get('RENPY_EDITOR', None)
+editor = None  # os.environ.get('RENPY_EDITOR', None)
 
 # NOT USED: Text editor, with arguments to reload or clobber the file - used,
 # for example, to display traceback.txt.
-editor_transient = None # os.environ.get('RENPY_EDITOR_TRANSIENT', editor)
+editor_transient = None  # os.environ.get('RENPY_EDITOR_TRANSIENT', editor)
 
 # NOT USED: The separator used between files in the text editor.
-editor_file_separator = None # os.environ.get('RENPY_EDITOR_FILE_SEPARATOR', '" "')
+editor_file_separator = None  # os.environ.get('RENPY_EDITOR_FILE_SEPARATOR', '" "')
 
 # Enable developer mode?
-developer = False # Changed to True or False in the init code.
+developer = False  # Changed to True or False in the init code.
+
+# The original value of config.developer.
+original_developer = False
 
 # A logfile that logging messages are sent to.
 log = None
@@ -378,7 +383,7 @@ gamedir = None
 basedir = None
 renpy_base = None
 commondir = None
-logdir = None # Where log and error files go.
+logdir = None  # Where log and error files go.
 
 # Should we enable OpenGL mode?
 gl_enable = True
@@ -718,8 +723,28 @@ max_fit_size = 8192
 # Should the window max size be enforced?
 enforce_window_max_size = True
 
+# The max priority to translate to.
+translate_launcher = False
+
+# A map from language to a list of callbacks that are used to help set it
+# up.
+language_callbacks = collections.defaultdict(list)
+
+# A function that is called to init system styles.
+init_system_styles = None
+
+# Callbacks that are called just before rebuilding styles.
+build_styles_callbacks = [ ]
+
+# Should movie displayables be given their own channels?
+auto_movie_channel = True
+
+# Should we ignore duplicate labels?
+ignore_duplicate_labels = False
+
 del renpy
 del os
 
+
 def init():
     pass
diff --git a/renpy/curry.py b/renpy/curry.py
index ef8cd05..dc1e5dd 100644
--- a/renpy/curry.py
+++ b/renpy/curry.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+
 class Curry(object):
     """
     Stores a callable and some arguments. When called, calls the
@@ -26,8 +27,7 @@ class Curry(object):
     supplied to the call.
     """
 
-
-    def __init__(self, callable, *args, **kwargs): #@ReservedAssignment
+    def __init__(self, callable, *args, **kwargs):  # @ReservedAssignment
         self.callable = callable
         self.args = args
         self.kwargs = kwargs
@@ -36,6 +36,7 @@ class Curry(object):
     def __call__(self, *args, **kwargs):
         return self.callable(*(self.args + args),
                              **dict(self.kwargs.items() + kwargs.items()))
+
     def __repr__(self):
         return "<curry %s %r %r>" % (self.callable, self.args, self.kwargs)
 
@@ -50,6 +51,7 @@ class Curry(object):
     def __hash__(self):
         return hash(self.callable) ^ hash(self.args) ^ hash(self.kwargs)
 
+
 def curry(fn):
     """
     Takes a callable, and returns something that, when called, returns
diff --git a/renpy/defaultstore.py b/renpy/defaultstore.py
index cda5092..f22aa85 100644
--- a/renpy/defaultstore.py
+++ b/renpy/defaultstore.py
@@ -61,6 +61,7 @@ _widget_properties = { }
 # The text rectangle, or None to use the automatic code.
 _text_rect = None
 
+
 class _Config(object):
 
     def __getstate__(self):
@@ -69,7 +70,7 @@ class _Config(object):
     def __setstate__(self, data):
         return
 
-    def register(self, name, default, cat=None, help=None): #@ReservedAssignment
+    def register(self, name, default, cat=None, help=None):  # @ReservedAssignment
         setattr(self, name, default)
         _config.help.append((cat, name, help))
 
@@ -88,7 +89,7 @@ class _Config(object):
             raise Exception('config.%s is not a known configuration variable.' % (name))
 
         if name == "script_version":
-            renpy.store._set_script_version(value) # E1101 @UndefinedVariable
+            renpy.store._set_script_version(value)  # E1101 @UndefinedVariable
 
         cvars[name] = value
 
@@ -104,7 +105,7 @@ style = None
 config = _Config()
 library = config
 
-eval = renpy.python.py_eval #@ReservedAssignment
+eval = renpy.python.py_eval  # @ReservedAssignment
 
 # Displayables.
 Bar = renpy.display.behavior.Bar
@@ -196,7 +197,7 @@ BarValue = renpy.ui.BarValue
 # NOTE: When exporting something from here, decide if we need to add it to
 # renpy.pyanalysis.pure_functions.
 
-Style = renpy.style.Style # @UndefinedVariable
+Style = renpy.style.Style  # @UndefinedVariable
 
 absolute = renpy.display.core.absolute
 
@@ -278,6 +279,7 @@ def AlphaBlend(control, old, new, alpha=False):
 
     return renpy.display.transition.AlphaDissolve(control, 0.0, old_widget=old, new_widget=new, alpha=alpha)
 
+
 def At(d, *args):
     """
     :doc: disp_at
@@ -312,7 +314,7 @@ Color = renpy.color.Color
 color = renpy.color.Color
 
 # Conveniently get rid of all the packages we had imported before.
-import renpy.exports as renpy #@Reimport
+import renpy.exports as renpy  # @Reimport
 
 # The default menu functions.
 menu = renpy.display_menu
@@ -366,6 +368,8 @@ adv = ADVCharacter(None,
 # predict_say and who are defined in 00library.rpy, but we add default
 # versions here in case there is a problem with initialization. (And
 # for pickling purposes.)
+
+
 def predict_say(who, what):
     who = Character(who, kind=adv)
     try:
@@ -373,6 +377,7 @@ def predict_say(who, what):
     except:
         pass
 
+
 def say(who, what, interact=True):
     who = Character(who, kind=adv)
     who(what, interact=interact)
@@ -408,6 +413,7 @@ main_menu = False
 import sys
 import os
 
+
 def public_api():
     ui
     im
@@ -418,4 +424,3 @@ def public_api():
     sys
 
 del public_api
-
diff --git a/renpy/display/__init__.py b/renpy/display/__init__.py
index 869dd47..bfc2555 100644
--- a/renpy/display/__init__.py
+++ b/renpy/display/__init__.py
@@ -38,6 +38,7 @@ touch = False
 # The pygame.display.Info object, which we want to survive a reload.
 info = None
 
+
 def get_info():
     global info
 
diff --git a/renpy/display/anim.py b/renpy/display/anim.py
index bd86ba7..2bf9b0b 100644
--- a/renpy/display/anim.py
+++ b/renpy/display/anim.py
@@ -27,12 +27,12 @@ import renpy.easy
 
 import random
 
+
 class State(object):
     """
     This creates a state that can be used in a SMAnimation.
     """
 
-
     def __init__(self, name, image, *atlist, **properties):
         """
         @param name: A string giving the name of this state.
@@ -61,7 +61,6 @@ class State(object):
         self.atlist = atlist
         self.properties = properties
 
-
     def add(self, sma):
         sma.states[self.name] = self
 
@@ -226,7 +225,6 @@ class SMAnimation(renpy.display.core.Displayable):
         the old and new states, and any transition that is present.
         """
 
-
         if self.edge.trans:
             im = self.edge.trans(old_widget=self.states[self.edge.old].get_image(),
                                  new_widget=self.states[self.edge.new].get_image())
@@ -272,7 +270,6 @@ class SMAnimation(renpy.display.core.Displayable):
                                              width, height,
                                              st - self.edge_start, at)
 
-
         # Otherwise, we have another edge.
 
         else:
@@ -284,7 +281,6 @@ class SMAnimation(renpy.display.core.Displayable):
             if not renpy.game.less_updates:
                 renpy.display.render.redraw(self.edge_cache, self.edge.delay - (t - self.edge_start))
 
-
         iw, ih = im.get_size()
 
         rv = renpy.display.render.Render(iw, ih)
@@ -432,7 +428,7 @@ class TransitionAnimation(renpy.display.core.Displayable):
                 transitions.append(arg)
 
         if len(images) > len(delays):
-            delays.append(365.25 * 86400.0) # One year, give or take.
+            delays.append(365.25 * 86400.0)  # One year, give or take.
         if len(images) > len(transitions):
             transitions.append(None)
 
@@ -441,7 +437,6 @@ class TransitionAnimation(renpy.display.core.Displayable):
         self.delays = delays
         self.transitions = [ transitions[-1] ] + transitions[:-1]
 
-
     def render(self, width, height, st, at):
 
         if self.anim_timebase:
@@ -472,13 +467,13 @@ class TransitionAnimation(renpy.display.core.Displayable):
     def visit(self):
         return self.images
 
+
 class Blink(renpy.display.core.Displayable):
     """
     """
 
-    def __init__(self, image, on=0.5, off=0.5, rise=0.5, set=0.5, #@ReservedAssignment
+    def __init__(self, image, on=0.5, off=0.5, rise=0.5, set=0.5,  # @ReservedAssignment
                  high=1.0, low=0.0, offset=0.0, anim_timebase=False, **properties):
-
         """
         This takes as an argument an image or widget, and blinks that image
         by varying its alpha. The sequence of phases is
@@ -519,7 +514,6 @@ class Blink(renpy.display.core.Displayable):
 
         self.cycle = on + set + off + rise
 
-
     def visit(self):
         return [ self.image ]
 
@@ -557,7 +551,6 @@ class Blink(renpy.display.core.Displayable):
             frac = time / self.rise
             alpha = self.high * frac + self.low * (1.0 - frac)
 
-
         rend = renpy.display.render.render(self.image, height, width, st, at)
         w, h = rend.get_size()
         rv = renpy.display.render.Render(w, h)
@@ -571,7 +564,6 @@ class Blink(renpy.display.core.Displayable):
         return rv
 
 
-
 def Filmstrip(image, framesize, gridsize, delay, frames=None, loop=True, **properties):
     """
     This creates an animation from a single image. This image
diff --git a/renpy/display/behavior.py b/renpy/display/behavior.py
index 88779c6..749b5b2 100644
--- a/renpy/display/behavior.py
+++ b/renpy/display/behavior.py
@@ -31,6 +31,7 @@ import pygame_sdl2 as pygame
 
 import math
 
+
 def compile_event(key, keydown):
     """
     Compiles a keymap entry into a python expression.
@@ -185,6 +186,7 @@ def queue_event(name, up=False, **kwargs):
     ev = pygame.event.Event(renpy.display.core.EVENTNAME, data)
     pygame.event.post(ev)
 
+
 def map_event(ev, keysym):
     """
     :doc: udd_utility
@@ -212,6 +214,7 @@ def map_event(ev, keysym):
 
     return check_code(ev)
 
+
 def map_keyup(ev, name):
     """Returns true if the event matches the named keycode being released."""
 
@@ -243,7 +246,7 @@ def skipping(ev):
         renpy.config.skipping = "slow"
         renpy.exports.restart_interaction()
 
-    if map_keyup(ev, "skip"):
+    if map_keyup(ev, "skip") or map_event(ev, "stop_skipping"):
         renpy.config.skipping = None
         renpy.exports.restart_interaction()
 
@@ -272,6 +275,7 @@ def predict_action(var):
         for i in var:
             predict_action(i)
 
+
 def run(action, *args, **kwargs):
     """
     :doc: run
@@ -301,6 +305,7 @@ def run(action, *args, **kwargs):
 
     return action(*args, **kwargs)
 
+
 def run_unhovered(var):
     """
     Calls the unhovered method on the variable, if it exists.
@@ -319,6 +324,7 @@ def run_unhovered(var):
     if f is not None:
         f()
 
+
 def run_periodic(var, st):
 
     if isinstance(var, (list, tuple)):
@@ -335,6 +341,7 @@ def run_periodic(var, st):
     if isinstance(var, renpy.ui.Action):
         return var.periodic(st)
 
+
 def is_selected(action):
     """
     :doc: run
@@ -344,7 +351,7 @@ def is_selected(action):
 
     if isinstance(action, (list, tuple)):
         for i in action:
-            if isinstance(i, renpy.store.SelectedIf): # @UndefinedVariable
+            if isinstance(i, renpy.store.SelectedIf):  # @UndefinedVariable
                 return i.get_selected()
         return any(is_selected(i) for i in action)
 
@@ -363,7 +370,7 @@ def is_sensitive(action):
 
     if isinstance(action, (list, tuple)):
         for i in action:
-            if isinstance(i, renpy.store.SensitiveIf): # @UndefinedVariable
+            if isinstance(i, renpy.store.SensitiveIf):  # @UndefinedVariable
                 return i.get_sensitive()
         return all(is_sensitive(i) for i in action)
 
@@ -372,6 +379,7 @@ def is_sensitive(action):
     else:
         return True
 
+
 def alt(clicked):
 
     if isinstance(clicked, (list, tuple)):
@@ -395,6 +403,7 @@ def alt(clicked):
 ##############################################################################
 # Special-Purpose Displayables
 
+
 class Keymap(renpy.display.layout.Null):
     """
     This is a behavior that maps keys to actions that are called when
@@ -468,9 +477,9 @@ class PauseBehavior(renpy.display.layout.Null):
             else:
                 renpy.game.interface.force_redraw = True
 
-
         renpy.game.interface.timeout(max(self.delay - st, 0))
 
+
 class SoundStopBehavior(renpy.display.layout.Null):
     """
     This is a class implementing the sound stop behavior,
@@ -484,7 +493,6 @@ class SoundStopBehavior(renpy.display.layout.Null):
         self.channel = channel
         self.result = result
 
-
     def event(self, ev, x, y, st):
 
         if not renpy.audio.music.get_playing(self.channel):
@@ -504,7 +512,9 @@ class SayBehavior(renpy.display.layout.Null):
     focusable = True
     text = None
 
-    def __init__(self, default=True, afm=None, dismiss=[ 'dismiss' ], allow_dismiss=None, **properties):
+    dismiss_unfocused = [ 'dismiss_unfocused' ]
+
+    def __init__(self, default=True, afm=None, dismiss=[ 'dismiss' ], allow_dismiss=None, dismiss_unfocused=[ 'dismiss_unfocused' ], **properties):
         super(SayBehavior, self).__init__(default=default, **properties)
 
         if not isinstance(dismiss, (list, tuple)):
@@ -547,9 +557,14 @@ class SayBehavior(renpy.display.layout.Null):
             else:
                 renpy.game.interface.timeout(afm_delay - st)
 
-        for dismiss in self.dismiss:
+        dismiss = [ (i, True) for i in self.dismiss ] + [ (i, False) for i in self.dismiss_unfocused ]
+
+        for dismiss_event, check_focus in dismiss:
 
-            if map_event(ev, dismiss) and self.is_focused():
+            if map_event(ev, dismiss_event):
+
+                if check_focus and not self.is_focused():
+                    continue
 
                 if renpy.config.skipping:
                     renpy.config.skipping = None
@@ -563,23 +578,25 @@ class SayBehavior(renpy.display.layout.Null):
                 else:
                     rollback_side = renpy.game.preferences.desktop_rollback_side
 
-                percent = 1.0 * x / renpy.config.screen_width
+                if ev.type == pygame.MOUSEBUTTONUP:
 
-                if rollback_side == "left":
+                    percent = 1.0 * x / renpy.config.screen_width
 
-                    if percent < renpy.config.rollback_side_size:
-                        renpy.exports.rollback()
-                        raise renpy.display.core.IgnoreEvent()
+                    if rollback_side == "left":
 
-                elif rollback_side == "right":
+                        if percent < renpy.config.rollback_side_size:
+                            renpy.exports.rollback()
+                            raise renpy.display.core.IgnoreEvent()
 
-                    if (1.0 - percent) < renpy.config.rollback_side_size:
-                        renpy.exports.rollback()
-                        raise renpy.display.core.IgnoreEvent()
+                    elif rollback_side == "right":
+
+                        if (1.0 - percent) < renpy.config.rollback_side_size:
+                            renpy.exports.rollback()
+                            raise renpy.display.core.IgnoreEvent()
 
                 if renpy.game.preferences.using_afm_enable and \
-                    renpy.game.preferences.afm_enable and \
-                    not renpy.game.preferences.afm_after_click:
+                        renpy.game.preferences.afm_enable and \
+                        not renpy.game.preferences.afm_after_click:
 
                     renpy.game.preferences.afm_enable = False
                     renpy.exports.restart_interaction()
@@ -602,10 +619,13 @@ class SayBehavior(renpy.display.layout.Null):
                     return True
                 elif renpy.game.context().seen_current(True):
                     return True
+                else:
+                    renpy.config.skipping = False
+                    renpy.exports.restart_interaction()
+
             else:
                 renpy.game.interface.timeout(skip_delay - st)
 
-
         return None
 
 
@@ -619,6 +639,7 @@ KEY_EVENTS = (
     pygame.TEXTINPUT
     )
 
+
 class Button(renpy.display.layout.Window):
 
     keymap = { }
@@ -653,7 +674,7 @@ class Button(renpy.display.layout.Window):
         self.unhovered = unhovered
         self.alternate = alternate
 
-        self.focusable = True #(clicked is not None) or (action is not None)
+        self.focusable = True  # (clicked is not None) or (action is not None)
         self.role_parameter = role
 
         self.keymap = keymap
@@ -872,7 +893,6 @@ class Button(renpy.display.layout.Window):
 
         return None
 
-
     def set_style_prefix(self, prefix, root):
         if root:
             super(Button, self).set_style_prefix(prefix, root)
@@ -885,12 +905,15 @@ class Button(renpy.display.layout.Window):
 
 # Reimplementation of the TextButton widget as a Button and a Text
 # widget.
+
+
 def TextButton(text, style='button', text_style='button_text',
                clicked=None, **properties):
 
-    text = renpy.text.text.Text(text, style=text_style) #@UndefinedVariable
+    text = renpy.text.text.Text(text, style=text_style)  # @UndefinedVariable
     return Button(text, style=style, clicked=clicked, **properties)
 
+
 class ImageButton(Button):
     """
     Used to implement the guts of an image button.
@@ -898,13 +921,13 @@ class ImageButton(Button):
 
     def __init__(self,
                  idle_image,
-                 hover_image = None,
-                 insensitive_image = None,
-                 activate_image = None,
-                 selected_idle_image = None,
-                 selected_hover_image = None,
-                 selected_insensitive_image = None,
-                 selected_activate_image = None,
+                 hover_image=None,
+                 insensitive_image=None,
+                 activate_image=None,
+                 selected_idle_image=None,
+                 selected_hover_image=None,
+                 selected_insensitive_image=None,
+                 selected_activate_image=None,
                  style='image_button',
                  clicked=None,
                  hovered=None,
@@ -920,15 +943,15 @@ class ImageButton(Button):
         selected_activate_image = selected_activate_image or activate_image
 
         self.state_children = dict(
-            idle_ = renpy.easy.displayable(idle_image),
-            hover_ = renpy.easy.displayable(hover_image),
-            insensitive_ = renpy.easy.displayable(insensitive_image),
-            activate_ = renpy.easy.displayable(activate_image),
-
-            selected_idle_ = renpy.easy.displayable(selected_idle_image),
-            selected_hover_ = renpy.easy.displayable(selected_hover_image),
-            selected_insensitive_ = renpy.easy.displayable(selected_insensitive_image),
-            selected_activate_ = renpy.easy.displayable(selected_activate_image),
+            idle_=renpy.easy.displayable(idle_image),
+            hover_=renpy.easy.displayable(hover_image),
+            insensitive_=renpy.easy.displayable(insensitive_image),
+            activate_=renpy.easy.displayable(activate_image),
+
+            selected_idle_=renpy.easy.displayable(selected_idle_image),
+            selected_hover_=renpy.easy.displayable(selected_hover_image),
+            selected_insensitive_=renpy.easy.displayable(selected_insensitive_image),
+            selected_activate_=renpy.easy.displayable(selected_activate_image),
             )
 
         super(ImageButton, self).__init__(None,
@@ -946,6 +969,7 @@ class ImageButton(Button):
 
 # This is used for an input that takes its focus from a button.
 class HoveredProxy(object):
+
     def __init__(self, a, b):
         self.a = a
         self.b = b
@@ -982,6 +1006,7 @@ def input_pre_per_interact():
     inputs = [ ]
     default_input_value = None
 
+
 def input_post_per_interact():
 
     global current_input_value
@@ -1008,7 +1033,7 @@ def input_post_per_interact():
             i.caret_pos = len(content)
 
 
-class Input(renpy.text.text.Text): #@UndefinedVariable
+class Input(renpy.text.text.Text):  # @UndefinedVariable
     """
     This is a Displayable that takes text as input.
     """
@@ -1083,7 +1108,6 @@ class Input(renpy.text.text.Text): #@UndefinedVariable
 
         self.update_text(self.content, self.editable)
 
-
     def _show(self):
         if self.default != self.content:
             self.content = self.default
@@ -1138,7 +1162,7 @@ class Input(renpy.text.text.Text): #@UndefinedVariable
             if editable:
                 l = len(content)
                 self.set_text([self.prefix, content[0:self.caret_pos].replace("{", "{{"), edit_text, caret,
-                                            content[self.caret_pos:l].replace("{", "{{"), self.suffix])
+                               content[self.caret_pos:l].replace("{", "{{"), self.suffix])
             else:
                 self.set_text([self.prefix, content.replace("{", "{{"), self.suffix ])
 
@@ -1307,6 +1331,8 @@ adj_registered = { }
 
 # This class contains information about an adjustment that can change the
 # position of content.
+
+
 class Adjustment(renpy.object.Object):
     """
     :doc: ui
@@ -1320,7 +1346,7 @@ class Adjustment(renpy.object.Object):
 
     """
 
-    def __init__(self, range=1, value=0, step=None, page=0, changed=None, adjustable=None, ranged=None): #@ReservedAssignment
+    def __init__(self, range=1, value=0, step=None, page=0, changed=None, adjustable=None, ranged=None):  # @ReservedAssignment
         """
         The following parameters correspond to fields or properties on
         the adjustment object:
@@ -1369,7 +1395,6 @@ class Adjustment(renpy.object.Object):
             any bars and viewports that use the adjustment.
          """
 
-
         super(Adjustment, self).__init__()
 
         if adjustable is None:
@@ -1403,7 +1428,7 @@ class Adjustment(renpy.object.Object):
         if self.ranged:
             self.ranged(self)
 
-    range = property(get_range, set_range) #@ReservedAssignment
+    range = property(get_range, set_range)  # @ReservedAssignment
 
     def get_page(self):
         if self._page is not None:
@@ -1453,6 +1478,7 @@ class Adjustment(renpy.object.Object):
 
         return None
 
+
 class Bar(renpy.display.core.Displayable):
     """
     Implements a bar that can display an integer value, and respond
@@ -1464,17 +1490,17 @@ class Bar(renpy.display.core.Displayable):
     def after_upgrade(self, version):
 
         if version < 1:
-            self.adjustment = Adjustment(self.range, self.value, changed=self.changed) # E1101
+            self.adjustment = Adjustment(self.range, self.value, changed=self.changed)  # E1101
             self.adjustment.register(self)
-            del self.range # E1101
-            del self.value # E1101
-            del self.changed # E1101
+            del self.range  # E1101
+            del self.value  # E1101
+            del self.changed  # E1101
 
         if version < 2:
             self.value = None
 
     def __init__(self,
-                 range=None, #@ReservedAssignment
+                 range=None,  # @ReservedAssignment
                  value=None,
                  width=None,
                  height=None,
@@ -1572,7 +1598,7 @@ class Bar(renpy.display.core.Displayable):
         # Store the width and height for the event function to use.
         self.width = width
         self.height = height
-        range = self.adjustment.range #@ReservedAssignment
+        range = self.adjustment.range  # @ReservedAssignment
         value = self.adjustment.value
         page = self.adjustment.page
 
@@ -1677,7 +1703,6 @@ class Bar(renpy.display.core.Displayable):
 
         return rv
 
-
     def focus(self, default=False):
         super(Bar, self).focus(default)
         self.set_transform_event("hover")
@@ -1685,7 +1710,6 @@ class Bar(renpy.display.core.Displayable):
         if not default:
             run(self.hovered)
 
-
     def unfocus(self, default=False):
         super(Bar, self).unfocus()
         self.set_transform_event("idle")
@@ -1705,7 +1729,7 @@ class Bar(renpy.display.core.Displayable):
         if self.hidden:
             return None
 
-        range = self.adjustment.range #@ReservedAssignment
+        range = self.adjustment.range  # @ReservedAssignment
         old_value = self.adjustment.value
         value = old_value
 
@@ -1860,6 +1884,7 @@ class TimerState(renpy.python.RevertableObject):
     started = False
     next_event = None
 
+
 class Timer(renpy.display.layout.Null):
 
     __version__ = 1
@@ -1903,7 +1928,6 @@ class Timer(renpy.display.layout.Null):
         else:
             self.state = TimerState()
 
-
     def event(self, ev, x, y, st):
 
         state = self.state
@@ -1985,13 +2009,13 @@ class MouseArea(renpy.display.core.Displayable):
             run_unhovered(self.hovered)
             run(self.unhovered)
 
+
 class OnEvent(renpy.display.core.Displayable):
     """
     This is a displayable that runs an action in response to a transform
     event. It's used to implement the screen language on statement.
     """
 
-
     def __init__(self, event, action=[ ]):
         """
         `event`
diff --git a/renpy/display/controller.py b/renpy/display/controller.py
index 326f329..78d6694 100644
--- a/renpy/display/controller.py
+++ b/renpy/display/controller.py
@@ -30,6 +30,7 @@ import pygame_sdl2 as pygame
 
 import os
 
+
 def load_mappings():
 
     try:
@@ -53,6 +54,7 @@ def load_mappings():
     except:
         pass
 
+
 def init():
     """
     Initialize gamepad support.
@@ -89,6 +91,7 @@ THRESHOLD = (32768 // 2)
 # Should we ignore events?
 ignore = False
 
+
 def make_event(name):
     """
     Creates an EVENTNAME event with `name`, and returns it.
@@ -122,7 +125,8 @@ def exists():
     else:
         return False
 
-def quit(index): # @ReservedAssignment
+
+def quit(index):  # @ReservedAssignment
     """
     Quits the controller at index.
     """
@@ -145,6 +149,7 @@ def start(index):
 
     renpy.exports.restart_interaction()
 
+
 def event(ev):
     """
     Processes an event and returns the same event, a new event, or None if
@@ -166,7 +171,7 @@ def event(ev):
         elif ev.value < -THRESHOLD:
             pos = "neg"
         else:
-            pos = None
+            pos = "zero"
 
         old_pos = axis_positions.get((ev.which, ev.axis), None)
 
@@ -175,9 +180,6 @@ def event(ev):
 
         axis_positions[(ev.which, ev.axis)] = pos
 
-        if pos is None:
-            return None
-
         name = "pad_{}_{}".format(get_string_for_axis(ev.axis), pos)
         ev = make_event(name)
 
@@ -192,14 +194,14 @@ def event(ev):
         ev = make_event(name)
 
     elif ev.type in (
-        pygame.JOYAXISMOTION,
-        pygame.JOYHATMOTION,
-        pygame.JOYBALLMOTION,
-        pygame.JOYBUTTONDOWN,
-        pygame.JOYBUTTONUP,
-        pygame.JOYDEVICEADDED,
-        pygame.JOYDEVICEREMOVED,
-        ):
+            pygame.JOYAXISMOTION,
+            pygame.JOYHATMOTION,
+            pygame.JOYBALLMOTION,
+            pygame.JOYBUTTONDOWN,
+            pygame.JOYBUTTONUP,
+            pygame.JOYDEVICEADDED,
+            pygame.JOYDEVICEREMOVED,
+            ):
 
         if not renpy.config.pass_joystick_events:
             return None
diff --git a/renpy/display/core.py b/renpy/display/core.py
index 5c27e70..f455f4a 100644
--- a/renpy/display/core.py
+++ b/renpy/display/core.py
@@ -22,6 +22,7 @@
 # This file contains code for initializing and managing the display
 # window.
 
+from __future__ import print_function
 import renpy.display
 import renpy.audio
 import renpy.text
@@ -39,17 +40,17 @@ import copy
 import_time = time.time()
 
 try:
-    import android # @UnresolvedImport
+    import android  # @UnresolvedImport
 except:
     android = None
 
 TIMEEVENT = pygame.event.register("TIMEEVENT")
-PERIODIC =  pygame.event.register("PERIODIC")
+PERIODIC = pygame.event.register("PERIODIC")
 REDRAW = pygame.event.register("REDRAW")
 EVENTNAME = pygame.event.register("EVENTNAME")
 
 # All events except for TIMEEVENT and REDRAW
-ALL_EVENTS = set(pygame.event.get_standard_events()) # @UndefinedVariable
+ALL_EVENTS = set(pygame.event.get_standard_events())  # @UndefinedVariable
 ALL_EVENTS.add(PERIODIC)
 ALL_EVENTS.add(EVENTNAME)
 
@@ -106,6 +107,7 @@ PERIODIC_INTERVAL = 50
 time_base = 0.0
 time_mult = 1.0
 
+
 def init_time():
     warp = os.environ.get("RENPY_TIMEWARP", "1.0")
 
@@ -115,10 +117,12 @@ def init_time():
     time_base = time.time()
     time_mult = float(warp)
 
+
 def get_time():
     t = time.time()
     return time_base + (t - time_base) * time_mult
 
+
 def displayable_by_tag(layer, tag):
     """
     Get the displayable on the given layer with the given tag.
@@ -126,6 +130,7 @@ def displayable_by_tag(layer, tag):
 
     return renpy.game.context().scene_lists.get_displayable_by_tag(layer, tag)
 
+
 class IgnoreEvent(Exception):
     """
     Exception that is raised when we want to ignore an event, but
@@ -134,6 +139,7 @@ class IgnoreEvent(Exception):
 
     pass
 
+
 class EndInteraction(Exception):
     """
     Exception that can be raised (for example, during the render method of
@@ -143,6 +149,7 @@ class EndInteraction(Exception):
     def __init__(self, value):
         self.value = value
 
+
 class absolute(float):
     """
     This represents an absolute float coordinate.
@@ -199,6 +206,7 @@ def place(width, height, sw, sh, placement):
 
     return x, y
 
+
 class DisplayableArguments(renpy.object.Object):
     """
     Represents a set of arguments that can be passed to a duplicated
@@ -287,8 +295,11 @@ class Displayable(renpy.object.Object):
     # duplicate method), or one of its children is.
     _duplicatable = False
 
+    # Does this displayable require clipping?
+    _clipping = False
+
     def __init__(self, focus=None, default=False, style='default', _args=None, **properties):
-        self.style = renpy.style.Style(style, properties) # @UndefinedVariable
+        self.style = renpy.style.Style(style, properties)  # @UndefinedVariable
         self.focus_name = focus
         self.default = default
 
@@ -324,6 +335,14 @@ class Displayable(renpy.object.Object):
 
         return self
 
+    def _in_current_store(self):
+        """
+        Returns a version of this displayable that will not change as it is
+        rendered.
+        """
+
+        return self
+
     def parameterize(self, name, parameters):
         """
         Obsolete alias for _duplicate.
@@ -374,7 +393,6 @@ class Displayable(renpy.object.Object):
 
             i.find_focusable(callback, focus_name)
 
-
     def focus(self, default=False):
         """
         Called to indicate that this widget has the focus.
@@ -587,23 +605,20 @@ class Displayable(renpy.object.Object):
 
         return
 
-    def _in_old_scene(self):
-        """
-        Returns a version of this displayable that will not change as it is
-        rendered.
-        """
-
-        return self
-
     def _tts_common(self, default_alt=None):
 
         rv = [ ]
 
         for i in self.visit():
             if i is not None:
-                rv.append(i._tts())
+                speech = i._tts()
+
+                if speech.strip():
+                    rv.append(speech)
 
-        rv = " ".join(rv)
+        rv = ": ".join(rv)
+        rv = rv.replace("::", ":")
+        rv = rv.replace(": :", ":")
 
         alt = self.style.alt
 
@@ -624,7 +639,6 @@ class Displayable(renpy.object.Object):
 
         return self._tts_common()
 
-
     def _tts_all(self):
         """
         Returns the self-voicing text of this displayable and all of its
@@ -835,7 +849,6 @@ class SceneLists(renpy.object.Object):
         new_transform.take_state(old_transform)
         return new_thing
 
-
     def find_index(self, layer, tag, zorder, behind):
         """
         This finds the spot in the named layer where we should insert the
@@ -876,7 +889,6 @@ class SceneLists(renpy.object.Object):
 
         return add_index, remove_index, zorder
 
-
     def add(self,
             layer,
             thing,
@@ -955,9 +967,9 @@ class SceneLists(renpy.object.Object):
                 st = sle.show_time
 
             if (not atl and
-                not at_list and
-                renpy.config.keep_running_transform and
-                isinstance(old, renpy.display.motion.Transform)):
+                    not at_list and
+                    renpy.config.keep_running_transform and
+                    isinstance(old, renpy.display.motion.Transform)):
 
                 thing = sle.displayable._change_transform_child(thing)
             else:
@@ -1089,7 +1101,7 @@ class SceneLists(renpy.object.Object):
         totally wiped out.
         """
 
-        if not layer in self.layers:
+        if layer not in self.layers:
             return
 
         if not hide:
@@ -1115,7 +1127,7 @@ class SceneLists(renpy.object.Object):
         time with the given time.
         """
 
-        for l, (t, list) in self.layer_at_list.items(): #@ReservedAssignment
+        for l, (t, list) in self.layer_at_list.items():  # @ReservedAssignment
             self.layer_at_list[l] = (t or time, list)
 
         for l, ll in self.layers.iteritems():
@@ -1140,6 +1152,7 @@ class SceneLists(renpy.object.Object):
         rv = renpy.display.layout.MultiBox(layout='fixed', focus=layer, **properties)
         rv.append_scene_list(self.layers[layer])
         rv.layer_name = layer
+        rv._duplicatable = False
 
         time, at_list = self.layer_at_list[layer]
 
@@ -1158,7 +1171,6 @@ class SceneLists(renpy.object.Object):
 
             rv = f
 
-
         return rv
 
     def remove_hide_replaced(self, layer, tag):
@@ -1320,6 +1332,7 @@ class MouseMove(object):
         renpy.display.draw.set_mouse_pos(x, y)
         return True
 
+
 def get_safe_mode():
     """
     Returns true if we should go into safe mode.
@@ -1464,21 +1477,20 @@ class Interface(object):
             if layer in renpy.config.layer_clipping:
                 x, y, w, h = renpy.config.layer_clipping[layer]
                 self.layer_properties[layer] = dict(
-                    xpos = x,
-                    xanchor = 0,
-                    ypos = y,
-                    yanchor = 0,
-                    xmaximum = w,
-                    ymaximum = h,
-                    xminimum = w,
-                    yminimum = h,
-                    clipping = True,
+                    xpos=x,
+                    xanchor=0,
+                    ypos=y,
+                    yanchor=0,
+                    xmaximum=w,
+                    ymaximum=h,
+                    xminimum=w,
+                    yminimum=h,
+                    clipping=True,
                     )
 
             else:
                 self.layer_properties[layer] = dict()
 
-
         # A stack giving the values of self.transition and self.transition_time
         # for contexts outside the current one. This is used to restore those
         # in the case where nothing has changed in the new context.
@@ -1580,7 +1592,6 @@ class Interface(object):
         # True if this is the first interact.
         self.start_interact = True
 
-
     def setup_dpi_scaling(self):
 
         if "RENPY_HIGHDPI" in os.environ:
@@ -1623,8 +1634,6 @@ class Interface(object):
             renpy.display.log.exception()
             return 1.0
 
-
-
     def start(self):
         """
         Starts the interface, by opening a window and setting the mode.
@@ -1659,7 +1668,7 @@ class Interface(object):
         renpy.display.log.write(s)
 
         if renpy.android and not renpy.config.log_to_stdout:
-            print s
+            print(s)
 
     def post_init(self):
         """
@@ -1668,7 +1677,7 @@ class Interface(object):
 
         # Needed for Unity.
         wmclass = renpy.config.save_directory or os.path.basename(sys.argv[0])
-        os.environ['SDL_VIDEO_X11_WMCLASS'] = wmclass
+        os.environ[b'SDL_VIDEO_X11_WMCLASS'] = wmclass.encode("utf-8")
 
         self.set_window_caption(force=True)
         self.set_icon()
@@ -1691,8 +1700,6 @@ class Interface(object):
 
             pygame.event.set_blocked(i)
 
-
-
     def set_icon(self):
         """
         This is called to set up the window icon.
@@ -1717,7 +1724,6 @@ class Interface(object):
 
             pygame.display.set_icon(im)
 
-
     def set_window_caption(self, force=False):
 
         window_title = renpy.config.window_title
@@ -1800,7 +1806,6 @@ class Interface(object):
 
         return rv
 
-
     def kill_textures(self):
         renpy.display.render.free_memory()
         renpy.text.text.layout_cache_clear()
@@ -1826,8 +1831,8 @@ class Interface(object):
 
         if self.display_reset:
 
-            pygame.key.stop_text_input() # @UndefinedVariable
-            pygame.key.set_text_input_rect(None) # @UndefinedVariable
+            pygame.key.stop_text_input()  # @UndefinedVariable
+            pygame.key.set_text_input_rect(None)  # @UndefinedVariable
             self.text_rect = None
 
             renpy.display.draw.deinit()
@@ -1853,7 +1858,7 @@ class Interface(object):
         virtual_size = (renpy.config.screen_width, renpy.config.screen_height)
 
         if physical_size is None:
-            if renpy.mobile or renpy.game.preferences.physical_size is None: #@UndefinedVariable
+            if renpy.mobile or renpy.game.preferences.physical_size is None:  # @UndefinedVariable
                 physical_size = (None, None)
             else:
                 physical_size = renpy.game.preferences.physical_size
@@ -1964,7 +1969,6 @@ class Interface(object):
         self.screenshot = sio.getvalue()
         sio.close()
 
-
     def check_background_screenshot(self):
         """
         Handles requests for a background screenshot.
@@ -2034,7 +2038,7 @@ class Interface(object):
 
         if renpy.config.empty_window:
 
-            old_history = renpy.store._history # @UndefinedVariable
+            old_history = renpy.store._history  # @UndefinedVariable
             renpy.store._history = False
 
             try:
@@ -2086,7 +2090,6 @@ class Interface(object):
         scene_lists.replace_transient()
         scene_lists.shown_window = False
 
-
     def set_transition(self, transition, layer=None, force=False):
         """
         Sets the transition that will be performed as part of the next
@@ -2101,7 +2104,6 @@ class Interface(object):
         else:
             self.transition[layer] = transition
 
-
     def event_peek(self):
         """
         This peeks the next event. It returns None if no event exists.
@@ -2137,7 +2139,6 @@ class Interface(object):
 
         return rv
 
-
     def event_wait(self):
         """
         This is in its own function so that we can track in the
@@ -2174,7 +2175,6 @@ class Interface(object):
 
         renpy.ui.close()
 
-
     def compute_scene(self, scene_lists):
         """
         This converts scene lists into a dictionary mapping layer
@@ -2196,7 +2196,6 @@ class Interface(object):
 
         return rv
 
-
     def quit_event(self):
         """
         This is called to handle the user invoking a quit.
@@ -2224,7 +2223,6 @@ class Interface(object):
         else:
             raise renpy.game.QuitException()
 
-
     def get_mouse_info(self):
         # Figure out if the mouse visibility algorithm is hiding the mouse.
         if (renpy.config.mouse_hide_time is not None) and (self.mouse_event_time + renpy.config.mouse_hide_time < renpy.display.core.get_time()):
@@ -2312,7 +2310,7 @@ class Interface(object):
 
         renpy.exports.free_memory()
 
-        print "Entered background."
+        print("Entered background.")
 
         while True:
             ev = pygame.event.wait()
@@ -2323,7 +2321,7 @@ class Interface(object):
             if ev.type == pygame.APP_TERMINATING:
                 sys.exit(0)
 
-        print "Entering foreground."
+        print("Entering foreground.")
 
         # Since we came back to life, we can get rid of the
         # auto-reload.
@@ -2354,7 +2352,6 @@ class Interface(object):
 
         renpy.display.log.write("The window was minimized.")
 
-
     def restored(self):
         """
         Called when we are restored from being an icon.
@@ -2402,7 +2399,6 @@ class Interface(object):
         self.ignore_touch = True
         renpy.display.focus.mouse_handler(None, -1, -1, default=False)
 
-
     def text_event_in_queue(self):
         """
         Returns true if the next event in the queue is a text editing event.
@@ -2419,15 +2415,15 @@ class Interface(object):
         Updates the text input state and text rectangle.
         """
 
-        if renpy.store._text_rect is not None: # @UndefinedVariable
-            self.text_rect = renpy.store._text_rect # @UndefinedVariable
+        if renpy.store._text_rect is not None:  # @UndefinedVariable
+            self.text_rect = renpy.store._text_rect  # @UndefinedVariable
 
         if self.text_rect is not None:
 
-            not_shown = pygame.key.has_screen_keyboard_support() and not pygame.key.is_screen_keyboard_shown() # @UndefinedVariable
+            not_shown = pygame.key.has_screen_keyboard_support() and not pygame.key.is_screen_keyboard_shown()  # @UndefinedVariable
 
             if not self.old_text_rect or not_shown:
-                pygame.key.start_text_input() # @UndefinedVariable
+                pygame.key.start_text_input()  # @UndefinedVariable
 
             if self.old_text_rect != self.text_rect:
                 x, y, w, h = self.text_rect
@@ -2435,16 +2431,15 @@ class Interface(object):
                 x1, y1 = renpy.display.draw.untranslate_point(x + w, y + h)
                 rect = (x0, y0, x1 - x0, y1 - y0)
 
-                pygame.key.set_text_input_rect(rect) # @UndefinedVariable
+                pygame.key.set_text_input_rect(rect)  # @UndefinedVariable
 
         else:
             if self.old_text_rect:
-                pygame.key.stop_text_input() # @UndefinedVariable
-                pygame.key.set_text_input_rect(None) # @UndefinedVariable
+                pygame.key.stop_text_input()  # @UndefinedVariable
+                pygame.key.set_text_input_rect(None)  # @UndefinedVariable
 
         self.old_text_rect = self.text_rect
 
-
     def maximum_framerate(self, t):
         """
         Forces Ren'Py to draw the screen at the maximum framerate for `t` seconds.
@@ -2455,7 +2450,7 @@ class Interface(object):
         else:
             self.maximum_framerate_time = max(self.maximum_framerate_time, get_time() + t)
 
-    def interact(self, clear=True, suppress_window=False, **kwargs):
+    def interact(self, clear=True, suppress_window=False, trans_pause=False, **kwargs):
         """
         This handles an interaction, restarting it if necessary. All of the
         keyword arguments are passed off to interact_core.
@@ -2464,6 +2459,8 @@ class Interface(object):
         if not self.started:
             self.start()
 
+        self.trans_pause = trans_pause
+
         # Cancel magic error reporting.
         renpy.bootstrap.report_error = None
 
@@ -2474,7 +2471,6 @@ class Interface(object):
 
         context.interacting = True
 
-
         # Show a missing window.
         if not suppress_window:
             self.show_window()
@@ -2493,7 +2489,7 @@ class Interface(object):
             self.start_interact = True
 
             while repeat:
-                repeat, rv = self.interact_core(preloads=preloads, **kwargs)
+                repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
                 self.start_interact = False
 
             return rv
@@ -2524,7 +2520,6 @@ class Interface(object):
                       preloads=[],
                       roll_forward=None,
                       ):
-
         """
         This handles one cycle of displaying an image to the user,
         and then responding to user input.
@@ -2566,7 +2561,7 @@ class Interface(object):
                 continue
 
             self.ongoing_transition[k] = self.transition[k]
-            self.transition_from[k] = self.old_scene[k]._in_old_scene()
+            self.transition_from[k] = self.old_scene[k]._in_current_store()
             self.transition_time[k] = None
 
         self.transition.clear()
@@ -2576,7 +2571,7 @@ class Interface(object):
             self.transition_from.clear()
             self.transition_time.clear()
 
-        ## Safety condition, prevents deadlocks.
+        # Safety condition, prevents deadlocks.
         if trans_pause:
             if not self.ongoing_transition:
                 return False, None
@@ -2678,7 +2673,7 @@ class Interface(object):
             focus_roots.append(scene_layer)
 
             if (self.ongoing_transition.get(layer, None) and
-                not suppress_transition):
+                    not suppress_transition):
 
                 trans = self.ongoing_transition[layer](
                     old_widget=self.transition_from[layer],
@@ -2702,7 +2697,7 @@ class Interface(object):
 
         # Add layers_root to root_widget, perhaps through a transition.
         if (self.ongoing_transition.get(None, None) and
-            not suppress_transition):
+                not suppress_transition):
 
             old_root = renpy.display.layout.MultiBox(layout='fixed')
             old_root.layers = { }
@@ -2845,7 +2840,7 @@ class Interface(object):
                     if not self.interact_time:
                         self.interact_time = self.frame_time
 
-                    renpy.audio.audio.advance_time() # Sets the time of all video frames.
+                    renpy.audio.audio.advance_time()  # Sets the time of all video frames.
 
                     self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn)
 
@@ -2862,25 +2857,25 @@ class Interface(object):
                         new_time = get_time()
 
                         if self.profile_once or (new_time - self.profile_time > .015):
-                            print "Profile: Redraw took %.3f ms." % (1000 * (new_time - self.frame_time))
-                            print "Profile: %.3f ms to complete event." % (1000 * (new_time - self.profile_time))
+                            print("Profile: Redraw took %.3f ms." % (1000 * (new_time - self.frame_time)))
+                            print("Profile: %.3f ms to complete event." % (1000 * (new_time - self.profile_time)))
 
                         self.profile_once = False
 
                     if first_pass and self.last_event and self.last_event.type in [ pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP, pygame.MOUSEMOTION ]:
 
-                            x, y = renpy.display.draw.get_mouse_pos()
-                            ev, x, y = renpy.display.emulator.emulator(self.last_event, x, y)
+                        x, y = renpy.display.draw.get_mouse_pos()
+                        ev, x, y = renpy.display.emulator.emulator(self.last_event, x, y)
 
-                            if self.ignore_touch:
-                                x = -1
-                                y = -1
+                        if self.ignore_touch:
+                            x = -1
+                            y = -1
 
-                            if renpy.android and self.last_event.type == pygame.MOUSEBUTTONUP:
-                                x = -1
-                                y = -1
+                        if renpy.android and self.last_event.type == pygame.MOUSEBUTTONUP:
+                            x = -1
+                            y = -1
 
-                            renpy.display.focus.mouse_handler(None, x, y, default=False)
+                        renpy.display.focus.mouse_handler(None, x, y, default=False)
 
                     needs_redraw = False
                     first_pass = False
@@ -3091,13 +3086,12 @@ class Interface(object):
                 # If we're ignoring touch events, and get a mouse up, stop
                 # ignoring those events.
                 if self.ignore_touch and \
-                    ev.type == pygame.MOUSEBUTTONUP and \
-                    ev.button == 1:
+                        ev.type == pygame.MOUSEBUTTONUP and \
+                        ev.button == 1:
 
                     self.ignore_touch = False
                     continue
 
-
                 # Merge mousemotion events.
                 if ev.type == pygame.MOUSEMOTION:
                     evs = pygame.event.get([pygame.MOUSEMOTION])
@@ -3163,7 +3157,7 @@ class Interface(object):
                 try:
 
                     if self.touch:
-                        renpy.display.gesture.recognizer.event(ev, x, y) # @UndefinedVariable
+                        renpy.display.gesture.recognizer.event(ev, x, y)  # @UndefinedVariable
 
                     # Handle the event normally.
                     rv = renpy.display.focus.mouse_handler(ev, x, y)
@@ -3186,7 +3180,6 @@ class Interface(object):
                             l = self.surftree.main_displayables_at_point(x, y, renpy.config.layers)
                             renpy.game.invoke_in_new_context(renpy.config.inspector, l)
 
-
                 except IgnoreEvent:
                     # An ignored event can change the timeout. So we want to
                     # process an TIMEEVENT to ensure that the timeout is
@@ -3195,7 +3188,6 @@ class Interface(object):
                     if ev.type != TIMEEVENT:
                         self.post_time_event()
 
-
                 # Check again after handling the event.
                 needs_redraw |= renpy.display.render.process_redraws()
 
diff --git a/renpy/display/dragdrop.py b/renpy/display/dragdrop.py
index 551ff6c..574db1d 100644
--- a/renpy/display/dragdrop.py
+++ b/renpy/display/dragdrop.py
@@ -29,6 +29,7 @@ from renpy.display.behavior import map_event, run, run_unhovered
 
 import pygame_sdl2 as pygame
 
+
 def default_drag_group():
     """
     Gets the default drag group. If it doesn't exist yet, creates it.
@@ -44,9 +45,11 @@ def default_drag_group():
 
     return rv
 
+
 def default_drag_joined(drag):
     return [ (drag, 0, 0) ]
 
+
 class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
     """
     :doc: drag_drop class
@@ -273,7 +276,6 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
         if d is not None:
             self.add(d)
 
-
     def snap(self, x, y, delay=0):
         """
         :doc: drag_drop method
@@ -425,7 +427,7 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
             # Snap starts now
             self.target_at = at + self.target_at_delay
             self.target_at_delay = 0
-            redraw(self,0)
+            redraw(self, 0)
         elif at >= self.target_at:
             # Snap complete
             self.x = self.target_x
@@ -634,7 +636,6 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
         if handled:
             raise renpy.display.core.IgnoreEvent()
 
-
     def get_placement(self):
 
         if self.x is not None:
@@ -685,7 +686,6 @@ class DragGroup(renpy.display.layout.MultiBox):
         for i in children:
             self.add(i)
 
-
     def add(self, child):
         """
         :doc: drag_drop method
@@ -706,14 +706,12 @@ class DragGroup(renpy.display.layout.MultiBox):
         Removes `child` from this DragGroup.
         """
 
-
         if not isinstance(child, Drag):
             raise Exception("Only drags can be removed from a drag group.")
 
         child.x = None
         super(DragGroup, self).remove(child)
 
-
     def event(self, ev, x, y, st):
 
         if not self.sensitive:
@@ -754,7 +752,6 @@ class DragGroup(renpy.display.layout.MultiBox):
         self.children = self._list_type(children)
         self.offsets = self._list_type(offsets)
 
-
     def get_best_drop(self, joined):
         """
         Returns the droppable that the members of joined overlap the most.
diff --git a/renpy/display/emulator.py b/renpy/display/emulator.py
index ee79bb7..6c02b89 100644
--- a/renpy/display/emulator.py
+++ b/renpy/display/emulator.py
@@ -36,6 +36,7 @@ overlay = [ ]
 # True if we're in ios mode, where we don't allow keys.
 ios = False
 
+
 def null_emulator(ev, x, y):
     """
     This is used when emulation is not desired.
@@ -82,6 +83,7 @@ def touch_emulator(ev, x, y):
 
 TV_KEYS = [ pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN, pygame.K_RETURN, pygame.K_ESCAPE, pygame.K_PAGEUP ]
 
+
 def tv_emulator(ev, x, y):
     """
     This emulates a tv-based device, like the OUYA.
@@ -105,6 +107,7 @@ def tv_emulator(ev, x, y):
 keyboard = None
 null = None
 
+
 def dynamic_keyboard(st, at):
     global keyboard
     global null
diff --git a/renpy/display/error.py b/renpy/display/error.py
index 1cce48a..5e9f824 100644
--- a/renpy/display/error.py
+++ b/renpy/display/error.py
@@ -29,6 +29,7 @@ error_handled = False
 ##############################################################################
 # Initialized approach.
 
+
 def call_exception_screen(screen_name, **kwargs):
     try:
 
@@ -44,14 +45,19 @@ def call_exception_screen(screen_name, **kwargs):
     finally:
         renpy.config.quit_action = old_quit
 
+
 def rollback_action():
     renpy.exports.rollback(force=True)
 
+
 def init_display():
     """
     The minimum amount of code required to init the display.
     """
 
+    if renpy.config.init_system_styles is not None:
+        renpy.config.init_system_styles()
+
     if not renpy.game.interface:
         renpy.display.core.Interface().start()
         renpy.loader.index_archives()
@@ -59,6 +65,7 @@ def init_display():
 
     renpy.ui.reset()
 
+
 def error_dump():
     """
     Handles dumps in the case where an error occurs.
@@ -66,6 +73,7 @@ def error_dump():
 
     renpy.dump.dump(True)
 
+
 def report_exception(short, full, traceback_fn):
     """
     Reports an exception to the user. Returns True if the exception should
@@ -78,7 +86,7 @@ def report_exception(short, full, traceback_fn):
 
     error_dump()
 
-    if renpy.game.args.command != "run": #@UndefinedVariable
+    if renpy.game.args.command != "run":  # @UndefinedVariable
         return True
 
     if "RENPY_SIMPLE_EXCEPTIONS" in os.environ:
@@ -148,7 +156,7 @@ def report_parse_errors(errors, error_fn):
 
     error_dump()
 
-    if renpy.game.args.command != "run": #@UndefinedVariable
+    if renpy.game.args.command != "run":  # @UndefinedVariable
         return True
 
     if "RENPY_SIMPLE_EXCEPTIONS" in os.environ:
@@ -168,7 +176,7 @@ def report_parse_errors(errors, error_fn):
             "_parse_errors",
             reload_action=reload_action,
             errors=errors,
-            error_fn = error_fn,
+            error_fn=error_fn,
             )
 
     except renpy.game.CONTROL_EXCEPTIONS:
diff --git a/renpy/display/focus.py b/renpy/display/focus.py
index 755ce90..a9b44e7 100644
--- a/renpy/display/focus.py
+++ b/renpy/display/focus.py
@@ -24,6 +24,7 @@
 import pygame_sdl2 as pygame
 import renpy.display
 
+
 class Focus(object):
 
     def __init__(self, widget, arg, x, y, w, h, screen):
@@ -79,6 +80,8 @@ focus_type = "mouse"
 pending_focus_type = "mouse"
 
 # Sets the currently focused widget.
+
+
 def set_focused(widget, arg, screen):
     global argument
     argument = arg
@@ -91,10 +94,14 @@ def set_focused(widget, arg, screen):
     renpy.display.tts.displayable(widget)
 
 # Gets the currently focused widget.
+
+
 def get_focused():
     return renpy.game.context().scene_lists.focused
 
 # Get the mouse cursor for the focused widget.
+
+
 def get_mouse():
     focused = get_focused()
     if focused is None:
@@ -102,12 +109,14 @@ def get_mouse():
     else:
         return focused.style.mouse
 
+
 def set_grab(widget):
     global grab
     grab = widget
 
     renpy.exports.cancel_gesture()
 
+
 def get_grab():
     return grab
 
@@ -115,6 +124,8 @@ def get_grab():
 focus_list = [ ]
 
 # This takes in a focus list from the rendering system.
+
+
 def take_focuses():
     global focus_list
     focus_list = [ ]
@@ -131,6 +142,7 @@ def take_focuses():
     if (default_focus is not None) and (get_focused() is None):
         change_focus(default_focus, True)
 
+
 def focus_coordinates():
     """
     :doc: other
@@ -152,13 +164,13 @@ def focus_coordinates():
 # A map from id(displayable) to the displayable that replaces it.
 replaced_by = { }
 
+
 def before_interact(roots):
     """
     Called before each interaction to choose the focused and grabbed
     displayables.
     """
 
-
     global new_grab
     global grab
 
@@ -251,6 +263,8 @@ def before_interact(roots):
 
 # This changes the focus to be the widget contained inside the new
 # focus object.
+
+
 def change_focus(newfocus, default=False):
     rv = None
 
@@ -294,6 +308,7 @@ def change_focus(newfocus, default=False):
 
     return rv
 
+
 def clear_focus():
     """
     Clears the focus when the window loses mouse focus.
@@ -302,6 +317,8 @@ def clear_focus():
     change_focus(None)
 
 # This handles mouse events, to see if they change the focus.
+
+
 def mouse_handler(ev, x, y, default=False):
     """
     Handle mouse events, to see if they change the focus.
@@ -318,7 +335,6 @@ def mouse_handler(ev, x, y, default=False):
         else:
             pending_focus_type = "mouse"
 
-
     new_focus = renpy.display.render.focus_at_point(x, y)
 
     if new_focus is None:
diff --git a/renpy/display/gesture.py b/renpy/display/gesture.py
index 66f54ab..17ab7cc 100644
--- a/renpy/display/gesture.py
+++ b/renpy/display/gesture.py
@@ -25,6 +25,7 @@ import renpy.display
 
 DIRECTIONS = [ "n", "ne", "e", "se", "s", "sw", "w", "nw" ]
 
+
 def dispatch_gesture(gesture):
     """
     This is called with a gesture to dispatch it as an event.
@@ -133,5 +134,4 @@ class GestureRecognizer(object):
                 return self.finish()
 
 
-
 recognizer = GestureRecognizer()
diff --git a/renpy/display/im.py b/renpy/display/im.py
index a46082c..8ede1fa 100644
--- a/renpy/display/im.py
+++ b/renpy/display/im.py
@@ -23,6 +23,7 @@
 # size-based caching and constructing images from operations (like
 # cropping and scaling).
 
+from __future__ import print_function
 import renpy.display
 
 import math
@@ -52,6 +53,8 @@ class CacheEntry(object):
         self.time = 0
 
 # This is the singleton image cache.
+
+
 class Cache(object):
 
     def __init__(self):
@@ -111,7 +114,6 @@ class Cache(object):
         # This is only updated when config.developer is True.
         self.load_log = [ ]
 
-
     def init(self):
         """
         Updates the cache object to make use of settings that might be provided
@@ -120,7 +122,7 @@ class Cache(object):
 
         self.cache_limit = renpy.config.image_cache_size * renpy.config.screen_width * renpy.config.screen_height
 
-    def quit(self): #@ReservedAssignment
+    def quit(self):  # @ReservedAssignment
         if not self.preload_thread.isAlive():
             return
 
@@ -132,7 +134,6 @@ class Cache(object):
 
         self.clear()
 
-
     # Clears out the cache.
     def clear(self):
 
@@ -170,7 +171,6 @@ class Cache(object):
     def end_tick(self):
         self.preloads = [ ]
 
-
     # This returns the pygame surface corresponding to the provided
     # image. It also takes care of updating the age of images in the
     # cache to be current, and maintaining the size of the current
@@ -222,7 +222,6 @@ class Cache(object):
                     else:
                         renpy.display.ic_log.write("Total Miss %r", ce.what)
 
-
         # Move it into the current generation. This isn't protected by
         # a lock, so in certain circumstances we could have an
         # inaccurate size - but that will be cured at the end of the
@@ -235,7 +234,6 @@ class Cache(object):
         # Done... return the surface.
         return ce.surf
 
-
     # This kills off a given cache entry.
     def kill(self, ce):
 
@@ -319,7 +317,6 @@ class Cache(object):
         if in_cache and renpy.config.debug_image_cache:
             renpy.display.ic_log.write("Kept %r", im)
 
-
     def start_prediction(self):
         """
         Called at the start of prediction, to ensure the thread runs
@@ -384,7 +381,6 @@ class Cache(object):
 
                         del self.pin_cache[i]
 
-
                 # For each image in the worklist...
                 for image in workset:
 
@@ -415,10 +411,10 @@ class Cache(object):
             self.load_log.pop()
 
 
-
 # The cache object.
 cache = Cache()
 
+
 def free_memory():
     """
     Frees some memory.
@@ -450,7 +446,6 @@ class ImageBase(renpy.display.core.Displayable):
         super(ImageBase, self).__init__(**properties)
         self.identity = (type(self).__name__, ) + args
 
-
     def __hash__(self):
         return hash(self.identity)
 
@@ -494,6 +489,7 @@ class ImageBase(renpy.display.core.Displayable):
 
         return [ ]
 
+
 class Image(ImageBase):
     """
     This image manipulator loads an image from a file.
@@ -513,7 +509,6 @@ class Image(ImageBase):
         else:
             return u"Image \u2026%s" % self.filename[-20:]
 
-
     def get_hash(self):
         return renpy.loader.get_hash(self.filename)
 
@@ -530,7 +525,7 @@ class Image(ImageBase):
 
             return surf
 
-        except Exception, e:
+        except Exception as e:
 
             if renpy.config.missing_image_callback:
                 im = renpy.config.missing_image_callback(self.filename)
@@ -553,6 +548,7 @@ class Image(ImageBase):
 
             return [ self.filename ]
 
+
 class ZipFileImage(ImageBase):
 
     def __init__(self, zipfilename, filename, mtime=0, **properties):
@@ -572,13 +568,10 @@ class ZipFileImage(ImageBase):
         except:
             return renpy.display.pgrender.surface((2, 2), True)
 
-
-
     def predict_files(self):
         return [ ]
 
 
-
 class Composite(ImageBase):
     """
     :doc: im_im
@@ -648,6 +641,7 @@ class Composite(ImageBase):
 
         return rv
 
+
 class Scale(ImageBase):
     """
     :doc: im_im
@@ -698,6 +692,7 @@ class Scale(ImageBase):
     def predict_files(self):
         return self.image.predict_files()
 
+
 class FactorScale(ImageBase):
     """
     :doc: im_im
@@ -714,7 +709,6 @@ class FactorScale(ImageBase):
         image logo doubled = im.FactorScale("logo.png", 1.5)
     """
 
-
     def __init__(self, im, width, height=None, bilinear=True, **properties):
 
         if height is None:
@@ -784,7 +778,6 @@ class Flip(ImageBase):
         self.horizontal = horizontal
         self.vertical = vertical
 
-
     def get_hash(self):
         return self.image.get_hash()
 
@@ -800,12 +793,10 @@ class Flip(ImageBase):
 
         return rv
 
-
     def predict_files(self):
         return self.image.predict_files()
 
 
-
 class Rotozoom(ImageBase):
     """
     This is an image manipulator that is a smooth rotation and zoom of another image manipulator.
@@ -848,7 +839,6 @@ class Rotozoom(ImageBase):
         return self.image.predict_files()
 
 
-
 class Crop(ImageBase):
     """
     :doc: im_im
@@ -914,6 +904,7 @@ def ramp(start, end):
 
 identity = ramp(0, 255)
 
+
 class Map(ImageBase):
     """
     This adjusts the colors of the image that is its child. It takes
@@ -954,6 +945,7 @@ class Map(ImageBase):
     def predict_files(self):
         return self.image.predict_files()
 
+
 class Twocolor(ImageBase):
     """
     This takes as arguments two colors, white and black. The image is
@@ -1036,6 +1028,7 @@ class Recolor(ImageBase):
     def predict_files(self):
         return self.image.predict_files()
 
+
 class MatrixColor(ImageBase):
     """
     :doc: im_matrixcolor
@@ -1097,6 +1090,7 @@ class MatrixColor(ImageBase):
     def predict_files(self):
         return self.image.predict_files()
 
+
 class matrix(tuple):
     """
     :doc: im_matrixcolor
@@ -1132,8 +1126,6 @@ class matrix(tuple):
         if not isinstance(a, matrix):
             a = matrix(a)
 
-
-
         if not isinstance(b, matrix):
 
             if isinstance(b, renpy.easy.Color):
@@ -1161,7 +1153,6 @@ class matrix(tuple):
                 o[0]*self[15] + o[1]*self[16] + o[2]*self[17] + o[3]*self[18] + self[19],
                 1)
 
-
     def __add__(self, other):
         if isinstance(other, (int, float)):
             other = float(other)
@@ -1198,7 +1189,6 @@ im.matrix(%f, %f, %f, %f, %f.
           %f, %f, %f, %f, %f,
           %f, %f, %f, %f, %f)""" % self
 
-
     @staticmethod
     def identity():
         """
@@ -1213,6 +1203,7 @@ im.matrix(%f, %f, %f, %f, %f.
                       0, 1, 0, 0, 0,
                       0, 0, 1, 0, 0,
                       0, 0, 0, 1, 0)
+
     @staticmethod
     def saturation(level, desat=(0.2126, 0.7152, 0.0722)):
         """
@@ -1358,11 +1349,11 @@ im.matrix(%f, %f, %f, %f, %f.
         lumG = 0.715
         lumB = 0.072
         return matrix(
-            lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0,
-            lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0,
-            lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0,
-            0,0,0,1,0,
-            0,0,0,0,1
+            lumR+cosVal*(1-lumR)+sinVal*(-lumR), lumG+cosVal*(-lumG)+sinVal*(-lumG), lumB+cosVal*(-lumB)+sinVal*(1-lumB), 0, 0,
+            lumR+cosVal*(-lumR)+sinVal*(0.143), lumG+cosVal*(1-lumG)+sinVal*(0.140), lumB+cosVal*(-lumB)+sinVal*(-0.283), 0, 0,
+            lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)), lumG+cosVal*(-lumG)+sinVal*(lumG), lumB+cosVal*(1-lumB)+sinVal*(lumB), 0, 0,
+            0, 0, 0, 1, 0,
+            0, 0, 0, 0, 1
             )
 
     @staticmethod
@@ -1399,7 +1390,6 @@ im.matrix(%f, %f, %f, %f, %f.
                       0, 0, 0, 1, 0)
 
 
-
 def Grayscale(im, desat=(0.2126, 0.7152, 0.0722), **properties):
     """
     :doc: im_im
@@ -1447,6 +1437,7 @@ def Alpha(image, alpha, **properties):
 
     return Recolor(image, 255, 255, 255, int(255 * alpha), force_alpha=True, **properties)
 
+
 class Tile(ImageBase):
     """
     :doc: im_im
@@ -1493,6 +1484,7 @@ class Tile(ImageBase):
     def predict_files(self):
         return self.image.predict_files()
 
+
 class AlphaMask(ImageBase):
     """
     :doc: im_im
@@ -1536,6 +1528,7 @@ class AlphaMask(ImageBase):
     def predict_files(self):
         return self.base.predict_files() + self.mask.predict_files()
 
+
 def image(arg, loose=False, **properties):
     """
     :doc: im_image
@@ -1597,6 +1590,7 @@ def load_image(im):
     surf = cache.get(image(im))
     return renpy.display.draw.load_texture(surf)
 
+
 def load_surface(im):
     """
     :doc: udd_utility
@@ -1608,7 +1602,7 @@ def load_surface(im):
 
 
 def reset_module():
-    print "Resetting cache."
+    print("Resetting cache.")
 
     global cache
     cache = Cache()
diff --git a/renpy/display/image.py b/renpy/display/image.py
index cc73500..1767cf0 100644
--- a/renpy/display/image.py
+++ b/renpy/display/image.py
@@ -47,6 +47,7 @@ def get_available_image_tags():
 
     return [ k for k, v in image_attributes.items() if v ]
 
+
 def get_available_image_attributes(tag, attributes=()):
     """
     :doc: image_func
@@ -135,7 +136,17 @@ class ImageReference(renpy.display.core.Displayable):
     """
 
     nosave = [ 'target' ]
+
     target = None
+    old_transform = None
+    param_target = None
+
+    __version__ = 1
+
+    def after_upgrade(self, version):
+        if version < 1:
+            if isinstance(self.param_target, renpy.display.transform.Transform):
+                self.old_transform = self.param_target
 
     def __init__(self, name, **properties):
         """
@@ -166,6 +177,7 @@ class ImageReference(renpy.display.core.Displayable):
         return True
 
     def _target(self):
+
         if self.target is None:
             self.find_target()
 
@@ -206,15 +218,28 @@ class ImageReference(renpy.display.core.Displayable):
         try:
 
             a = self._args.copy(name=name, args=args)
+
             self.target = target._duplicate(a)
 
-        except Exception, e:
+        except Exception as e:
 
             if renpy.config.debug:
                 raise
 
             error(str(e))
 
+        # Copy the old transform over.
+        new_transform = self.target._target()
+
+        if isinstance(new_transform, renpy.display.transform.Transform):
+            if self.old_transform is not None:
+                new_transform.take_state(self.old_transform)
+
+            self.old_transform = new_transform
+
+        else:
+            self.old_transform = None
+
         return True
 
     _duplicatable = True
@@ -230,6 +255,20 @@ class ImageReference(renpy.display.core.Displayable):
 
         return rv
 
+    def _in_current_store(self):
+
+        if self.target is None:
+            self.find_target()
+
+        target = self.target._in_current_store()
+
+        if target is self.target:
+            return self
+
+        rv = self._copy()
+        rv.target = target
+        return rv
+
     def _hide(self, st, at, kind):
         if self.target is None:
             self.find_target()
@@ -302,6 +341,9 @@ class DynamicImage(renpy.display.core.Displayable):
     # The raw target that the image resolves to, before it has been parameterized.
     raw_target = None
 
+    # Have we been locked, so we never change?
+    locked = False
+
     def __init__(self, name, scope=None, **properties):
         super(DynamicImage, self).__init__(**properties)
 
@@ -319,7 +361,6 @@ class DynamicImage(renpy.display.core.Displayable):
         if isinstance(name, list):
             self._duplicatable = True
 
-
     def _scope(self, scope, update):
         return self.find_target(scope, update)
 
@@ -349,6 +390,9 @@ class DynamicImage(renpy.display.core.Displayable):
 
     def find_target(self, scope=None, update=True):
 
+        if self.locked and (self.target is not None):
+            return
+
         if self._args.prefix is None:
             prefix = ""
         else:
@@ -357,7 +401,6 @@ class DynamicImage(renpy.display.core.Displayable):
         try:
             target = renpy.easy.dynamic_image(self.name, scope, prefix=prefix)
         except Exception as e:
-            raise
             raise Exception("In DynamicImage %r: %r" % (self.name, e))
 
         if target is None:
@@ -402,6 +445,12 @@ class DynamicImage(renpy.display.core.Displayable):
         rv.target = None
         return rv
 
+    def _in_current_store(self):
+        rv = self._copy()
+        rv.target = rv.target._in_current_store()
+        rv.locked = True
+        return rv
+
     def _hide(self, st, at, kind):
         if self.target is None:
             self.find_target()
@@ -480,7 +529,6 @@ class ShownImageInfo(renpy.object.Object):
             self.attributes = old.attributes.copy()
             self.shown = old.shown.copy()
 
-
     def after_upgrade(self, version):
         if version < 2:
 
@@ -601,7 +649,6 @@ class ShownImageInfo(renpy.object.Object):
         for i in remove:
             optional.discard(i)
 
-
         return self.choose_image(nametag, required, optional, name)
 
     def choose_image(self, tag, required, optional, exception_name):
@@ -663,4 +710,3 @@ Image = renpy.display.im.image
 Solid = renpy.display.imagelike.Solid
 Frame = renpy.display.imagelike.Frame
 ImageButton = renpy.display.behavior.ImageButton
-
diff --git a/renpy/display/imagelike.py b/renpy/display/imagelike.py
index d48a82c..8aee735 100644
--- a/renpy/display/imagelike.py
+++ b/renpy/display/imagelike.py
@@ -25,6 +25,7 @@ from renpy.display.render import render, Render, Matrix2D
 # This file contains displayables that are image-like, because they take
 # up a rectangular area of the screen, and do not respond to input.
 
+
 class Solid(renpy.display.core.Displayable):
     """
     :doc: disp_imagelike
@@ -83,6 +84,7 @@ class Solid(renpy.display.core.Displayable):
 
         return rv
 
+
 class Borders(object):
     """
     :doc: disp_imagelike
@@ -114,7 +116,6 @@ class Borders(object):
         four sides.
     """
 
-
     def __init__(self, left, top, right, bottom, pad_left=0, pad_top=0, pad_right=0, pad_bottom=0):
 
         self.left = left
@@ -136,6 +137,7 @@ class Borders(object):
             self.bottom + self.pad_bottom,
             )
 
+
 class Frame(renpy.display.core.Displayable):
     """
     :doc: disp_imagelike
@@ -397,8 +399,6 @@ class Frame(renpy.display.core.Displayable):
             if right:
                 draw(-right, 0, -bottom, 0)
 
-
-
     def sw_render(self, crend, dw, dh, left, top, right, bottom):
 
         source = crend.render_to_texture(True)
@@ -497,6 +497,16 @@ class Frame(renpy.display.core.Displayable):
         rv.image = image
         return rv
 
+    def _in_current_store(self):
+        image = self.image._in_current_store()
+
+        if image is self.image:
+            return self
+
+        rv = self._copy()
+        rv.image = image
+        return rv
+
     def visit(self):
         return [ ]
 
@@ -505,6 +515,7 @@ class Frame(renpy.display.core.Displayable):
         self.style._predict_frame(pd)
         pd(self.image)
 
+
 class FileCurrentScreenshot(renpy.display.core.Displayable):
     """
     :doc: file_action_function
@@ -526,7 +537,6 @@ class FileCurrentScreenshot(renpy.display.core.Displayable):
 
         self.empty = empty
 
-
     def render(self, width, height, st, at):
 
         ss = renpy.display.interface.screenshot_surface
@@ -541,4 +551,3 @@ class FileCurrentScreenshot(renpy.display.core.Displayable):
         rv.blit(tex, (0, 0))
 
         return rv
-
diff --git a/renpy/display/imagemap.py b/renpy/display/imagemap.py
index 5d90382..93be7e9 100644
--- a/renpy/display/imagemap.py
+++ b/renpy/display/imagemap.py
@@ -31,6 +31,7 @@ import hashlib
 # A list of cache images we've already written.
 cached = set()
 
+
 class ImageMapCrop(renpy.display.core.Displayable):
     """
     This handles the cropping of uncached imagemap components.
@@ -70,6 +71,7 @@ class ImageCacheCrop(renpy.display.core.Displayable):
     def render(self, width, height, st, at):
         return self.cache.render(self.index, width, height, st, at)
 
+
 class ImageMapCache(renpy.object.Object):
 
     def __init__(self, enable):
@@ -213,7 +215,6 @@ class ImageMapCache(renpy.object.Object):
         if renpy.loader.loadable(filename):
             self.cache = renpy.display.im.Image(filename)
 
-
     def render(self, index, width, height, st, at):
         if self.cache is None:
             d, rect = self.imagerect[index]
diff --git a/renpy/display/joystick.py b/renpy/display/joystick.py
index 9e0bdc5..9eefcda 100644
--- a/renpy/display/joystick.py
+++ b/renpy/display/joystick.py
@@ -28,6 +28,7 @@ import pygame_sdl2
 # Do we have a joystick enabled?
 enabled = False
 
+
 class JoyBehavior(renpy.display.layout.Null):
     """
     This is a behavior intended for joystick calibration. If a joystick
@@ -38,9 +39,11 @@ class JoyBehavior(renpy.display.layout.Null):
 
 joysticks = { }
 
+
 def count():
     return pygame_sdl2.joystick.get_count()
 
+
 def get(n):
 
     if n in joysticks:
@@ -51,4 +54,3 @@ def get(n):
         return joysticks[n]
     except:
         return None
-
diff --git a/renpy/display/layout.py b/renpy/display/layout.py
index 3ee73f9..4147c6c 100644
--- a/renpy/display/layout.py
+++ b/renpy/display/layout.py
@@ -37,6 +37,7 @@ def scale(num, base):
     else:
         return num
 
+
 class Null(renpy.display.core.Displayable):
     """
     :doc: disp_imagelike
@@ -121,6 +122,28 @@ class Container(renpy.display.core.Displayable):
 
         return rv
 
+    def _in_current_store(self):
+
+        children = [ ]
+
+        changed = False
+
+        for old in self.children:
+            new = old._in_current_store()
+            changed |= (old is not new)
+            children.append(new)
+
+        if not changed:
+            return self
+
+        rv = self._copy()
+        rv.children = children
+
+        if rv.children:
+            rv.child = rv.children[-1]
+
+        return rv
+
     def add(self, d):
         """
         Adds a child to this container.
@@ -155,7 +178,7 @@ class Container(renpy.display.core.Displayable):
         else:
             return
 
-        self.children.pop(i) # W0631
+        self.children.pop(i)  # W0631
         self.offsets = self._list_type()
 
         if self.children:
@@ -163,7 +186,6 @@ class Container(renpy.display.core.Displayable):
         else:
             self.child = None
 
-
     def update(self):
         """
         This should be called if a child is added to this
@@ -172,7 +194,6 @@ class Container(renpy.display.core.Displayable):
 
         renpy.display.render.invalidate(self)
 
-
     def render(self, width, height, st, at):
 
         rv = Render(width, height)
@@ -185,7 +206,6 @@ class Container(renpy.display.core.Displayable):
 
         return rv
 
-
     def event(self, ev, x, y, st):
 
         children = self.children
@@ -224,8 +244,6 @@ class Container(renpy.display.core.Displayable):
         return False
 
 
-
-
 def LiveComposite(size, *args, **properties):
     """
     :doc: disp_imagelike
@@ -265,6 +283,7 @@ def LiveComposite(size, *args, **properties):
 
     return rv
 
+
 class Position(Container):
     """
     Controls the placement of a displayable on the screen, using
@@ -445,6 +464,7 @@ class Grid(Container):
 
         return rv
 
+
 class IgnoreLayers(Exception):
     """
     Raise this to have the event ignored by layers, but reach the
@@ -453,6 +473,7 @@ class IgnoreLayers(Exception):
 
     pass
 
+
 class MultiBox(Container):
 
     layer_name = None
@@ -488,7 +509,7 @@ class MultiBox(Container):
         self.layers = None
         self.scene_list = None
 
-    def _in_old_scene(self):
+    def _in_current_store(self):
 
         if self.layer_name is not None:
 
@@ -502,7 +523,7 @@ class MultiBox(Container):
             for old_sle in self.scene_list:
                 new_sle = old_sle.copy()
 
-                d = new_sle.displayable._in_old_scene()
+                d = new_sle.displayable._in_current_store()
 
                 if d is not new_sle.displayable:
                     new_sle.displayable = d
@@ -525,7 +546,7 @@ class MultiBox(Container):
 
             for layer in renpy.config.layers:
                 old_d = self.layers[layer]
-                new_d = old_d._in_old_scene()
+                new_d = old_d._in_current_store()
 
                 if new_d is not old_d:
                     changed = True
@@ -537,7 +558,7 @@ class MultiBox(Container):
                 return self
 
         else:
-            return self
+            return super(MultiBox, self)._in_current_store()
 
         if self.offsets:
             rv.offsets = list(self.offsets)
@@ -563,7 +584,7 @@ class MultiBox(Container):
         else:
             return "MultiBox"
 
-    def add(self, widget, start_time=None, anim_time=None): # W0221
+    def add(self, widget, start_time=None, anim_time=None):  # W0221
         super(MultiBox, self).add(widget)
         self.start_times.append(start_time)
         self.anim_times.append(anim_time)
@@ -610,12 +631,11 @@ class MultiBox(Container):
             if layout is None:
                 layout = self.default_layout
 
-            self.layout = layout # W0201
+            self.layout = layout  # W0201
 
         else:
             layout = self.layout
 
-
         # Handle time adjustment, store the results in csts and cats.
         if adjust_times:
             t = renpy.game.interface.frame_time
@@ -638,28 +658,41 @@ class MultiBox(Container):
             else:
                 iterator = zip(self.children, csts, cats)
 
-
             rv = renpy.display.render.Render(width, height, layer_name=self.layer_name)
 
-            fit_first = self.style.fit_first
-
             xfit = self.style.xfit
             yfit = self.style.yfit
 
+            fit_first = self.style.fit_first
+
             if fit_first == "width":
-                xfit = True
+                first_fit_width = True
+                first_fit_height = False
             elif fit_first == "height":
-                yfit = True
+                first_fit_width = False
+                first_fit_height = True
             elif fit_first:
-                xfit = True
-                yfit = True
+                first_fit_width = True
+                first_fit_height = True
+            else:
+                first_fit_width = False
+                first_fit_height = False
 
             sizes = [ ]
 
             for child, cst, cat in iterator:
 
                 surf = render(child, width, height, cst, cat)
-                sizes.append(surf.get_size())
+                size = surf.get_size()
+                sizes.append(size)
+
+                if first_fit_width:
+                    width = rv.width = size[0]
+                    first_fit_width = False
+
+                if first_fit_height:
+                    height = rv.height = size[1]
+                    first_fit_height = False
 
                 if surf:
                     offset = child.place(rv, 0, 0, width, height, surf)
@@ -667,7 +700,6 @@ class MultiBox(Container):
                 else:
                     offsets.append((0, 0))
 
-
             if xfit:
                 width = 0
 
@@ -696,7 +728,6 @@ class MultiBox(Container):
                 if height > renpy.config.max_fit_size:
                     raise Exception("Fixed fit width ({}) is too large.".format(height))
 
-
             if self.style.order_reverse:
                 offsets.reverse()
 
@@ -707,7 +738,6 @@ class MultiBox(Container):
         # If we're here, we have a box, either horizontal or vertical. Which is good,
         # as we can share some code between boxes.
 
-
         spacing = self.style.spacing
         first_spacing = self.style.first_spacing
 
@@ -746,7 +776,6 @@ class MultiBox(Container):
         minx = 0
         miny = 0
 
-
         def layout_line(line, xfill, yfill):
             """
             Lays out a single line.
@@ -790,8 +819,6 @@ class MultiBox(Container):
         x = 0
         y = 0
 
-
-
         if layout == "horizontal":
 
             if yfill:
@@ -827,7 +854,6 @@ class MultiBox(Container):
                     remwidth = width
                     line = [ ]
 
-
                 line.append((d, x, y, surf))
                 line_height = max(line_height, sh)
                 x += sw + padding
@@ -835,7 +861,6 @@ class MultiBox(Container):
 
             maxx, maxy = layout_line(line, target_width - x, 0)
 
-
         elif layout == "vertical":
 
             if xfill:
@@ -908,7 +933,6 @@ class MultiBox(Container):
 
         return rv
 
-
     def event(self, ev, x, y, st):
 
         children_offsets = zip(self.children, self.offsets, self.start_times)
@@ -937,9 +961,11 @@ class MultiBox(Container):
 
         return None
 
+
 def Fixed(**properties):
     return MultiBox(layout='fixed', **properties)
 
+
 class SizeGroup(renpy.object.Object):
 
     def __init__(self):
@@ -973,6 +999,7 @@ class SizeGroup(renpy.object.Object):
 
 size_groups = dict()
 
+
 class Window(Container):
     """
     A window that has padding and margins, and can place a background
@@ -1095,7 +1122,7 @@ class Window(Container):
         if self.child:
             self.offsets = [ offsets ]
 
-        self.window_size = width, height # W0201
+        self.window_size = width, height  # W0201
 
         return rv
 
@@ -1104,6 +1131,7 @@ def dynamic_displayable_compat(st, at, expr):
     child = renpy.python.py_eval(expr)
     return child, None
 
+
 class DynamicDisplayable(renpy.display.core.Displayable):
     """
     :doc: disp_dynamic
@@ -1205,7 +1233,6 @@ class DynamicDisplayable(renpy.display.core.Displayable):
 
         return self.child.get_placement()
 
-
     def event(self, ev, x, y, st):
         if self.child:
             return self.child.event(ev, x, y, st)
@@ -1215,6 +1242,8 @@ cond_cache = { }
 
 # This chooses the first member of switch that's being shown on the
 # given layer.
+
+
 def condition_switch_pick(switch):
     for cond, d in switch:
 
@@ -1232,9 +1261,11 @@ def condition_switch_pick(switch):
 
     raise Exception("Switch could not choose a displayable.")
 
+
 def condition_switch_show(st, at, switch):
     return condition_switch_pick(switch), None
 
+
 def condition_switch_predict(switch):
 
     if renpy.game.lint:
@@ -1242,6 +1273,7 @@ def condition_switch_predict(switch):
 
     return [ condition_switch_pick(switch) ]
 
+
 def ConditionSwitch(*args, **kwargs):
     """
     :doc: disp_dynamic
@@ -1318,7 +1350,6 @@ def ShowingSwitch(*args, **kwargs):
 
     condargs = [ ]
 
-
     for name, d in zip(args[0::2], args[1::2]):
         if name is not None:
             if not isinstance(name, tuple):
@@ -1327,7 +1358,6 @@ def ShowingSwitch(*args, **kwargs):
         else:
             cond = None
 
-
         condargs.append(cond)
         condargs.append(d)
 
@@ -1368,6 +1398,7 @@ def LiveCrop(rect, child, **properties):
 
     return renpy.display.motion.Transform(child, crop=rect, **properties)
 
+
 class Side(Container):
 
     possible_positions = set([ 'tl', 't', 'tr', 'r', 'br', 'b', 'bl', 'l', 'c'])
@@ -1433,10 +1464,10 @@ class Side(Container):
                 else:
                     return 0, axis
 
-            self.left_space, width = spacer('tl', 'l', 'bl', width) # W0201
-            self.right_space, width = spacer('tr', 'r', 'br', width) # W0201
-            self.top_space, height = spacer('tl', 't', 'tr', height) # W0201
-            self.bottom_space, height = spacer('bl', 'b', 'br', height) # W0201
+            self.left_space, width = spacer('tl', 'l', 'bl', width)  # W0201
+            self.right_space, width = spacer('tr', 'r', 'br', width)  # W0201
+            self.top_space, height = spacer('tl', 't', 'tr', height)  # W0201
+            self.bottom_space, height = spacer('bl', 'b', 'br', height)  # W0201
 
             # The sizes of the various borders.
             left = 0
@@ -1466,13 +1497,13 @@ class Side(Container):
             right, top = sizeit('tr', right, top, right, top)
             right, bottom = sizeit('br', right, bottom, right, bottom)
 
-            self.cwidth = cwidth # W0201
-            self.cheight = cheight # W0201
+            self.cwidth = cwidth  # W0201
+            self.cheight = cheight  # W0201
 
-            self.top = top # W0201
-            self.bottom = bottom # W0201
-            self.left = left # W0201
-            self.right = right # W0201
+            self.top = top  # W0201
+            self.bottom = bottom  # W0201
+            self.left = left  # W0201
+            self.right = right  # W0201
 
         else:
             cwidth = self.cwidth
@@ -1494,7 +1525,6 @@ class Side(Container):
         tops = self.top_space
         bottoms = self.bottom_space
 
-
         if self.style.xfill:
             cwidth = width
 
@@ -1539,7 +1569,9 @@ class Side(Container):
 
         return rv
 
+
 class Alpha(renpy.display.core.Displayable):
+
     def __init__(self, start, end, time, child=None, repeat=False, bounce=False,
                  anim_timebase=False, time_warp=None, **properties):
 
@@ -1654,7 +1686,16 @@ class LiveTile(Container):
 
         for y in range(0, height, ch):
             for x in range(0, width, cw):
-                rv.blit(cr, (x, y), focus=False)
+
+                ccw = min(cw, width - x)
+                cch = min(ch, height - y)
+
+                if (ccw < cw) or (cch < ch):
+                    ccr = cr.subsurface((0, 0, ccw, cch))
+                else:
+                    ccr = cr
+
+                rv.blit(ccr, (x, y), focus=False)
 
         return rv
 
@@ -1753,11 +1794,3 @@ class AlphaMask(Container):
         rv.blit(cr, (0, 0))
 
         return rv
-
-
-
-
-
-
-
-
diff --git a/renpy/display/minigame.py b/renpy/display/minigame.py
index 8cf68bd..7d8c895 100644
--- a/renpy/display/minigame.py
+++ b/renpy/display/minigame.py
@@ -22,4 +22,3 @@
 
 def Minigame(*args, **kwargs):
     raise Exception("Minigame is no longer implemented.")
-
diff --git a/renpy/display/module.py b/renpy/display/module.py
index dd9f9f4..7172547 100644
--- a/renpy/display/module.py
+++ b/renpy/display/module.py
@@ -28,6 +28,7 @@ import _renpy
 
 import sys
 
+
 def convert_and_call(function, src, dst, *args):
     """
     This calls the function with the source and destination
@@ -93,6 +94,7 @@ else:
 
 bo_cache = None
 
+
 def byte_offset(src):
     """
     Given the surface src, returns a 4-tuple giving the byte offsets
@@ -107,6 +109,7 @@ def byte_offset(src):
 
     return bo_cache
 
+
 def endian_order(src, r, g, b, a):
 
     if bo_cache is None:
@@ -120,7 +123,6 @@ def endian_order(src, r, g, b, a):
     return rv
 
 
-
 def linmap(src, dst, rmap, gmap, bmap, amap):
     """
     This maps the colors between two surfaces. The various map
@@ -134,7 +136,8 @@ def linmap(src, dst, rmap, gmap, bmap, amap):
 
 save_png = _renpy.save_png
 
-def map(src, dst, rmap, gmap, bmap, amap): #@ReservedAssignment
+
+def map(src, dst, rmap, gmap, bmap, amap):  # @ReservedAssignment
     """
     This maps the colors between two surfaces. The various map
     parameters must be 256 character long strings, with the value
@@ -147,7 +150,6 @@ def map(src, dst, rmap, gmap, bmap, amap): #@ReservedAssignment
                      *endian_order(dst, rmap, gmap, bmap, amap))
 
 
-
 def twomap(src, dst, white, black):
     """
     Given colors for white and black, linearly maps things
@@ -228,6 +230,7 @@ transform = _renpy.transform
 # Note: Blend requires all surfaces to be the same size.
 blend = _renpy.blend
 
+
 def imageblend(a, b, dst, img, amap):
     alpha = byte_offset(img)[3]
     _renpy.imageblend(a, b, dst, img, alpha, amap)
diff --git a/renpy/display/motion.py b/renpy/display/motion.py
index 93b666a..51e6bc2 100644
--- a/renpy/display/motion.py
+++ b/renpy/display/motion.py
@@ -22,7 +22,7 @@
 # This file contains displayables that move, zoom, rotate, or otherwise
 # transform displayables. (As well as displayables that support them.)
 
-from renpy.display.transform import * # @UnusedWildImport
+from renpy.display.transform import *  # @UnusedWildImport
 
 import math
 
@@ -108,7 +108,6 @@ class Motion(Container):
 
         self.position = None
 
-
     def update_position(self, t, sizes):
 
         if renpy.game.less_updates:
@@ -260,6 +259,7 @@ def Pan(startpos, endpos, time, child=None, repeat=False, bounce=False,
                   time_warp=time_warp,
                   **properties)
 
+
 def Move(startpos, endpos, time, child=None, repeat=False, bounce=False,
          anim_timebase=False, style='motion', time_warp=None, **properties):
     """
@@ -314,7 +314,9 @@ class Revolver(object):
         self.pos = pos
         self.child = child
 
-    def __call__(self, t, (w, h, cw, ch)):
+    def __call__(self, t, rect):
+
+        (w, h, cw, ch) = rect
 
         # Converts a float to an integer in the given range, passes
         # integers through unchanged.
@@ -376,7 +378,6 @@ def Revolve(start, end, time, child, around=(0.5, 0.5), cor=(0.5, 0.5), pos=None
                   **properties)
 
 
-
 def zoom_render(crend, x, y, w, h, zw, zh, bilinear):
     """
     This creates a render that zooms its child.
@@ -392,7 +393,6 @@ def zoom_render(crend, x, y, w, h, zw, zh, bilinear):
     if zw == 0 or zh == 0 or w == 0 or h == 0:
         return rv
 
-
     rv.forward = renpy.display.render.Matrix2D(w / zw, 0, 0, h / zh)
     rv.reverse = renpy.display.render.Matrix2D(zw / w, 0, 0, zh / h)
 
@@ -404,6 +404,7 @@ def zoom_render(crend, x, y, w, h, zw, zh, bilinear):
 
 
 class ZoomCommon(renpy.display.core.Displayable):
+
     def __init__(self,
                  time, child,
                  end_identity=False,
@@ -453,7 +454,6 @@ class ZoomCommon(renpy.display.core.Displayable):
         self.opaque = opaque
         self.anim_timebase = anim_timebase
 
-
     def visit(self):
         return [ self.child, self.after_child ]
 
@@ -547,7 +547,6 @@ class FactorZoom(ZoomCommon):
         return 0, 0, width, height, factor * width, factor * height
 
 
-
 class SizeZoom(ZoomCommon):
 
     def __init__(self, start, end, time, child, **properties):
@@ -620,11 +619,9 @@ class RotoZoom(renpy.display.core.Displayable):
 
         self.opaque = opaque
 
-
     def visit(self):
         return [ self.child ]
 
-
     def render(self, width, height, st, at):
 
         if self.rot_anim_timebase:
@@ -674,7 +671,6 @@ class RotoZoom(renpy.display.core.Displayable):
         if self.zoom_time_warp:
             zoom_time = self.zoom_time_warp(zoom_time)
 
-
         angle = self.rot_start + (1.0 * self.rot_end - self.rot_start) * rot_time
         zoom = self.zoom_start + (1.0 * self.zoom_end - self.zoom_start) * zoom_time
         # angle = -angle * math.pi / 180
@@ -706,6 +702,6 @@ renpy.display.layout.Motion = Motion
 renpy.display.layout.Interpolate = Interpolate
 
 # Leave these functions around - they might have been pickled somewhere.
-renpy.display.layout.Revolve = Revolve # function
-renpy.display.layout.Move = Move # function
-renpy.display.layout.Pan = Pan # function
+renpy.display.layout.Revolve = Revolve  # function
+renpy.display.layout.Move = Move  # function
+renpy.display.layout.Pan = Pan  # function
diff --git a/renpy/display/movetransition.py b/renpy/display/movetransition.py
index 8ffa22d..cd586ae 100644
--- a/renpy/display/movetransition.py
+++ b/renpy/display/movetransition.py
@@ -27,6 +27,8 @@
 import renpy.display
 
 # Utility function used by MoveTransition et al.
+
+
 def position(d):
 
     xpos, ypos, xanchor, yanchor, _xoffset, _yoffset, _subpixel = d.get_placement()
@@ -42,6 +44,7 @@ def position(d):
 
     return xpos, ypos, xanchor, yanchor
 
+
 def offsets(d):
 
     _xpos, _ypos, _xanchor, _yanchor, xoffset, yoffset, _subpixel = d.get_placement()
@@ -59,13 +62,17 @@ def MoveFactory(pos1, pos2, delay, d, **kwargs):
 
     return renpy.display.motion.Move(pos1, pos2, delay, d, **kwargs)
 
+
 def default_enter_factory(pos, delay, d, **kwargs):
     return d
 
+
 def default_leave_factory(pos, delay, d, **kwargs):
     return None
 
 # These can be used to move things in and out of the screen.
+
+
 def MoveIn(pos, pos1, delay, d, **kwargs):
 
     def aorb(a, b):
@@ -76,6 +83,7 @@ def MoveIn(pos, pos1, delay, d, **kwargs):
     pos = tuple([aorb(a, b) for a, b in zip(pos, pos1)])
     return renpy.display.motion.Move(pos, pos1, delay, d, **kwargs)
 
+
 def MoveOut(pos, pos1, delay, d, **kwargs):
 
     def aorb(a, b):
@@ -86,6 +94,7 @@ def MoveOut(pos, pos1, delay, d, **kwargs):
     pos = tuple([aorb(a, b) for a, b in zip(pos, pos1)])
     return renpy.display.motion.Move(pos1, pos, delay, d, **kwargs)
 
+
 def ZoomInOut(start, end, pos, delay, d, **kwargs):
 
     xpos, ypos, xanchor, yanchor = pos
@@ -99,6 +108,7 @@ def ZoomInOut(start, end, pos, delay, d, **kwargs):
         return FactorZoom(start, end, delay, d, opaque=False,
                           xpos=xpos, ypos=ypos, xanchor=xanchor, yanchor=yanchor, **kwargs)
 
+
 def RevolveInOut(start, end, pos, delay, d, **kwargs):
     return renpy.display.motion.Revolve(start, end, delay, d, pos=pos, **kwargs)
 
@@ -166,7 +176,7 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
         # a move occured.
 
         if (not isinstance(new, renpy.display.layout.MultiBox)
-            or (new.layers is None and new.layer_name is None)):
+                or (new.layers is None and new.layer_name is None)):
 
             if use_old:
                 child = old
@@ -200,7 +210,7 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
 
                 if (isinstance(f, renpy.display.layout.MultiBox)
                     and layer in layers
-                    and f.scene_list is not None):
+                        and f.scene_list is not None):
 
                     f = merge_slide(old.layers[layer], new.layers[layer])
 
@@ -245,7 +255,6 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
             move = renpy.display.layout.IgnoresEvents(move)
             rv_sl.append(merge(old_sle, move))
 
-
         def moving(old_sle, new_sle):
             old_d = wrap(old_sle)
             new_d = wrap(new_sle)
@@ -261,13 +270,11 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
 
             rv_sl.append(merge(new_sle, move))
 
-
         # The old, new, and merged scene_lists.
         old_sl = old.scene_list[:]
         new_sl = new.scene_list[:]
         rv_sl = [ ]
 
-
         # A list of tags in old_sl, new_sl, and rv_sl.
         old_map = dict((tag(i), i) for i in old_sl if i is not None)
         new_tags = set(tag(i) for i in new_sl if i is not None)
@@ -294,7 +301,6 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
                     old_sl.pop(0)
                     continue
 
-
             # Otherwise, we must have something in new_sl. We want to
             # either move it or have it enter.
 
@@ -325,11 +331,10 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
 
         return rv
 
-
     # This calls merge_slide to actually do the merging.
 
     rv = merge_slide(old_widget, new_widget)
-    rv.delay = delay # W0201
+    rv.delay = delay  # W0201
 
     return rv
 
@@ -488,14 +493,13 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
         # a move occured.
 
         if (not isinstance(new, renpy.display.layout.MultiBox)
-            or (new.layers is None and new.layer_name is None)):
+                or (new.layers is None and new.layer_name is None)):
 
             if old is new:
                 return new
             else:
                 return MoveInterpolate(delay, old, new, use_old, time_warp)
 
-
         # If we're in the layers_root widget, merge the child widgets
         # for each layer.
         if new.layers:
@@ -508,7 +512,7 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
 
                 if (isinstance(f, renpy.display.layout.MultiBox)
                     and layer in layers
-                    and f.scene_list is not None):
+                        and f.scene_list is not None):
 
                     f = merge_slide(old.layers[layer], new.layers[layer])
 
@@ -552,7 +556,6 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
             move = renpy.display.layout.IgnoresEvents(move)
             rv_sl.append(merge(old_sle, move))
 
-
         def moving(old_sle, new_sle):
 
             if old_sle.displayable is new_sle.displayable:
@@ -566,7 +569,6 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
 
             rv_sl.append(merge(new_sle, move))
 
-
         # The old, new, and merged scene_lists.
         old_sl = old.scene_list[:]
         new_sl = new.scene_list[:]
@@ -598,7 +600,6 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
                     old_sl.pop(0)
                     continue
 
-
             # Otherwise, we must have something in new_sl. We want to
             # either move it or have it enter.
 
@@ -633,4 +634,3 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
     rv.delay = delay
 
     return rv
-
diff --git a/renpy/display/particle.py b/renpy/display/particle.py
index 11bd178..f3fe41d 100644
--- a/renpy/display/particle.py
+++ b/renpy/display/particle.py
@@ -47,6 +47,7 @@ class SpriteCache(renpy.object.Object):
     # If true, then the render is simple enough it can just be appended to
     # the manager's render's children list.
 
+
 class Sprite(renpy.object.Object):
     """
     :doc: sprites class
@@ -122,7 +123,6 @@ class Sprite(renpy.object.Object):
         self.events = False
 
 
-
 class SpriteManager(renpy.display.core.Displayable):
     """
     :doc: sprites class
@@ -227,7 +227,6 @@ class SpriteManager(renpy.display.core.Displayable):
             for i in self.predict_function():
                 renpy.display.predict.displayable(i)
 
-
     def redraw(self, delay=0):
         """
         :doc: sprites method
@@ -255,7 +254,7 @@ class SpriteManager(renpy.display.core.Displayable):
         if self.dead_child:
             self.children = [ i for i in self.children if i.live ]
 
-        self.children.sort(key=lambda sc:sc.zorder)
+        self.children.sort(key=lambda sc: sc.zorder)
 
         caches = [ ]
 
@@ -281,7 +280,6 @@ class SpriteManager(renpy.display.core.Displayable):
 
                 caches.append(cache)
 
-
             if cache.fast:
                 for child, xo, yo, _focus, _main in r.children:
                     rv.children.append((child,
@@ -415,6 +413,7 @@ class Particles(renpy.display.core.Displayable, renpy.python.NoRollback):
     def render(self, w, h, st, at):
         return renpy.display.render.render(self.sm, w, h, st, at)
 
+
 class SnowBlossomFactory(renpy.python.NoRollback):
 
     rotate = False
@@ -436,7 +435,7 @@ class SnowBlossomFactory(renpy.python.NoRollback):
         self.init()
 
     def init(self):
-        self.starts = [ random.uniform(0, self.start) for _i in xrange(0, self.count) ] # W0201
+        self.starts = [ random.uniform(0, self.start) for _i in xrange(0, self.count) ]  # W0201
         self.starts.append(self.start)
         self.starts.sort()
 
@@ -462,7 +461,6 @@ class SnowBlossomFactory(renpy.python.NoRollback):
                                               rotate=self.rotate))
             return rv
 
-
         if particles is None or len(particles) < self.count:
 
             # Check to see if we have a particle ready to start. If not,
@@ -499,7 +497,6 @@ class SnowBlossomParticle(renpy.python.NoRollback):
         self.offset = offset
         self.rotate = rotate
 
-
         if not rotate:
             sh = renpy.config.screen_height
             sw = renpy.config.screen_width
@@ -507,13 +504,11 @@ class SnowBlossomParticle(renpy.python.NoRollback):
             sw = renpy.config.screen_height
             sh = renpy.config.screen_width
 
-
         if self.yspeed > 0:
             self.ystart = -border
         else:
             self.ystart = sh + border
 
-
         travel_time = (2.0 * border + sh) / abs(yspeed)
 
         xdist = xspeed * travel_time
@@ -549,6 +544,7 @@ class SnowBlossomParticle(renpy.python.NoRollback):
         else:
             return int(ypos), int(xpos), to + self.offset, self.image
 
+
 def SnowBlossom(d,
                 count=10,
                 border=50,
@@ -557,7 +553,6 @@ def SnowBlossom(d,
                 start=0,
                 fast=False,
                 horizontal=False):
-
     """
     :doc: sprites_extra
 
@@ -606,4 +601,3 @@ def SnowBlossom(d,
                                         start=start,
                                         fast=fast,
                                         rotate=horizontal))
-
diff --git a/renpy/display/pgrender.py b/renpy/display/pgrender.py
index 5a7f3ec..8b5237a 100644
--- a/renpy/display/pgrender.py
+++ b/renpy/display/pgrender.py
@@ -33,6 +33,7 @@ import renpy.audio
 sample_alpha = None
 sample_noalpha = None
 
+
 def set_rgba_masks():
     """
     This rebuilds the sample surfaces, to ones that use the given
@@ -65,6 +66,7 @@ def set_rgba_masks():
 
     renpy.audio.audio.sample_surfaces(sample_noalpha, sample_alpha)
 
+
 class Surface(pygame.Surface):
     """
     This allows us to wrap around pygame's surface, to change
@@ -89,6 +91,7 @@ class Surface(pygame.Surface):
         rv = pygame.Surface.subsurface(self, rect)
         return rv
 
+
 def surface((width, height), alpha):
     """
     Constructs a new surface. The allocated surface is actually a subsurface
@@ -111,17 +114,18 @@ def surface((width, height), alpha):
         sample = pygame.Surface((4, 4), pygame.SRCALPHA, 32)
 
     surf = Surface((width + 4, height + 4), 0, sample)
-    return surf.subsurface((2, 2, width, height)) # E1101
+    return surf.subsurface((2, 2, width, height))  # E1101
 
 surface_unscaled = surface
 
+
 def copy_surface(surf, alpha=True):
     """
     Creates a copy of the surface.
     """
 
     rv = surface_unscaled(surf.get_size(), alpha)
-    renpy.display.accelerator.nogil_copy(surf, rv) # @UndefinedVariable
+    renpy.display.accelerator.nogil_copy(surf, rv)  # @UndefinedVariable
     return rv
 
 copy_surface_unscaled = copy_surface
@@ -130,11 +134,12 @@ copy_surface_unscaled = copy_surface
 # Wrapper around image loading.
 
 # Formats we can load reentrantly.
-safe_formats = { "png", "jpg", "jpeg" }
+safe_formats = { "png", "jpg", "jpeg", "webp" }
 
 # Lock used for loading unsafe formats.
 image_load_lock = threading.RLock()
 
+
 def load_image(f, filename):
     global count
 
diff --git a/renpy/display/predict.py b/renpy/display/predict.py
index 2ddafc1..290bc35 100644
--- a/renpy/display/predict.py
+++ b/renpy/display/predict.py
@@ -38,6 +38,7 @@ predicting = False
 # like to predict.
 screens = [ ]
 
+
 def displayable(d):
     """
     Called to predict that the displayable `d` will be shown.
@@ -50,6 +51,7 @@ def displayable(d):
         predicted.add(d)
         d.visit_all(lambda i : i.predict_one())
 
+
 def screen(_screen_name, *args, **kwargs):
     """
     Called to predict that the named screen is about to be shown
@@ -88,7 +90,6 @@ def prediction_coroutine(root_widget):
     # Start the prediction thread (to clean out the cache).
     renpy.display.im.cache.start_prediction()
 
-
     # Set up the image prediction method.
     global image
     image = renpy.display.im.cache.preload_image
@@ -103,7 +104,6 @@ def prediction_coroutine(root_widget):
         yield True
         predicting = True
 
-
     # Predict images that are going to be reached in the next few
     # clicks.
 
@@ -136,7 +136,6 @@ def prediction_coroutine(root_widget):
     while not (yield True):
         continue
 
-
     # Predict screens given with renpy.start_predict_screen.
     for name, value in renpy.store._predict_screen.items():
         args, kwargs = value
@@ -185,4 +184,3 @@ def prediction_coroutine(root_widget):
         predicting = False
 
     yield False
-
diff --git a/renpy/display/presplash.py b/renpy/display/presplash.py
index f40af1a..57e9ad2 100644
--- a/renpy/display/presplash.py
+++ b/renpy/display/presplash.py
@@ -42,6 +42,7 @@ start_time = time.time()
 
 PRESPLASHEVENT = pygame_sdl2.event.register("PRESPLASHEVENT")
 
+
 def run_event_thread():
     """
     Disposes of events while the window is running.
@@ -60,7 +61,6 @@ def start(basedir, gamedir):
     Called to display the presplash when necessary.
     """
 
-
     if "RENPY_LESS_UPDATES" in os.environ:
         return
 
@@ -79,7 +79,6 @@ def start(basedir, gamedir):
 
         ctypes.windll.user32.SetProcessDPIAware()
 
-
     pygame_sdl2.display.init()
 
     img = pygame_sdl2.image.load(fn, fn)
diff --git a/renpy/display/render.pyx b/renpy/display/render.pyx
index 6cf0a98..3d911c0 100644
--- a/renpy/display/render.pyx
+++ b/renpy/display/render.pyx
@@ -193,7 +193,7 @@ cpdef render(d, object widtho, object heighto, double st, double at):
 
     rv.render_of.append(d)
 
-    if style.clipping:
+    if d._clipping:
         rv = rv.subsurface((0, 0, rv.width, rv.height), focus=True)
         rv.render_of.append(d)
 
diff --git a/renpy/display/scale.py b/renpy/display/scale.py
index 6282683..154891c 100644
--- a/renpy/display/scale.py
+++ b/renpy/display/scale.py
@@ -32,38 +32,52 @@ import _renpy
 # The scaling API that's used if we don't enable scaling.
 
 # Gets the real pygame surface.
+
+
 def real(s):
     return s
 
 # Scales the number, n.
+
+
 def scale(n):
     return n
 
+
 def real_bilinear(src, size):
     rv = pgrender.surface_unscaled(size, src)
     renpy.display.module.bilinear_scale(src, rv)
     return rv
 
 # Does pygame.transform.scale.
+
+
 def real_transform_scale(surf, size):
     return pgrender.transform_scale_unscaled(surf, size)
 
 # Loads an image, without scaling it.
+
+
 def image_load_unscaled(f, hint, convert=True):
     rv = pgrender.load_image_unscaled(f, hint)
     return rv
 
 # Saves an image without rescaling.
+
+
 def image_save_unscaled(surf, filename):
     pygame.image.save(surf, renpy.exports.fsencode(filename))
 
 # Scales down a surface.
+
+
 def surface_scale(full):
     return full
 
 real_renpy_pixellate = _renpy.pixellate
 real_renpy_transform = _renpy.transform
 
+
 def real_smoothscale(src, size, dest=None):
     """
     This scales src up or down to size. This uses both the pixellate
@@ -106,4 +120,3 @@ def real_smoothscale(src, size, dest=None):
     return dest
 
 smoothscale = real_smoothscale
-
diff --git a/renpy/display/screen.py b/renpy/display/screen.py
index 26a76fe..d4a9b9f 100644
--- a/renpy/display/screen.py
+++ b/renpy/display/screen.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
 import renpy.display
 import time
 import collections
@@ -32,6 +33,7 @@ profile_log = renpy.log.open("profile_screen", developer=True, append=False, flu
 # A map from screen name to ScreenProfile object.
 profile = { }
 
+
 class ScreenProfile(renpy.object.Object):
     """
     :doc: profile_screen
@@ -107,6 +109,7 @@ class ScreenProfile(renpy.object.Object):
                 name = tuple(name.split())
                 profile[name] = self
 
+
 def get_profile(name):
     """
     Returns the profile object for the screen with `name`, or a default
@@ -130,6 +133,7 @@ def get_profile(name):
 # does not exceed config.screen_cache_size for each screen.
 predict_cache = collections.defaultdict(list)
 
+
 class ScreenCache(object):
     """
     Represents an entry in the screen cache. Upon creation, puts itself into
@@ -154,6 +158,7 @@ class ScreenCache(object):
 
 cache_put = ScreenCache
 
+
 def cache_get(screen, args, kwargs):
     """
     Returns the cache to use when `screen` is accessed with `args` and
@@ -220,7 +225,7 @@ class Screen(renpy.object.Object):
 
         # If this is a SL2 screen, the SLScreen node at the root of this
         # screen.
-        if isinstance(function, renpy.sl2.slast.SLScreen): # @UndefinedVariable
+        if isinstance(function, renpy.sl2.slast.SLScreen):  # @UndefinedVariable
             self.ast = function
         else:
             self.ast = None
@@ -257,7 +262,7 @@ class Screen(renpy.object.Object):
 
 
 # Phases we can be in.
-PREDICT = 0 # Predicting the screen before it is shown.
+PREDICT = 0  # Predicting the screen before it is shown.
 SHOW = 1    # Showing the screen for the first time.
 UPDATE = 2  # Showing the screen for the second and later times.
 HIDE = 3    # After the screen has been hid with "hide screen" (or the end of call screen).
@@ -271,6 +276,7 @@ phase_name = [
     "OLD",
     ]
 
+
 class ScreenDisplayable(renpy.display.layout.Container):
     """
     A screen is a collection of widgets that are displayed together. This
@@ -354,7 +360,6 @@ class ScreenDisplayable(renpy.display.layout.Container):
         else:
             self.use_cache = { }
 
-
         # What widgets and transforms were the last time this screen was
         # updated. Used to communicate with the ui module, and only
         # valid during an update - not used at other times.
@@ -479,7 +484,7 @@ class ScreenDisplayable(renpy.display.layout.Container):
 
         return rv
 
-    def _in_old_scene(self):
+    def _in_current_store(self):
 
         if self.screen is None:
             return self
@@ -495,8 +500,9 @@ class ScreenDisplayable(renpy.display.layout.Container):
 
         rv = self.copy()
         rv.phase = OLD
-        return rv
+        rv.child = self.child._in_current_store()
 
+        return rv
 
     def update(self):
 
@@ -533,16 +539,15 @@ class ScreenDisplayable(renpy.display.layout.Container):
 
             if profile:
                 profile_log.write("%s %s %s",
-                    phase_name[self.phase],
-                    " ".join(self.screen_name),
-                    datetime.datetime.now().strftime("%H:%M:%S.%f"))
+                                  phase_name[self.phase],
+                                  " ".join(self.screen_name),
+                                  datetime.datetime.now().strftime("%H:%M:%S.%f"))
 
                 start = time.time()
 
                 if self.profile.debug:
                     debug = True
 
-
         # Cycle widgets and transforms.
         self.old_widgets = self.widgets
         self.old_transforms = self.transforms
@@ -663,11 +668,13 @@ _current_screen = None
 # The stack of old current screens.
 current_screen_stack = [ ]
 
+
 def push_current_screen(screen):
     global _current_screen
     current_screen_stack.append(_current_screen)
     _current_screen = screen
 
+
 def pop_current_screen():
     _current_screen = current_screen_stack.pop()
 
@@ -680,6 +687,7 @@ screens_by_name = collections.defaultdict(dict)
 # The screens that were updated during the current interaction.
 updated_screens = set()
 
+
 def get_screen_variant(name, candidates=None):
     """
     Get a variant screen object for `name`.
@@ -698,6 +706,7 @@ def get_screen_variant(name, candidates=None):
 
     return None
 
+
 def get_all_screen_variants(name):
     """
     Gets all variants of the screen with `name`.
@@ -724,6 +733,7 @@ prepared = False
 sorted_screens = [ ]
 screens_at_sort = { }
 
+
 def sort_screens():
     """
     Produces a list of SL2 screens in topologically sorted order.
@@ -782,6 +792,7 @@ def sort_screens():
 
     return rv
 
+
 def sorted_variants():
     """
     Produces a list of screen variants in topological order.
@@ -794,6 +805,7 @@ def sorted_variants():
 
     return rv
 
+
 def analyze_screens():
     """
     Analyzes all screens.
@@ -812,6 +824,7 @@ def analyze_screens():
 
     analyzed = True
 
+
 def prepare_screens():
     """
     Prepares all screens for use.
@@ -836,6 +849,7 @@ def prepare_screens():
 
     prepared = True
 
+
 def define_screen(*args, **kwargs):
     """
     :doc: screens
@@ -953,6 +967,7 @@ def has_screen(name):
     else:
         return False
 
+
 def show_screen(_screen_name, *_args, **kwargs):
     """
     :doc: screens
@@ -1090,7 +1105,7 @@ def predict_screen(_screen_name, *_args, **kwargs):
         if renpy.config.debug_image_cache:
             import traceback
 
-            print "While predicting screen", _screen_name
+            print("While predicting screen", _screen_name)
             traceback.print_exc()
 
     renpy.ui.reset()
@@ -1113,6 +1128,7 @@ def hide_screen(tag, layer=None):
     if screen is not None:
         renpy.exports.hide(screen.tag, layer=layer)
 
+
 def use_screen(_screen_name, *_args, **kwargs):
 
     _name = kwargs.pop("_name", ())
@@ -1146,10 +1162,12 @@ def use_screen(_screen_name, *_args, **kwargs):
 
     _current_screen.old_transfers = old_transfers
 
+
 def current_screen():
     return _current_screen
 
-def get_widget(screen, id, layer=None): #@ReservedAssignment
+
+def get_widget(screen, id, layer=None):  # @ReservedAssignment
     """
     :doc: screens
 
@@ -1178,7 +1196,8 @@ def get_widget(screen, id, layer=None): #@ReservedAssignment
     rv = screen.widgets.get(id, None)
     return rv
 
-def get_widget_properties(id, screen=None, layer=None): # @ReservedAssignment
+
+def get_widget_properties(id, screen=None, layer=None):  # @ReservedAssignment
     """
     :doc: screens
 
@@ -1210,6 +1229,7 @@ def get_widget_properties(id, screen=None, layer=None): # @ReservedAssignment
 
     return rv
 
+
 def before_restart():
     """
     This is called before Ren'Py restarts to put the screens into restart
diff --git a/renpy/display/swdraw.py b/renpy/display/swdraw.py
index cca48cc..c3d26fa 100644
--- a/renpy/display/swdraw.py
+++ b/renpy/display/swdraw.py
@@ -31,6 +31,7 @@ from renpy.display.render import blit_lock, IDENTITY, BLIT, DISSOLVE, IMAGEDISSO
 # A map from cached surface to rle version of cached surface.
 rle_cache = weakref.WeakKeyDictionary()
 
+
 class Clipper(object):
     """
     This is used to calculate the clipping rectangle and update rectangles
@@ -171,7 +172,6 @@ class Clipper(object):
         while sized:
             area, x0, y0, x1, y1 = sized.pop()
 
-
             merged = False
 
             if nca + area >= sa:
@@ -234,6 +234,7 @@ class Clipper(object):
 
 clippers = [ Clipper() ]
 
+
 def surface(w, h, alpha):
     """
     Creates a surface that shares a pixel format with the screen. The created
@@ -247,13 +248,15 @@ def surface(w, h, alpha):
 
     return rv.subsurface((2, 2, w, h))
 
+
 def copy_surface(surf):
     w, h = surf.get_size()
     rv = surface(w, h, True)
 
-    renpy.display.accelerator.nogil_copy(surf, rv) # @UndefinedVariable
+    renpy.display.accelerator.nogil_copy(surf, rv)  # @UndefinedVariable
     return rv
 
+
 def draw_special(what, dest, x, y):
     """
     This handles the special drawing operations, such as dissolve and
@@ -428,7 +431,6 @@ def draw(dest, clip, what, xo, yo, screen):
             # what.draw_func(newdest, newx, newy)
             draw_special(what, newdest, newx, newy)
 
-
         return
 
     # Deal with clipping, if necessary.
@@ -490,10 +492,11 @@ def draw(dest, clip, what, xo, yo, screen):
     for child, cxo, cyo, _focus, _main in what.visible_children:
         draw(dest, clip, child, xo + cxo, yo + cyo, screen)
 
+
 def draw_transformed(dest, clip, what, xo, yo, alpha, forward, reverse):
 
     # If our alpha has hit 0, don't do anything.
-    if alpha <= 0.003: # (1 / 256)
+    if alpha <= 0.003:  # (1 / 256)
         return
 
     if forward is None:
@@ -638,7 +641,6 @@ def draw_transformed(dest, clip, what, xo, yo, alpha, forward, reverse):
         draw_transformed(dest, clip, child, xo + cxo, yo + cyo, alpha * what.alpha * what.over, child_forward, child_reverse)
 
 
-
 def do_draw_screen(screen_render, full_redraw, swdraw):
     """
     Draws the render produced by render_screen to the screen.
@@ -690,7 +692,6 @@ class SWDraw(object):
         self.mouse_backing_pos = None
         self.mouse_info = None
 
-
         # Is the mouse currently visible?
         self.mouse_old_visible = None
 
@@ -858,7 +859,7 @@ class SWDraw(object):
         if self.mouse_location:
             updates.append(self.hide_mouse())
 
-        if tex and pos and renpy.game.interface.mouse_focused: # @UndefinedVariable
+        if tex and pos and renpy.game.interface.mouse_focused:  # @UndefinedVariable
             updates.append(self.show_mouse(pos, info))
 
         return updates
@@ -949,7 +950,6 @@ class SWDraw(object):
 
         return True
 
-
     def draw_screen(self, surftree, fullscreen_video):
         """
         Draws the screen.
@@ -998,11 +998,9 @@ class SWDraw(object):
             self.draw_mouse(True)
             pygame.display.flip()
 
-
         if fullscreen_video:
             self.full_redraw = True
 
-
     def render_to_texture(self, render, alpha):
 
         rv = surface(render.width, render.height, alpha)
@@ -1033,7 +1031,6 @@ class SWDraw(object):
             if what.forward:
                 cx, cy = what.forward.transform(cx, cy)
 
-
             if isinstance(child, renpy.display.render.Render):
                 if self.is_pixel_opaque(child, x, y):
                     return True
@@ -1051,7 +1048,6 @@ class SWDraw(object):
 
         return False
 
-
     def mutated_surface(self, surf):
         """
         Called to indicate that the given surface has changed.
@@ -1097,7 +1093,6 @@ class SWDraw(object):
         self.mutated_surface(surf)
         return surf
 
-
     def free_memory(self):
         """
         Frees up memory.
@@ -1114,7 +1109,7 @@ class SWDraw(object):
 
         return
 
-    def quit(self): #@ReservedAssignment
+    def quit(self):  # @ReservedAssignment
         """
         Shuts down the drawing system.
         """
diff --git a/renpy/display/transform.py b/renpy/display/transform.py
index b04c1a1..d5055b5 100644
--- a/renpy/display/transform.py
+++ b/renpy/display/transform.py
@@ -22,9 +22,9 @@
 # This file contains displayables that move, zoom, rotate, or otherwise
 # transform displayables. (As well as displayables that support them.)
 import math
-import types #@UnresolvedImport
+import types  # @UnresolvedImport
 
-import renpy.display #@UnusedImport
+import renpy.display  # @UnusedImport
 from renpy.display.layout import Container
 
 import renpy.display.accelerator
@@ -32,6 +32,7 @@ import renpy.display.accelerator
 # The null object that's used if we don't have a defined child.
 null = None
 
+
 def get_null():
     global null
 
@@ -41,6 +42,8 @@ def get_null():
     return null
 
 # Convert a position from cartesian to polar coordinates.
+
+
 def cartesian_to_polar(x, y, xaround, yaround):
     """
     Converts cartesian coordinates to polar coordinates.
@@ -57,6 +60,7 @@ def cartesian_to_polar(x, y, xaround, yaround):
 
     return angle, radius
 
+
 def polar_to_cartesian(angle, radius, xaround, yaround):
     """
     Converts polart coordinates to cartesian coordinates.
@@ -72,6 +76,7 @@ def polar_to_cartesian(angle, radius, xaround, yaround):
 
     return x, y
 
+
 def first_not_none(*args):
     """
     Returns the first argument that is not None.
@@ -149,7 +154,6 @@ class TransformState(renpy.object.Object):
         # - renpy.atl.PROPERTIES
         # - Proxies in Transform
 
-
         # An xpos (etc) inherited from our child overrides an xpos inherited
         # from an old transform, but not an xpos set in the current transform.
         #
@@ -401,6 +405,7 @@ class TransformState(renpy.object.Object):
     xcenter = property(get_xcenter, set_xcenter)
     ycenter = property(get_ycenter, set_ycenter)
 
+
 class Proxy(object):
     """
     This class proxies a field from the transform to its state.
@@ -415,6 +420,7 @@ class Proxy(object):
     def __set__(self, instance, value):
         return setattr(instance.state, self.name, value)
 
+
 class Transform(Container):
     """
     Documented in sphinx, because we can't scan this object.
@@ -517,16 +523,16 @@ class Transform(Container):
             self.replaced_response = True
 
     DEFAULT_ARGUMENTS = {
-            "selected_activate" : { },
-            "selected_hover" : { },
-            "selected_idle" : { },
-            "selected_insensitive" : { },
-            "activate" : { },
-            "hover" : { },
-            "idle" : { },
-            "insensitive" : { },
-            "" : { },
-            }
+        "selected_activate" : { },
+        "selected_hover" : { },
+        "selected_idle" : { },
+        "selected_insensitive" : { },
+        "activate" : { },
+        "hover" : { },
+        "idle" : { },
+        "insensitive" : { },
+        "" : { },
+        }
 
     # Compatibility with old versions of the class.
     active = False
@@ -543,7 +549,7 @@ class Transform(Container):
                  style='transform',
                  focus=None,
                  default=False,
-                 _args = None,
+                 _args=None,
 
                  **kwargs):
 
@@ -662,7 +668,6 @@ class Transform(Container):
 
         super(Transform, self).set_transform_event(event)
 
-
     def take_state(self, t):
         """
         Takes the transformation state from object t into this object.
@@ -679,7 +684,6 @@ class Transform(Container):
         # The arguments will be applied when the default function is
         # called.
 
-
     def take_execution_state(self, t):
         """
         Takes the execution state from object t into this object. This is
@@ -705,7 +709,6 @@ class Transform(Container):
         if isinstance(self.child, Transform) and isinstance(t.child, Transform):
             self.child.take_execution_state(t.child)
 
-
     def copy(self):
         """
         Makes a copy of this transform.
@@ -811,7 +814,6 @@ class Transform(Container):
 
         self.active = True
 
-
     # The render method is now defined in accelerator.pyx.
 
     def event(self, ev, x, y, st):
@@ -944,11 +946,26 @@ class Transform(Container):
         rv.take_execution_state(self)
         return rv
 
+    def _in_current_store(self):
+
+        if self.child is None:
+            return self
+
+        child = self.child._in_current_store()
+        if child is self.child:
+            return self
+        rv = self()
+        rv.take_execution_state(self)
+        rv.child = child
+
+        return rv
+
     def _show(self):
         self.update_state()
 
 Transform.render = types.MethodType(renpy.display.accelerator.transform_render, None, Transform)
 
+
 class ATLTransform(renpy.atl.ATLTransformBase, Transform):
 
     def __init__(self, atl, child=None, context={}, parameters=None, **properties):
@@ -963,4 +980,3 @@ class ATLTransform(renpy.atl.ATLTransformBase, Transform):
     def _show(self):
         super(ATLTransform, self)._show()
         self.execute(self, self.st, self.at)
-
diff --git a/renpy/display/transition.py b/renpy/display/transition.py
index 2c0b0be..44587c5 100644
--- a/renpy/display/transition.py
+++ b/renpy/display/transition.py
@@ -42,12 +42,12 @@ class Transition(renpy.display.core.Displayable):
     def event(self, ev, x, y, st):
 
         if self.events or ev.type == renpy.display.core.TIMEEVENT:
-            return self.new_widget.event(ev, x, y, st) # E1101
+            return self.new_widget.event(ev, x, y, st)  # E1101
         else:
             return None
 
     def visit(self):
-        return [ self.new_widget, self.old_widget ] # E1101
+        return [ self.new_widget, self.old_widget ]  # E1101
 
 
 def null_render(d, width, height, st, at):
@@ -63,6 +63,7 @@ def null_render(d, width, height, st, at):
 
     return rv
 
+
 class NoTransition(Transition):
     """
     :doc: transition function
@@ -196,7 +197,6 @@ def Fade(out_time,
          widget=None,
          alpha=False,
          ):
-
     """
     :doc: transition function
     :args: (out_time, hold_time, in_time, color="#000")
@@ -290,7 +290,6 @@ class Pixellate(Transition):
             visible = self.new_widget
             self.events = True
 
-
         rdr = render(visible, width, height, st, at)
         rv = renpy.display.render.Render(rdr.width, rdr.height)
 
@@ -344,7 +343,6 @@ class Dissolve(Transition):
         self.alpha = alpha
         self.time_warp = time_warp
 
-
     def render(self, width, height, st, at):
 
         if renpy.game.less_updates:
@@ -432,18 +430,18 @@ class ImageDissolve(Transition):
     time_warp = None
 
     def __init__(
-        self,
-        image,
-        time,
-        ramplen=8,
-        ramptype='linear',
-        ramp=None,
-        reverse=False,
-        alpha=False,
-        old_widget=None,
-        new_widget=None,
-        time_warp=None,
-        **properties):
+            self,
+            image,
+            time,
+            ramplen=8,
+            ramptype='linear',
+            ramp=None,
+            reverse=False,
+            alpha=False,
+            old_widget=None,
+            new_widget=None,
+            time_warp=None,
+            **properties):
 
         # ramptype and ramp are now unused, but are kept for compatbility with
         # older code.
@@ -482,11 +480,9 @@ class ImageDissolve(Transition):
         # The length of the ramp.
         self.ramplen = max(ramplen, 1)
 
-
     def visit(self):
         return super(ImageDissolve, self).visit() + [ self.image ]
 
-
     def render(self, width, height, st, at):
 
         if renpy.game.less_updates or renpy.display.less_imagedissolve:
@@ -551,14 +547,14 @@ class AlphaDissolve(Transition):
      """
 
     def __init__(
-        self,
-        control,
-        delay=0.0,
-        old_widget=None,
-        new_widget=None,
-        alpha=False,
-        reverse=False,
-        **properties):
+            self,
+            control,
+            delay=0.0,
+            old_widget=None,
+            new_widget=None,
+            alpha=False,
+            reverse=False,
+            **properties):
 
         super(AlphaDissolve, self).__init__(delay, **properties)
 
@@ -804,7 +800,6 @@ class CropMove(Transition):
             endcrop = (0.5, 0.5, 0.0, 0.0)
             topnew = False
 
-
         elif mode == "custom":
             pass
         else:
@@ -855,7 +850,6 @@ class CropMove(Transition):
         crop = interpolate_tuple(self.startcrop, self.endcrop)
         pos = interpolate_tuple(self.startpos, self.endpos)
 
-
         top = render(self.top, width, height, st, at)
         bottom = render(self.bottom, width, height, st, at)
 
@@ -915,7 +909,7 @@ class PushMove(Transition):
             self.old_endcrop = (0.0, 0.0, 0.0, 1.0)
             self.old_startpos = (0.0, 0.0)
             self.old_startcrop = (0.0, 0.0, 1.0, 1.0)
-            
+
         elif mode == "pushleft":
             self.new_startpos = (1.0, 0.0)
             self.new_startcrop = (0.0, 0.0, 0.0, 1.0)
@@ -925,7 +919,7 @@ class PushMove(Transition):
             self.old_endcrop = (1.0, 0.0, 0.0, 1.0)
             self.old_startpos = (0.0, 0.0)
             self.old_startcrop = (0.0, 0.0, 1.0, 1.0)
-            
+
         elif mode == "pushup":
             self.new_startpos = (0.0, 1.0)
             self.new_startcrop = (0.0, 0.0, 1.0, 0.0)
@@ -935,7 +929,7 @@ class PushMove(Transition):
             self.old_endcrop = (0.0, 1.0, 1.0, 0.0)
             self.old_startpos = (0.0, 0.0)
             self.old_startcrop = (0.0, 0.0, 1.0, 1.0)
-            
+
         elif mode == "pushdown":
             self.new_startpos = (0.0, 0.0)
             self.new_startcrop = (0.0, 1.0, 1.0, 0.0)
@@ -945,7 +939,7 @@ class PushMove(Transition):
             self.old_endcrop = (0.0, 0.0, 1.0, 0.0)
             self.old_startpos = (0.0, 0.0)
             self.old_startcrop = (0.0, 0.0, 1.0, 1.0)
-            
+
         else:
             raise Exception("Invalid mode %s passed into PushMove." % mode)
 
@@ -978,25 +972,25 @@ class PushMove(Transition):
 
         new_crop = interpolate_tuple(self.new_startcrop, self.new_endcrop)
         new_pos = interpolate_tuple(self.new_startpos, self.new_endpos)
-        
+
         old_crop = interpolate_tuple(self.old_startcrop, self.old_endcrop)
         old_pos = interpolate_tuple(self.old_startpos, self.old_endpos)
 
-
         new = render(self.new_widget, width, height, st, at)
         old = render(self.old_widget, width, height, st, at)
 
         rv = renpy.display.render.Render(width, height)
 
-        old_ss = old.subsurface(old_crop, focus = True)
-        rv.blit(old_ss, old_pos, focus = True)
+        old_ss = old.subsurface(old_crop, focus=True)
+        rv.blit(old_ss, old_pos, focus=True)
 
-        new_ss = new.subsurface(new_crop, focus = True)
-        rv.blit(new_ss, new_pos, focus = True)
+        new_ss = new.subsurface(new_crop, focus=True)
+        rv.blit(new_ss, new_pos, focus=True)
 
         renpy.display.render.redraw(self, 0)
         return rv
 
+
 def ComposeTransition(trans, before=None, after=None, new_widget=None, old_widget=None):
     """
     :doc: transition function
@@ -1045,4 +1039,3 @@ def SubTransition(rect, trans, old_widget=None, new_widget=None, **properties):
     f.add(inner)
 
     return NoTransition(delay, old_widget=f, new_widget=f)
-
diff --git a/renpy/display/tts.py b/renpy/display/tts.py
index c898a9c..e910aad 100644
--- a/renpy/display/tts.py
+++ b/renpy/display/tts.py
@@ -25,6 +25,7 @@ import renpy.audio
 import subprocess
 import pygame
 
+
 class TTSRoot(Exception):
     """
     An exception that can be used to cause the TTS system to read the text
@@ -41,6 +42,7 @@ last = ""
 # The speech synthesis process.
 process = None
 
+
 def periodic():
     global process
 
@@ -91,7 +93,6 @@ def default_tts_function(s):
         else:
             process = subprocess.Popen([ "espeak", "-v", fsencode(renpy.config.tts_voice), fsencode(s) ])
 
-
     elif renpy.macintosh:
 
         if renpy.config.tts_voice is None:
@@ -99,12 +100,10 @@ def default_tts_function(s):
         else:
             process = subprocess.Popen([ "say", "-v", fsencode(renpy.config.tts_voice), fsencode(s) ])
 
-
-
     elif renpy.windows:
 
         if renpy.config.tts_voice is None:
-            voice = "default voice" # something that is unlikely to match.
+            voice = "default voice"  # something that is unlikely to match.
         else:
             voice = renpy.config.tts_voice
 
@@ -141,6 +140,7 @@ def speak(s, translate=True, force=False):
 
     tts(s)
 
+
 def set_root(d):
     global root
     root = d
@@ -148,6 +148,7 @@ def set_root(d):
 # The old value of the self_voicing preference.
 old_self_voicing = False
 
+
 def displayable(d):
     """
     Causes the TTS system to read the text of the displayable `d`.
diff --git a/renpy/display/video.py b/renpy/display/video.py
index a432d14..2b5a9be 100644
--- a/renpy/display/video.py
+++ b/renpy/display/video.py
@@ -39,6 +39,7 @@ surface_file = None
 # The surface to display the movie on, if not fullscreen.
 surface = None
 
+
 def movie_stop(clear=True, only_fullscreen=False):
     """
     Stops the currently playing movie.
@@ -94,6 +95,7 @@ old_channel_movie = { }
 # Is there a video being displayed fullscreen?
 fullscreen = False
 
+
 def early_interact():
     """
     Called early in the interact process, to clear out the fullscreen
@@ -116,8 +118,6 @@ def interact():
         if not renpy.audio.music.get_playing(i):
             del texture[i]
 
-
-
     if renpy.audio.music.get_playing("movie"):
 
         for i in displayable_channels.keys():
@@ -166,6 +166,7 @@ def get_movie_texture(channel, mask_channel=None):
 
     return tex, new
 
+
 def render_movie(channel, width, height):
     tex, _new = get_movie_texture(channel)
 
@@ -206,8 +207,9 @@ class Movie(renpy.display.core.Displayable):
 
     `channel`
         The audio channel associated with this movie. When a movie file
-        is played on that channel, it wil be displayed in this Movie
-        displayable.
+        is played on that channel, it will be displayed in this Movie
+        displayable. If this is not given, and the `play` is provided,
+        a channel name is automatically selected.
 
     `play`
         If given, this should be the path to a movie file. The movie
@@ -256,6 +258,12 @@ class Movie(renpy.display.core.Displayable):
 
     def __init__(self, fps=24, size=None, channel="movie", play=None, mask=None, mask_channel=None, image=None, **properties):
         super(Movie, self).__init__(**properties)
+
+        global auto_channel_serial
+
+        if channel == "movie" and play and renpy.config.auto_movie_channel:
+            channel = "movie_{}_{}".format(play, mask)
+
         self.size = size
         self.channel = channel
         self._play = play
@@ -354,7 +362,6 @@ class Movie(renpy.display.core.Displayable):
             if self.mask:
                 renpy.audio.music.stop(channel=self.mask_channel)
 
-
     def per_interact(self):
         displayable_channels[(self.channel, self.mask_channel)].append(self)
         renpy.display.render.redraw(self, 0)
@@ -370,6 +377,7 @@ def playing():
         if renpy.audio.music.get_playing(channel):
             return True
 
+
 def update_playing():
     """
     Calls play/stop on Movie displayables.
@@ -389,6 +397,7 @@ def update_playing():
 
     old_channel_movie = dict(channel_movie)
 
+
 def frequent():
     """
     Called to update the video playback. Returns true if a video refresh is
diff --git a/renpy/display/viewport.py b/renpy/display/viewport.py
index 3c4aa7a..80752ca 100644
--- a/renpy/display/viewport.py
+++ b/renpy/display/viewport.py
@@ -33,6 +33,7 @@ def edgescroll_proportional(n):
     """
     return n
 
+
 class Viewport(renpy.display.layout.Container):
 
     __version__ = 5
@@ -71,7 +72,6 @@ class Viewport(renpy.display.layout.Container):
         if version < 5:
             self.focusable = self.draggable
 
-
     def __init__(self,
                  child=None,
                  child_size=(None, None),
@@ -234,8 +234,9 @@ class Viewport(renpy.display.layout.Container):
         cxo = -int(self.xadjustment.value)
         cyo = -int(self.yadjustment.value)
 
-        return cxo, cyo, width, height
+        self._clipping = (cw > width) or (ch > height)
 
+        return cxo, cyo, width, height
 
     def render(self, width, height, st, at):
 
@@ -255,6 +256,8 @@ class Viewport(renpy.display.layout.Container):
         rv = renpy.display.render.Render(width, height)
         rv.blit(surf, (cxo, cyo))
 
+        rv = rv.subsurface((0, 0, width, height), focus=True)
+
         if self.arrowkeys:
             rv.add_focus(self, None, None, None, None, None)
 
@@ -298,7 +301,7 @@ class Viewport(renpy.display.layout.Container):
             self.xadjustment.change(self.xadjustment.value - dx)
             self.yadjustment.change(self.yadjustment.value - dy)
 
-            self.drag_position = (x, y) # W0201
+            self.drag_position = (x, y)  # W0201
 
             if renpy.display.behavior.map_event(ev, 'viewport_drag_end'):
                 renpy.display.focus.set_grab(None)
@@ -316,13 +319,24 @@ class Viewport(renpy.display.layout.Container):
 
         if inside and self.mousewheel:
 
-            if self.mousewheel == "horizontal":
+            if self.mousewheel == "horizontal-change":
                 adjustment = self.xadjustment
+                change = True
+            elif self.mousewheel == "change":
+                adjustment = self.yadjustment
+                change = True
+            elif self.mousewheel == "horizontal":
+                adjustment = self.xadjustment
+                change = False
             else:
                 adjustment = self.yadjustment
-
+                change = False
 
             if renpy.display.behavior.map_event(ev, 'viewport_up'):
+
+                if change and (adjustment.value == 0):
+                    return None
+
                 rv = adjustment.change(adjustment.value - adjustment.step)
                 if rv is not None:
                     return rv
@@ -330,6 +344,10 @@ class Viewport(renpy.display.layout.Container):
                     raise renpy.display.core.IgnoreEvent()
 
             if renpy.display.behavior.map_event(ev, 'viewport_down'):
+
+                if change and (adjustment.value == adjustment.range):
+                    return None
+
                 rv = adjustment.change(adjustment.value + adjustment.step)
                 if rv is not None:
                     return rv
@@ -459,7 +477,6 @@ class VPGrid(Viewport):
         self.grid_rows = rows
         self.grid_transpose = transpose
 
-
     def render(self, width, height, st, at):
 
         self.width = width
@@ -497,7 +514,6 @@ class VPGrid(Viewport):
         tw = (cw + spacing) * cols - spacing
         th = (ch + spacing) * rows - spacing
 
-
         if self.style.xfill:
             tw = child_width
             cw = (tw - (cols - 1) * spacing) / cols
@@ -546,6 +562,8 @@ class VPGrid(Viewport):
 
             self.offsets.append(pos)
 
+        rv = rv.subsurface((0, 0, width, height), focus=True)
+
         if self.arrowkeys:
             rv.add_focus(self, None, None, None, None, None)
 
diff --git a/renpy/dump.py b/renpy/dump.py
index 325294d..f18d697 100644
--- a/renpy/dump.py
+++ b/renpy/dump.py
@@ -41,6 +41,7 @@ screens = [ ]
 # Does a file exist? We cache the result here.
 file_exists_cache = { }
 
+
 def file_exists(fn):
     rv = file_exists_cache.get(fn, None)
 
@@ -56,6 +57,7 @@ def file_exists(fn):
 # Did we do a dump?
 completed_dump = False
 
+
 def dump(error):
     """
     Causes a JSON dump file to be written, if the user has requested it.
@@ -64,7 +66,6 @@ def dump(error):
         An error flag that is added to the written file.
     """
 
-
     global completed_dump
 
     args = renpy.game.args
@@ -77,7 +78,7 @@ def dump(error):
     if not args.json_dump:
         return
 
-    def filter(name, filename): #@ReservedAssignment
+    def filter(name, filename):  # @ReservedAssignment
         """
         Returns true if the name is included by the filter, or false if it is excluded.
         """
@@ -132,7 +133,6 @@ def dump(error):
 
         label[name] = [ filename, line ]
 
-
     # Definitions.
     define = location["define"] = { }
 
@@ -160,7 +160,6 @@ def dump(error):
 
         transform[name] = [ filename, line ]
 
-
     # Code.
 
     def get_line(o):
@@ -238,7 +237,7 @@ def dump(error):
 
     # Add the build info from 00build.rpy, if it's available.
     try:
-        result["build"] = renpy.store.build.dump() #@UndefinedVariable
+        result["build"] = renpy.store.build.dump()  # @UndefinedVariable
     except:
         pass
 
diff --git a/renpy/easy.py b/renpy/easy.py
index bb765f6..1ba591d 100644
--- a/renpy/easy.py
+++ b/renpy/easy.py
@@ -21,6 +21,7 @@
 
 # Functions that make the user's life easier.
 
+from __future__ import print_function
 import renpy.display
 import renpy.styledata
 import contextlib
@@ -29,6 +30,7 @@ import time
 Color = renpy.color.Color
 color = renpy.color.Color
 
+
 def displayable_or_none(d, scope=None, dynamic=True):
 
     if isinstance(d, renpy.display.core.Displayable):
@@ -64,6 +66,7 @@ def displayable_or_none(d, scope=None, dynamic=True):
 
     raise Exception("Not a displayable: %r" % (d,))
 
+
 def displayable(d, scope=None):
     """
     :doc: udd_utility
@@ -128,7 +131,7 @@ def dynamic_image(d, scope=None, prefix=None):
             else:
                 scope = { }
 
-            for p in renpy.styledata.stylesets.prefix_search[prefix]: # @UndefinedVariable
+            for p in renpy.styledata.stylesets.prefix_search[prefix]:  # @UndefinedVariable
                 scope["prefix_"] = p
 
                 rv = renpy.substitutions.substitute(i, scope=scope, force=True, translate=False)[0]
@@ -165,7 +168,7 @@ def predict(d):
 def timed(name):
     start = time.time()
     yield
-    print "{0}: {1:.2f} ms".format(name, (time.time() - start) * 1000.0)
+    print("{0}: {1:.2f} ms".format(name, (time.time() - start) * 1000.0))
 
 
 def split_properties(properties, *prefixes):
diff --git a/renpy/editor.py b/renpy/editor.py
index d94b682..d630764 100644
--- a/renpy/editor.py
+++ b/renpy/editor.py
@@ -24,6 +24,7 @@ import renpy
 import traceback
 import subprocess
 
+
 class Editor(object):
     """
     This class is intended to be subclassed by editor subclasses. It provides a
@@ -63,7 +64,7 @@ class Editor(object):
         Ends an editor transaction.
         """
 
-    def open(self, filename, line=None, **kwargs): #@ReservedAssignment
+    def open(self, filename, line=None, **kwargs):  # @ReservedAssignment
         """
         Ensures `path` is open in the editor. This may be called multiple
         times per transaction.
@@ -79,26 +80,26 @@ class Editor(object):
 
 class SystemEditor(Editor):
 
-    def open(self, filename, line=None, **kwargs): #@ReservedAssignment
+    def open(self, filename, line=None, **kwargs):  # @ReservedAssignment
 
         filename = renpy.exports.fsencode(filename)
 
         try:
             if renpy.windows:
-                os.startfile(filename) #@UndefinedVariable
+                os.startfile(filename)  # @UndefinedVariable
             elif renpy.macintosh:
-                subprocess.call([ "open", filename ]) #@UndefinedVariable
+                subprocess.call([ "open", filename ])  # @UndefinedVariable
             elif renpy.linux:
-                subprocess.call([ "xdg-open", filename ]) #@UndefinedVariable
+                subprocess.call([ "xdg-open", filename ])  # @UndefinedVariable
         except:
             traceback.print_exc()
 
 
-
 # The editor that Ren'Py is using. It should be a subclass of the Editor
 # class.
 editor = None
 
+
 def init():
     """
     Creates the editor object, based on the contents of the RENPY_EDIT_PY
@@ -122,6 +123,7 @@ def init():
 
     raise Exception("{0} did not define an Editor class.".format(path))
 
+
 def launch_editor(filenames, line=1, transient=False):
     """
     Causes the editor to be launched.
@@ -144,7 +146,7 @@ def launch_editor(filenames, line=1, transient=False):
 
         for i in filenames:
             editor.open(i, line)
-            line = None # The line number only applies to the first filename.
+            line = None  # The line number only applies to the first filename.
 
         editor.end()
 
diff --git a/renpy/error.py b/renpy/error.py
index 0710a78..c96641f 100644
--- a/renpy/error.py
+++ b/renpy/error.py
@@ -21,6 +21,7 @@
 
 # This file contains code for formatting tracebacks.
 
+from __future__ import print_function
 import traceback
 import sys
 import cStringIO
@@ -103,6 +104,7 @@ def traceback_list(tb):
 
     return rv
 
+
 def filter_traceback_list(tl):
     """
     Returns the subset of `tl` that originates in creator-written files, as
@@ -143,6 +145,7 @@ def open_error_file(fn, mode):
     new_fn = os.path.join(tempfile.gettempdir(), "renpy-" + fn)
     return file(new_fn, mode), new_fn
 
+
 def report_exception(e, editor=True):
     """
     Reports an exception by writing it to standard error and
@@ -155,9 +158,9 @@ def report_exception(e, editor=True):
 
     import codecs
 
-    type, _value, tb = sys.exc_info() #@ReservedAssignment
+    type, _value, tb = sys.exc_info()  # @ReservedAssignment
 
-    print(repr(e))
+    print((repr(e)))
 
     def safe_utf8(e):
         try:
@@ -188,15 +191,15 @@ def report_exception(e, editor=True):
     full_tl = traceback_list(tb)
     simple_tl = filter_traceback_list(full_tl)
 
-    print >>simple, renpy.game.exception_info
+    print(renpy.game.exception_info, file=simple)
     write_utf8_traceback_list(simple, simple_tl)
-    print >>simple, type.__name__ + ":",
-    print >>simple, safe_utf8(e)
+    print(type.__name__ + ":", end=' ', file=simple)
+    print(safe_utf8(e), file=simple)
 
-    print >>full, "Full traceback:"
+    print("Full traceback:", file=full)
     write_utf8_traceback_list(full, full_tl)
-    print >>full, type.__name__ + ":",
-    print >>full, safe_utf8(e)
+    print(type.__name__ + ":", end=' ', file=full)
+    print(safe_utf8(e), file=full)
 
     # Write to stdout/stderr.
     sys.stdout.write("\n")
@@ -204,15 +207,14 @@ def report_exception(e, editor=True):
     sys.stdout.write("\n")
     sys.stdout.write(simple.getvalue())
 
-    print >>full
+    print(file=full)
     try:
-        print >>full, platform.platform()
-        print >>full, renpy.version
-        print >>full, renpy.config.name + " " + renpy.config.version
+        print(platform.platform(), file=full)
+        print(renpy.version, file=full)
+        print(renpy.config.name + " " + renpy.config.version, file=full)
     except:
         pass
 
-
     simple = simple.getvalue()
     full = full.getvalue()
 
@@ -223,20 +225,20 @@ def report_exception(e, editor=True):
 
         f.write(codecs.BOM_UTF8)
 
-        print >>f, "I'm sorry, but an uncaught exception occurred."
-        print >>f
+        print("I'm sorry, but an uncaught exception occurred.", file=f)
+        print(file=f)
 
         f.write(simple)
 
-        print >>f
-        print >>f, "-- Full Traceback ------------------------------------------------------------"
-        print >>f
+        print(file=f)
+        print("-- Full Traceback ------------------------------------------------------------", file=f)
+        print(file=f)
 
         f.write(full)
         f.close()
 
         try:
-            if editor and renpy.game.args.command == "run": #@UndefinedVariable
+            if editor and renpy.game.args.command == "run":  # @UndefinedVariable
                 renpy.exports.launch_editor([ traceback_fn ], 1, transient=1)
         except:
             pass
@@ -245,10 +247,8 @@ def report_exception(e, editor=True):
         pass
 
     try:
-        renpy.display.log.exception() #@UndefinedVariable
+        renpy.display.log.exception()  # @UndefinedVariable
     except:
         pass
 
     return simple.decode("utf-8", "replace"), full.decode("utf-8", "replace"), traceback_fn
-
-
diff --git a/renpy/execution.py b/renpy/execution.py
index 4116559..4c0a3ce 100644
--- a/renpy/execution.py
+++ b/renpy/execution.py
@@ -22,6 +22,7 @@
 # This file contains code responsible for managing the execution of a
 # renpy object, as well as the context object.
 
+from __future__ import print_function
 import sys
 import time
 
@@ -37,6 +38,7 @@ il_statements = 0
 # The deadline for reporting we're not in an infinite loop.
 il_time = 0
 
+
 def check_infinite_loop():
     global il_statements
 
@@ -55,6 +57,7 @@ def check_infinite_loop():
 
     return
 
+
 def not_infinite_loop(delay):
     """
     :doc: other
@@ -65,14 +68,32 @@ def not_infinite_loop(delay):
     global il_time
     il_time = time.time() + delay
 
+
 class Delete(object):
     pass
 
+
 class PredictInfo(renpy.object.Object):
     """
     Not used anymore, but needed for backwards compatibility.
     """
 
+
+class LineLogEntry(object):
+
+    def __init__(self, filename, line, node, abnormal):
+        self.filename = filename
+        self.line = line
+        self.node = node
+        self.abnormal = abnormal
+
+    def __eq__(self, other):
+        if not isinstance(other, LineLogEntry):
+            return False
+
+        return (self.filename == other.filename) and (self.line == other.line) and (self.node is other.node)
+
+
 class Context(renpy.object.Object):
     """
     This is the context object which stores the current context
@@ -102,6 +123,8 @@ class Context(renpy.object.Object):
 
     next_node = None
 
+    force_checkpoint = False
+
     def after_upgrade(self, version):
         if version < 1:
             self.scene_lists.image_predict_info = self.predict_info.images
@@ -146,7 +169,6 @@ class Context(renpy.object.Object):
         if version < 13:
             self.line_log = [ ]
 
-
     def __init__(self, rollback, context=None, clear=False):
         """
         `clear`
@@ -206,6 +228,10 @@ class Context(renpy.object.Object):
         # cleared.
         self.line_log = [ ]
 
+        # Do we want to force a checkpoint before the next statement
+        # executed?
+        self.force_checkpoint = False
+
         if context:
             oldsl = context.scene_lists
             self.runtime = context.runtime
@@ -243,7 +269,6 @@ class Context(renpy.object.Object):
         # The language of the current translate block.
         self.translate_block_language = None
 
-
     def make_dynamic(self, names, context=False):
         """
         Makes the variable names listed in names dynamic, by backing up
@@ -267,7 +292,6 @@ class Context(renpy.object.Object):
             else:
                 self.dynamic_stack[index][i] = Delete()
 
-
     def pop_dynamic(self):
         """
         Pops one level of the dynamic stack. Called when the return
@@ -296,7 +320,6 @@ class Context(renpy.object.Object):
         while self.dynamic_stack:
             self.pop_dynamic()
 
-
     def goto_label(self, node_name):
         """
         Sets the name of the node that will be run when this context
@@ -356,7 +379,7 @@ class Context(renpy.object.Object):
         ps = pyast.Pass(lineno=node.linenumber, col_offset=0)
         module = pyast.Module(lineno=node.linenumber, col_offset=0, body=[ ps ])
         code = compile(module, node.filename, 'exec')
-        exec code
+        exec(code)
 
     def run(self, node=None):
         """
@@ -383,7 +406,7 @@ class Context(renpy.object.Object):
             self.defer_rollback = None
 
             if renpy.config.line_log:
-                ll_entry = (node.filename, node.linenumber, node)
+                ll_entry = LineLogEntry(node.filename, node.linenumber, node, self.last_abnormal)
 
                 if ll_entry not in self.line_log:
                     self.line_log.append(ll_entry)
@@ -391,6 +414,10 @@ class Context(renpy.object.Object):
             if self.rollback and renpy.game.log:
                 renpy.game.log.begin()
 
+            if self.force_checkpoint:
+                renpy.game.log.checkpoint(hard=False)
+                self.force_checkpoint = False
+
             self.seen = False
 
             renpy.test.testexecution.take_name(self.current)
@@ -410,14 +437,14 @@ class Context(renpy.object.Object):
                     if developer and self.next_node:
                         self.check_stacks()
 
-                except renpy.game.CONTROL_EXCEPTIONS, e:
+                except renpy.game.CONTROL_EXCEPTIONS as e:
 
                     # An exception ends the current translation.
                     self.translate_interaction = None
 
                     raise
 
-                except Exception, e:
+                except Exception as e:
                     self.translate_interaction = None
 
                     exc_info = sys.exc_info()
@@ -428,18 +455,18 @@ class Context(renpy.object.Object):
                             self.exception_handler(short, full, traceback_fn)
                         elif renpy.display.error.report_exception(short, full, traceback_fn):
                             raise
-                    except renpy.game.CONTROL_EXCEPTIONS, ce:
+                    except renpy.game.CONTROL_EXCEPTIONS as ce:
                         raise ce
-                    except Exception, ce:
+                    except Exception as ce:
                         raise exc_info[0], exc_info[1], exc_info[2]
 
                 node = self.next_node
 
-            except renpy.game.JumpException, e:
+            except renpy.game.JumpException as e:
                 node = renpy.game.script.lookup(e.args[0])
                 self.abnormal = True
 
-            except renpy.game.CallException, e:
+            except renpy.game.CallException as e:
 
                 if self.next_node is None:
                     raise Exception("renpy.call can't be used when the next node is undefined.")
@@ -456,7 +483,6 @@ class Context(renpy.object.Object):
             if self.rollback and renpy.game.log:
                 renpy.game.log.complete()
 
-
     def mark_seen(self):
         """
         Marks the current statement as one that has been seen by the user.
@@ -572,7 +598,6 @@ class Context(renpy.object.Object):
 
         return renpy.game.script.lookup(label)
 
-
     def predict_return(self):
         """
         This predicts that a return will occur.
@@ -649,9 +674,9 @@ class Context(renpy.object.Object):
                 if renpy.config.debug_image_cache:
                     import traceback
 
-                    print
+                    print()
                     traceback.print_exc()
-                    print "While predicting images."
+                    print("While predicting images.")
 
             self.images = old_images
             self.predict_return_stack = None
@@ -660,7 +685,6 @@ class Context(renpy.object.Object):
 
         yield False
 
-
     def seen_current(self, ever):
         """
         Returns a true value if we have finshed the current statement
diff --git a/renpy/exports.py b/renpy/exports.py
index 6134616..4b5bb88 100644
--- a/renpy/exports.py
+++ b/renpy/exports.py
@@ -24,6 +24,8 @@
 # their behavior, while functions imported in are probably best left
 # alone as part of the api.
 
+from __future__ import print_function
+
 # Remember the real file.
 _file = file
 
@@ -34,6 +36,7 @@ import renpy.audio
 
 from renpy.pyanalysis import const, pure, not_const
 
+
 def renpy_pure(fn):
     """
     Marks renpy.`fn` as a pure function.
@@ -116,6 +119,7 @@ import time
 import sys
 import threading
 
+
 def public_api():
     """
     :undocumented:
@@ -303,6 +307,7 @@ def retain_after_load():
 
 scene_lists = renpy.display.core.scene_lists
 
+
 def count_displayables_in_layer(layer):
     """
     Returns how many displayables are in the supplied layer.
@@ -461,6 +466,7 @@ def showing(name, layer='master'):
 
     return renpy.game.context().images.showing(layer, name)
 
+
 def get_showing_tags(layer='master'):
     """
     :doc: image_func
@@ -470,6 +476,7 @@ def get_showing_tags(layer='master'):
 
     return renpy.game.context().images.get_showing_tags(layer)
 
+
 def predict_show(name, layer=None, what=None, tag=None, at_list=[ ]):
     """
     :undocumented:
@@ -710,7 +717,7 @@ def scene(layer='master'):
         renpy.config.missing_scene(layer)
 
 
-def input(prompt, default='', allow=None, exclude='{}', length=None, with_none=None, pixel_width=None): #@ReservedAssignment
+def input(prompt, default='', allow=None, exclude='{}', length=None, with_none=None, pixel_width=None):  # @ReservedAssignment
     """
     :doc: input
 
@@ -750,7 +757,7 @@ def input(prompt, default='', allow=None, exclude='{}', length=None, with_none=N
     if roll_forward is not None:
         default = roll_forward
 
-    fixed = in_fixed_rollback();
+    fixed = in_fixed_rollback()
 
     if has_screen("input"):
         widget_properties = { }
@@ -809,7 +816,6 @@ def menu(items, set_expr):
         def substitute(s):
             return s
 
-
     # Filter the list of items to only include ones for which the
     # condition is true.
     items = [ (substitute(label), value)
@@ -818,12 +824,12 @@ def menu(items, set_expr):
 
     # Filter the list of items on the set_expr:
     if set_expr:
-        set = renpy.python.py_eval(set_expr) #@ReservedAssignment
+        set = renpy.python.py_eval(set_expr)  # @ReservedAssignment
         items = [ (label, value)
                   for label, value in items
                   if label not in set ]
     else:
-        set = None #@ReservedAssignment
+        set = None  # @ReservedAssignment
 
     # Check to see if there's at least one choice in set of items:
     choices = [ value for label, value in items if value is not None ]
@@ -866,7 +872,6 @@ def choice_for_skipping():
         renpy.loadsave.force_autosave(True)
 
 
-
 def predict_menu():
     """
     :undocumented:
@@ -908,7 +913,7 @@ def display_menu(items,
                  scope={ },
                  widget_properties=None,
                  screen="choice",
-                 type="menu", #@ReservedAssignment
+                 type="menu",  # @ReservedAssignment
                  predict_only=False,
                  **kwargs):
     """
@@ -1045,6 +1050,7 @@ def display_menu(items,
 
 
 class TagQuotingDict(object):
+
     def __getitem__(self, key):
 
         store = renpy.store.__dict__
@@ -1072,7 +1078,7 @@ def predict_say(who, what):
     """
 
     if who is None:
-        who = renpy.store.narrator # E1101 @UndefinedVariable
+        who = renpy.store.narrator  # E1101 @UndefinedVariable
 
     if isinstance(who, (str, unicode)):
         return renpy.store.predict_say(who, what)
@@ -1095,6 +1101,7 @@ def scry_say(who, scry):
     except:
         scry.interacts = True
 
+
 def say(who, what, interact=True):
     """
     :doc: se_say
@@ -1127,7 +1134,7 @@ def say(who, what, interact=True):
         what = what % tag_quoting_dict
 
     if who is None:
-        who = renpy.store.narrator # E1101 @UndefinedVariable
+        who = renpy.store.narrator  # E1101 @UndefinedVariable
 
     if isinstance(who, (str, unicode)):
         renpy.store.say(who, what, interact=interact)
@@ -1226,7 +1233,6 @@ def pause(delay=None, music=None, with_none=None, hard=False, checkpoint=None):
         a checkpoint will only be set if delay is set.
     """
 
-
     if checkpoint is None:
         if delay is not None:
             checkpoint = False
@@ -1372,7 +1378,7 @@ def with_statement(trans, always=False, paired=None, clear=True):
 globals()["with"] = with_statement
 
 
-def rollback(force=False, checkpoints=1, defer=False, greedy=True, label=None):
+def rollback(force=False, checkpoints=1, defer=False, greedy=True, label=None, abnormal=True):
     """
     :doc: rollback
 
@@ -1397,6 +1403,11 @@ def rollback(force=False, checkpoints=1, defer=False, greedy=True, label=None):
 
     `label`
         If not None, a label that is called when rollback completes.
+
+    `abnormal`
+        If true, the default, the code executed after the transition is run in
+        an abnormal mode that skips transitions that would have otherwise
+        occured.
     """
 
     if defer and len(renpy.game.contexts) > 1:
@@ -1416,7 +1427,7 @@ def rollback(force=False, checkpoints=1, defer=False, greedy=True, label=None):
 
     renpy.config.skipping = None
     renpy.game.log.complete()
-    renpy.game.log.rollback(checkpoints, greedy=greedy, label=label, force=(force is True))
+    renpy.game.log.rollback(checkpoints, greedy=greedy, label=label, force=(force is True), abnormal=abnormal)
 
 
 def toggle_fullscreen():
@@ -1434,6 +1445,7 @@ def toggle_music():
     Does nothing.
     """
 
+
 @renpy_pure
 def has_label(name):
     """
@@ -1448,6 +1460,7 @@ def has_label(name):
 
     return renpy.game.script.has_label(name)
 
+
 @renpy_pure
 def get_all_labels():
     """
@@ -1530,8 +1543,7 @@ def reload_script():
         utter_restart()
 
 
-
-def quit(relaunch=False, status=0): #@ReservedAssignment
+def quit(relaunch=False, status=0):  # @ReservedAssignment
     """
     :doc: other
 
@@ -1581,6 +1593,7 @@ def call(label, *args, **kwargs):
 
     raise renpy.game.CallException(label, args, kwargs)
 
+
 def return_statement():
     """
     :doc: se_call
@@ -1600,8 +1613,9 @@ def screenshot(filename):
 
     renpy.game.interface.save_screenshot(filename)
 
+
 @renpy_pure
-def version(tuple=False): #@ReservedAssignment
+def version(tuple=False):  # @ReservedAssignment
     """
     :doc: renpy_version
 
@@ -1621,7 +1635,8 @@ version_string = renpy.version
 version_only = renpy.version_only
 version_name = renpy.version_name
 version_tuple = renpy.version_tuple
-license = "" # @ReservedAssignment
+license = ""  # @ReservedAssignment
+
 
 def transition(trans, layer=None, always=False, force=False):
     """
@@ -1681,6 +1696,7 @@ def get_game_runtime():
 
     return renpy.game.contexts[0].runtime
 
+
 @renpy_pure
 def loadable(filename):
     """
@@ -1796,6 +1812,7 @@ def get_filename_line():
 # A file that log logs to.
 logfile = None
 
+
 def log(msg):
     """
     :doc: debug
@@ -1824,7 +1841,7 @@ def log(msg):
 
         import textwrap
 
-        print >>logfile, textwrap.fill(msg, renpy.config.log_width).encode("utf-8")
+        print(textwrap.fill(msg, renpy.config.log_width).encode("utf-8"), file=logfile)
         logfile.flush()
 
     except:
@@ -1871,7 +1888,7 @@ def last_interact_type():
     return getattr(renpy.game.context().info, "_last_interact_type", None)
 
 
-def dynamic(*vars): #@ReservedAssignment
+def dynamic(*vars):  # @ReservedAssignment
     """
     :doc: other
 
@@ -1887,7 +1904,7 @@ def dynamic(*vars): #@ReservedAssignment
     renpy.game.context().make_dynamic(vars)
 
 
-def context_dynamic(*vars): #@ReservedAssignment
+def context_dynamic(*vars):  # @ReservedAssignment
     """
     :doc: other
 
@@ -1943,7 +1960,7 @@ def seen_image(name):
     return name in renpy.game.persistent._seen_images  # @UndefinedVariable
 
 
-def file(fn): #@ReservedAssignment
+def file(fn):  # @ReservedAssignment
     """
     :doc: file
 
@@ -2028,6 +2045,7 @@ def free_memory():
     force_full_redraw()
     renpy.display.interface.kill_textures_and_surfaces()
 
+
 @renpy_pure
 def easy_displayable(d, none=False):
     """
@@ -2077,12 +2095,15 @@ def _error(msg):
 
 _error_handlers = [ _error ]
 
+
 def push_error_handler(eh):
     _error_handlers.append(eh)
 
+
 def pop_error_handler():
     _error_handlers.pop()
 
+
 def error(msg):
     _error_handlers[-1](msg)
 
@@ -2135,6 +2156,7 @@ def scry():
     node = renpy.game.script.lookup(name)
     return node.scry()
 
+
 @renpy_pure
 def munged_filename():
     return renpy.parser.munge_filename(get_filename_line()[0])
@@ -2144,6 +2166,7 @@ def munged_filename():
 
 loaded_modules = set()
 
+
 def load_module(name, **kwargs):
     """
     :doc: other
@@ -2177,9 +2200,9 @@ def load_module(name, **kwargs):
     renpy.game.contexts.append(context)
 
     context.make_dynamic(kwargs)
-    renpy.store.__dict__.update(kwargs) #@UndefinedVariable
+    renpy.store.__dict__.update(kwargs)  # @UndefinedVariable
 
-    for prio, node in initcode: #@UnusedVariable
+    for prio, node in initcode:  # @UnusedVariable
         renpy.game.context().run(node)
 
     context.pop_all_dynamic()
@@ -2217,7 +2240,7 @@ def load_string(s, filename="<string>"):
         context.init_phase = True
         renpy.game.contexts.append(context)
 
-        for prio, node in initcode: #@UnusedVariable
+        for prio, node in initcode:  # @UnusedVariable
             renpy.game.context().run(node)
 
         context.pop_all_dynamic()
@@ -2287,6 +2310,7 @@ def shown_window():
 
 
 class placement(renpy.python.RevertableObject):
+
     def __init__(self, p):
         super(placement, self).__init__()
 
@@ -2298,6 +2322,7 @@ class placement(renpy.python.RevertableObject):
         self.yoffset = p[5]
         self.subpixel = p[6]
 
+
 def get_placement(d):
     """
     :doc: image_func
@@ -2357,9 +2382,11 @@ render = renpy.display.render.render
 IgnoreEvent = renpy.display.core.IgnoreEvent
 redraw = renpy.display.render.redraw
 
+
 class Displayable(renpy.display.core.Displayable, renpy.python.RevertableObject):
     pass
 
+
 class Container(renpy.display.core.Displayable, renpy.python.RevertableObject):
     _list_type = renpy.python.RevertableList
 
@@ -2387,7 +2414,6 @@ def cache_pin(*args):
     renpy.store._cache_pin_set = new_pins | renpy.store._cache_pin_set
 
 
-
 def cache_unpin(*args):
     """
     :undocumented: Cache pin is deprecated.
@@ -2443,7 +2469,6 @@ def stop_predict(*args):
 
 
 def start_predict_screen(_screen_name, *args, **kwargs):
-
     """
     :doc: screens
 
@@ -2494,7 +2519,7 @@ def call_screen(_screen_name, *args, **kwargs):
 
     try:
         rv = renpy.ui.interact(mouse="screen", type="screen", roll_forward=roll_forward)
-    except (renpy.game.JumpException, renpy.game.CallException), e:
+    except (renpy.game.JumpException, renpy.game.CallException) as e:
         rv = e
 
     renpy.exports.checkpoint(rv)
@@ -2512,6 +2537,7 @@ def call_screen(_screen_name, *args, **kwargs):
 
     return rv
 
+
 @renpy_pure
 def list_files(common=False):
     """
@@ -2527,7 +2553,7 @@ def list_files(common=False):
 
     rv = [ ]
 
-    for dir, fn in renpy.loader.listdirfiles(common): #@ReservedAssignment
+    for dir, fn in renpy.loader.listdirfiles(common):  # @ReservedAssignment
         if fn.startswith("saves/"):
             continue
 
@@ -2601,6 +2627,7 @@ def mode(mode):
 
     modes.insert(0, mode)
 
+
 def get_mode():
     """
     :doc: modes
@@ -2617,6 +2644,7 @@ def get_mode():
 
     return modes[0]
 
+
 def notify(message):
     """
     :doc: other
@@ -2670,7 +2698,7 @@ def vibrate(duration):
     """
 
     try:
-        import android #@UnresolvedImport
+        import android  # @UnresolvedImport
         android.vibrate(duration)
     except:
         pass
@@ -2754,6 +2782,8 @@ def set_physical_size(size):
     if get_renderer_info()["resizable"]:
         renpy.display.draw.quit()
         renpy.display.interface.set_mode(size)
+        renpy.display.interface.last_resize = size
+
 
 def reset_physical_size():
     """
@@ -2803,7 +2833,7 @@ def fsdecode(s):
     return s.decode(fsencoding)
 
 
-from renpy.editor import launch_editor #@UnusedImport
+from renpy.editor import launch_editor  # @UnusedImport
 
 
 def get_image_load_log(age=None):
@@ -2832,7 +2862,6 @@ def get_image_load_log(age=None):
     else:
         deadline = 0
 
-
     for i in renpy.display.im.cache.load_log:
         if i[0] < deadline:
             break
@@ -2944,6 +2973,7 @@ def count_seen_dialogue_blocks():
 
     return renpy.game.seen_translates_count
 
+
 def count_newly_seen_dialogue_blocks():
     """
     :doc: other
@@ -2955,7 +2985,6 @@ def count_newly_seen_dialogue_blocks():
     return renpy.game.new_translates_count
 
 
-
 def substitute(s, scope=None, translate=True):
     """
     :doc: other
@@ -3011,6 +3040,7 @@ def get_return_stack():
 
     return renpy.game.context().get_return_stack()
 
+
 def set_return_stack(stack):
     """
     :doc: label
@@ -3024,6 +3054,7 @@ def set_return_stack(stack):
 
     renpy.game.context().set_return_stack(stack)
 
+
 def invoke_in_thread(fn, *args, **kwargs):
     """
     :doc: other
@@ -3049,6 +3080,7 @@ def invoke_in_thread(fn, *args, **kwargs):
     t.daemon = True
     t.start()
 
+
 def cancel_gesture():
     """
     :doc: gesture
@@ -3057,7 +3089,8 @@ def cancel_gesture():
     This should be called by displayables that have gesture-like behavior.
     """
 
-    renpy.display.gesture.recognizer.cancel() # @UndefinedVariable
+    renpy.display.gesture.recognizer.cancel()  # @UndefinedVariable
+
 
 def execute_default_statement(start=False):
     """
@@ -3069,6 +3102,7 @@ def execute_default_statement(start=False):
     for i in renpy.ast.default_statements:
         i.set_default(start)
 
+
 def write_log(s, *args):
     """
     :undocumented:
@@ -3078,6 +3112,7 @@ def write_log(s, *args):
 
     renpy.display.log.write(s, *args)
 
+
 def predicting():
     """
     :doc: screens
@@ -3087,6 +3122,7 @@ def predicting():
 
     return renpy.display.predict.predicting
 
+
 def get_line_log():
     """
     :undocumented:
@@ -3097,6 +3133,7 @@ def get_line_log():
 
     return renpy.game.context().line_log[:]
 
+
 def clear_line_log():
     """
     :undocumented:
@@ -3106,6 +3143,7 @@ def clear_line_log():
 
     renpy.game.context().line_log = [ ]
 
+
 def add_layer(layer, above=None, below=None, menu_clear=True):
     """
     :doc: other
@@ -3157,7 +3195,7 @@ def add_layer(layer, above=None, below=None, menu_clear=True):
     layers.insert(index, layer)
 
     if menu_clear:
-        renpy.config.menu_clear_layers.append(layer) # @UndefinedVariable
+        renpy.config.menu_clear_layers.append(layer)  # @UndefinedVariable
 
 
 def maximum_framerate(t):
@@ -3270,6 +3308,7 @@ def get_identifier_checkpoints(identifier):
 
     return renpy.game.log.get_identifier_checkpoints(identifier)
 
+
 def get_adjustment(bar_value):
     """
     :doc: other
diff --git a/renpy/game.py b/renpy/game.py
index d64d38a..784ea33 100644
--- a/renpy/game.py
+++ b/renpy/game.py
@@ -93,6 +93,7 @@ persistent = None
 # The current preferences.
 preferences = None
 
+
 class ExceptionInfo(object):
     """
     Context manager that sets exception_info iff an exception occurs.
@@ -116,6 +117,7 @@ class ExceptionInfo(object):
 
         return False
 
+
 class RestartContext(Exception):
     """
     Restarts the current context. If `label` is given, calls that label
@@ -125,6 +127,7 @@ class RestartContext(Exception):
     def __init__(self, label):
         self.label = label
 
+
 class RestartTopContext(Exception):
     """
     Restarts the top context. If `label` is given, calls that label
@@ -134,21 +137,24 @@ class RestartTopContext(Exception):
     def __init__(self, label):
         self.label = label
 
+
 class FullRestartException(Exception):
     """
     An exception of this type forces a hard restart, completely
     destroying the store and config and so on.
     """
 
-    def __init__(self, reason="end_game"): # W0231
+    def __init__(self, reason="end_game"):  # W0231
         self.reason = reason
 
+
 class UtterRestartException(Exception):
     """
     An exception of this type forces an even harder restart, causing
     Ren'Py and the script to be reloaded.
     """
 
+
 class QuitException(Exception):
     """
     An exception of this class will let us force a safe quit, from
@@ -167,6 +173,7 @@ class QuitException(Exception):
         self.relaunch = relaunch
         self.status = status
 
+
 class JumpException(Exception):
     """
     This should be raised with a label as the only argument. This causes
@@ -174,12 +181,14 @@ class JumpException(Exception):
     to the named label.
     """
 
+
 class JumpOutException(Exception):
     """
     This should be raised with a label as the only argument. This exits
     the current context, and then raises a JumpException.
     """
 
+
 class CallException(Exception):
     """
     Raise this exception to cause the current statement to terminate,
@@ -196,12 +205,14 @@ class CallException(Exception):
     def __reduce__(self):
         return (CallException, (self.label, self.args, self.kwargs))
 
+
 class EndReplay(Exception):
     """
     Raise this exception to end the current replay (the current call to
     call_replay).
     """
 
+
 class ParseErrorException(Exception):
     """
     This is raised when a parse error occurs, after it has been
@@ -233,7 +244,8 @@ def context(index=-1):
 
     return contexts[index]
 
-def invoke_in_new_context(callable, *args, **kwargs): #@ReservedAssignment
+
+def invoke_in_new_context(callable, *args, **kwargs):  # @ReservedAssignment
     """
     :doc: label
 
@@ -267,12 +279,15 @@ def invoke_in_new_context(callable, *args, **kwargs): #@ReservedAssignment
 
         return callable(*args, **kwargs)
 
-    except renpy.game.JumpOutException, e:
+    except renpy.game.JumpOutException as e:
 
+        contexts[-2].force_checkpoint = True
         raise renpy.game.JumpException(e.args[0])
 
     finally:
 
+        context.pop_all_dynamic()
+
         contexts.pop()
         contexts[-1].do_deferred_rollback()
 
@@ -280,7 +295,6 @@ def invoke_in_new_context(callable, *args, **kwargs): #@ReservedAssignment
             contexts[-1].scene_lists.focused = None
 
 
-
 def call_in_new_context(label, *args, **kwargs):
     """
     :doc: label
@@ -315,8 +329,8 @@ def call_in_new_context(label, *args, **kwargs):
         context.goto_label(label)
         return renpy.execution.run_context(False)
 
-    except renpy.game.JumpOutException, e:
-
+    except renpy.game.JumpOutException as e:
+        contexts[-2].force_checkpoint = True
         raise renpy.game.JumpException(e.args[0])
 
     finally:
@@ -327,6 +341,7 @@ def call_in_new_context(label, *args, **kwargs):
         if interface and interface.restart_interaction and contexts:
             contexts[-1].scene_lists.focused = None
 
+
 def call_replay(label, scope={}):
     """
     :doc: replay
@@ -368,6 +383,9 @@ def call_replay(label, scope={}):
         pass
 
     finally:
+
+        context.pop_all_dynamic()
+
         contexts.pop()
         renpy.game.log = old_log
         sb.restore()
diff --git a/renpy/gl/gldraw.pyx b/renpy/gl/gldraw.pyx
index 46cf2db..7d4af06 100644
--- a/renpy/gl/gldraw.pyx
+++ b/renpy/gl/gldraw.pyx
@@ -979,7 +979,7 @@ cdef class GLDraw:
             # Non-aligned clipping uses RTT.
             if reverse.ydx != 0 or reverse.xdy != 0:
                 tex = what.render_to_texture(True)
-                self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse, nearest, subpixel)
+                self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse * self.draw_to_virt, nearest, subpixel)
                 return 0
 
             minx, miny, maxx, maxy = clip
diff --git a/renpy/lint.py b/renpy/lint.py
index cd900ea..51c8cb4 100644
--- a/renpy/lint.py
+++ b/renpy/lint.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
 import renpy.display
 import renpy.text
 import codecs
@@ -51,6 +52,8 @@ image_prefixes = None
 report_node = None
 
 # Reports a message to the user.
+
+
 def report(msg, *args):
     if report_node:
         out = u"%s:%d " % (renpy.parser.unicode_filename(report_node.filename), report_node.linenumber)
@@ -58,17 +61,19 @@ def report(msg, *args):
         out = ""
 
     out += msg % args
-    print
-    print out.encode('utf-8')
+    print()
+    print(out.encode('utf-8'))
 
 added = { }
 
 # Reports additional information about a message, the first time it
 # occurs.
+
+
 def add(msg):
     if not msg in added:
         added[msg] = True
-        print unicode(msg).encode('utf-8')
+        print(unicode(msg).encode('utf-8'))
 
 
 # Trys to evaluate an expression, announcing an error if it fails.
@@ -90,12 +95,14 @@ def try_eval(where, expr, additional=None):
     if m.group(1) in __builtins__:
         return
 
-    report( "Could not evaluate '%s', in %s.", expr, where)
+    report("Could not evaluate '%s', in %s.", expr, where)
     if additional:
         add(additional)
 
 # Returns True of the expression can be compiled as python, False
 # otherwise.
+
+
 def try_compile(where, expr, additional=None):
 
     try:
@@ -109,6 +116,7 @@ def try_compile(where, expr, additional=None):
 # The sets of names + attributes that we know are valid.
 imprecise_cache = set()
 
+
 def image_exists_imprecise(name):
     """
     Returns true if the image is a plausible image that can be used in a show
@@ -116,7 +124,6 @@ def image_exists_imprecise(name):
     tag and containing all of the attributes (and none of the removed attributes).
     """
 
-
     if name in imprecise_cache:
         return True
 
@@ -152,6 +159,7 @@ def image_exists_imprecise(name):
 
 precise_cache = set()
 
+
 def image_exists_precise(name):
     """
     Returns true if an image exists with the same tag and attributes as
@@ -217,6 +225,7 @@ def image_exists(name, expression, tag, precise=True):
 # Only check each file once.
 check_file_cache = { }
 
+
 def check_file(what, fn):
 
     present = check_file_cache.get(fn, None)
@@ -245,7 +254,7 @@ def check_displayable(what, d):
 
     try:
         if isinstance(d, renpy.display.core.Displayable):
-            d.visit_all(lambda a : a.predict_one())
+            d.visit_all(lambda a: a.predict_one())
     except:
         pass
 
@@ -260,6 +269,7 @@ def check_image(node):
 
     check_displayable('image %s' % name, renpy.display.image.images[node.imgname])
 
+
 def imspec(t):
     if len(t) == 3:
         return t[0], None, None, t[1], t[2], 0
@@ -318,6 +328,7 @@ def check_hide(node):
 def check_with(node):
     try_eval("a with statement or clause", node.expr, "Perhaps you forgot to declare, or misspelled, a transition?")
 
+
 def check_user(node):
 
     def error(msg):
@@ -334,6 +345,7 @@ def check_user(node):
     except:
         report("Didn't properly report what the next statement should be.")
 
+
 def text_checks(s):
     msg = renpy.text.extras.check_text_tags(s)
     if msg:
@@ -376,6 +388,7 @@ def text_checks(s):
         if state != 0:
             report("Unterminated string format code '%s' (in %s)", fmt, repr(s)[1:])
 
+
 def check_say(node):
 
     if node.who:
@@ -432,6 +445,7 @@ def check_menu(node):
 
         text_checks(l)
 
+
 def check_jump(node):
 
     if node.expression:
@@ -440,6 +454,7 @@ def check_jump(node):
     if not renpy.game.script.has_label(node.target):
         report("The jump is to nonexistent label '%s'.", node.target)
 
+
 def check_call(node):
 
     if node.expression:
@@ -448,14 +463,17 @@ def check_call(node):
     if not renpy.game.script.has_label(node.label):
         report("The call is to nonexistent label '%s'.", node.label)
 
+
 def check_while(node):
     try_compile("in the condition of the while statement", node.condition)
 
+
 def check_if(node):
 
     for condition, _block in node.entries:
         try_compile("in a condition of the if statement", condition)
 
+
 def check_define(node, kind):
     if node.store != 'store':
         return
@@ -482,7 +500,7 @@ def check_style_property_displayable(name, property, d):
 
     def sort_short(l):
         l = list(l)
-        l.sort(key=lambda a : len(a))
+        l.sort(key=lambda a: len(a))
         return l
 
     alts = sort_short(renpy.style.prefix_alts)
@@ -507,15 +525,20 @@ def check_style(name, s):
 
     for p in s.properties:
         for k, v in p.iteritems():
-
+            
             # Treat font specially.
             if k.endswith("font"):
-                check_file(name, v)
+                if isinstance(v, renpy.text.font.FontGroup):
+                    for f in v.fonts:
+                        check_file(name, f)
+                else:
+                    check_file(name, v)
 
             if isinstance(v, renpy.display.core.Displayable):
                 check_style_property_displayable(name, k, v)
 #                check_displayable(kname, v)
 
+
 def check_label(node):
 
     def add_arg(n):
@@ -536,13 +559,14 @@ def check_label(node):
 
 
 def check_styles():
-    for full_name, s in renpy.style.styles.iteritems(): # @UndefinedVariable
+    for full_name, s in renpy.style.styles.iteritems():  # @UndefinedVariable
         name = "style." + full_name[0]
         for i in full_name[1:]:
             name += "[{!r}]".format(i)
 
         check_style("Style " + name, s)
 
+
 def humanize(n):
     s = str(n)
 
@@ -556,6 +580,7 @@ def humanize(n):
 
     return ''.join(rv)
 
+
 def check_filename_encodings():
     """
     Checks files to ensure that they are displayable in unicode.
@@ -571,6 +596,7 @@ def check_filename_encodings():
         report("%s contains non-ASCII characters in its filename.", filename)
         add("(ZIP file distributions can only reliably include ASCII filenames.)")
 
+
 class Count(object):
     """
     Stores information about the word count.
@@ -591,6 +617,7 @@ class Count(object):
         self.words += len(s.split())
         self.characters += len(s)
 
+
 def common(n):
     """
     Returns true if the node is in the common directory.
@@ -603,6 +630,7 @@ def common(n):
     else:
         return False
 
+
 def lint():
     """
     The master lint function, that's responsible for staging all of the
@@ -620,8 +648,8 @@ def lint():
 
     renpy.game.lint = True
 
-    print codecs.BOM_UTF8
-    print unicode(renpy.version + " lint report, generated at: " + time.ctime()).encode("utf-8")
+    print(codecs.BOM_UTF8)
+    print(unicode(renpy.version + " lint report, generated at: " + time.ctime()).encode("utf-8"))
 
     # This supports check_hide.
     global image_prefixes
@@ -680,7 +708,6 @@ def lint():
 
             counts[language].add(node.what)
 
-
         elif isinstance(node, renpy.ast.Menu):
             check_menu(node)
             menu_count += 1
@@ -718,8 +745,6 @@ def lint():
         elif isinstance(node, renpy.ast.Default):
             check_define(node, "default")
 
-
-
     report_node = None
 
     check_styles()
@@ -728,7 +753,6 @@ def lint():
     for f in renpy.config.lint_hooks:
         f()
 
-
     lines = [ ]
 
     def report_language(language):
@@ -754,11 +778,10 @@ characters per block. """.format(
 
         lines.append(s)
 
-
-    print
-    print
-    print "Statistics:"
-    print
+    print()
+    print()
+    print("Statistics:")
+    print()
 
     languages = list(counts)
     languages.sort()
@@ -770,17 +793,16 @@ characters per block. """.format(
 
     for l in lines:
         for ll in textwrap.wrap(l, 78):
-            print ll.encode("utf-8")
+            print(ll.encode("utf-8"))
 
-        print
+        print()
 
-    print
-    if renpy.config.developer and (renpy.config.developer != "auto"):
-        print "Remember to set config.developer to False before releasing."
-        print
+    print()
+    if renpy.config.developer and (renpy.config.original_developer != "auto"):
+        print("Remember to set config.developer to False before releasing.")
+        print()
 
-    print "Lint is not a substitute for thorough testing. Remember to update Ren'Py"
-    print "before releasing. New releases fix bugs and improve compatibility."
+    print("Lint is not a substitute for thorough testing. Remember to update Ren'Py")
+    print("before releasing. New releases fix bugs and improve compatibility.")
 
     return False
-
diff --git a/renpy/loader.py b/renpy/loader.py
index 9492d77..c157447 100644
--- a/renpy/loader.py
+++ b/renpy/loader.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
 import renpy
 import os.path
 from pickle import loads
@@ -34,7 +35,7 @@ import re
 u"".encode("utf-8")
 
 
-################################################################# Physical Paths
+# Physical Paths
 
 def get_path(fn):
     """
@@ -55,14 +56,14 @@ def get_path(fn):
 
     return fn
 
-################################################################## Asset Loading
+# Asset Loading
 
 try:
     import android.apk
 
     expansion = os.environ.get("ANDROID_EXPANSION", None)
     if expansion is not None:
-        print "Using expansion file", expansion
+        print("Using expansion file", expansion)
 
         apks = [
             android.apk.APK(apk=expansion, prefix='assets/x-game/'),
@@ -72,7 +73,7 @@ try:
         game_apks = [ apks[0] ]
 
     else:
-        print "Not using expansion file."
+        print("Not using expansion file.")
 
         apks = [
             android.apk.APK(prefix='assets/x-game/'),
@@ -96,6 +97,7 @@ old_config_archives = None
 # A map from lower-case filename to regular-case filename.
 lower_map = { }
 
+
 def index_archives():
     """
     Loads in the indexes for the archive files. Also updates the lower_map.
@@ -164,10 +166,11 @@ def index_archives():
         except:
             raise
 
-    for dir, fn in listdirfiles(): #@ReservedAssignment
+    for dir, fn in listdirfiles():  # @ReservedAssignment
         lower_map[fn.lower()] = fn
 
-def walkdir(dir): #@ReservedAssignment
+
+def walkdir(dir):  # @ReservedAssignment
     rv = [ ]
 
     if not os.path.exists(dir) and not renpy.config.developer:
@@ -192,6 +195,7 @@ game_files = [ ]
 # A list of files that are in the common directory.
 common_files = [ ]
 
+
 def cleardirfiles():
     """
     Clears the lists above when the game has changed.
@@ -203,6 +207,7 @@ def cleardirfiles():
     game_files = [ ]
     common_files = [ ]
 
+
 def scandirfiles():
     """
     Scans directories, archives, and apks and fills out game_files and
@@ -228,9 +233,9 @@ def scandirfiles():
     for apk in apks:
 
         if apk not in game_apks:
-            files = common_files # @UnusedVariable
+            files = common_files  # @UnusedVariable
         else:
-            files = game_files # @UnusedVariable
+            files = game_files  # @UnusedVariable
 
         for f in apk.list():
 
@@ -243,9 +248,9 @@ def scandirfiles():
     for i in renpy.config.searchpath:
 
         if (renpy.config.commondir) and (i == renpy.config.commondir):
-            files = common_files # @UnusedVariable
+            files = common_files  # @UnusedVariable
         else:
-            files = game_files # @UnusedVariable
+            files = game_files  # @UnusedVariable
 
         i = os.path.join(renpy.config.basedir, i)
         for j in walkdir(i):
@@ -258,7 +263,6 @@ def scandirfiles():
             add(None, j)
 
 
-
 def listdirfiles(common=True):
     """
     Returns a list of directory, file tuples known to the system. If
@@ -381,7 +385,7 @@ class SubFile(object):
     def __iter__(self):
         return self
 
-    def next(self): #@ReservedAssignment
+    def next(self):  # @ReservedAssignment
         rv = self.readline()
 
         if not rv:
@@ -438,6 +442,7 @@ if "RENPY_FORCE_SUBFILE" in os.environ:
 
         return SubFile(f, 0, length, '')
 
+
 def load_core(name):
     """
     Returns an open python file object of the given type.
@@ -503,6 +508,7 @@ def load_core(name):
 
     return None
 
+
 def get_prefixes():
     """
     Returns a list of prefixes to search for files.
@@ -521,6 +527,7 @@ def get_prefixes():
 
     return rv
 
+
 def load(name):
 
     if renpy.config.reject_backslash and "\\" in name:
@@ -538,6 +545,7 @@ def load(name):
 
 loadable_cache = { }
 
+
 def loadable_core(name):
     """
     Returns True if the name is loadable with load, False if it is not.
@@ -568,6 +576,7 @@ def loadable_core(name):
     loadable_cache[name] = False
     return False
 
+
 def loadable(name):
 
     name = name.lstrip('/')
@@ -608,6 +617,7 @@ def transfn(name):
 
 hash_cache = dict()
 
+
 def get_hash(name):
     """
     Returns the time the file m was last modified, or 0 if it
@@ -639,7 +649,7 @@ def get_hash(name):
     return rv
 
 
-################################################################# Module Loading
+# Module Loading
 
 class RenpyImporter(object):
     """
@@ -696,22 +706,26 @@ class RenpyImporter(object):
         source = source.encode("raw_unicode_escape")
 
         source = source.replace("\r", "")
-        code = compile(source, filename, 'exec')
+
+        code = compile(source, filename, 'exec', renpy.python.old_compile_flags, 1)
         exec code in mod.__dict__
+
         return mod
 
     def get_data(self, filename):
         return load(filename).read()
 
+
 def init_importer():
     sys.meta_path.insert(0, RenpyImporter("python-packages/"))
     sys.meta_path.insert(0, RenpyImporter())
 
+
 def quit_importer():
     sys.meta_path.pop(0)
     sys.meta_path.pop(0)
 
-#################################################################### Auto-Reload
+# Auto-Reload
 
 # This is set to True if autoreload hads detected an autoreload is needed.
 needs_autoreload = False
@@ -731,6 +745,7 @@ auto_lock = threading.Condition()
 # Used to indicate that this file is blacklisted.
 auto_blacklisted = renpy.object.Sentinel("auto_blacklisted")
 
+
 def auto_mtime(fn):
     """
     Gets the mtime of fn, or None if the file does not exist.
@@ -741,6 +756,7 @@ def auto_mtime(fn):
     except:
         return None
 
+
 def add_auto(fn, force=False):
     """
     Adds fn as a file we watch for changes. If it's mtime changes or the file
@@ -764,6 +780,7 @@ def add_auto(fn, force=False):
     with auto_lock:
         auto_mtimes[fn] = mtime
 
+
 def auto_thread_function():
     """
     This thread sets need_autoreload when necessary.
@@ -793,6 +810,7 @@ def auto_thread_function():
                     if auto_mtime(fn) != auto_mtimes[fn]:
                         needs_autoreload = True
 
+
 def auto_init():
     """
     Starts the autoreload thread.
@@ -813,6 +831,7 @@ def auto_init():
     auto_thread.daemon = True
     auto_thread.start()
 
+
 def auto_quit():
     """
     Terminates the autoreload thread.
diff --git a/renpy/loadsave.py b/renpy/loadsave.py
index a1525fa..5763c58 100644
--- a/renpy/loadsave.py
+++ b/renpy/loadsave.py
@@ -38,18 +38,22 @@ import renpy
 from json import dumps as json_dumps
 
 # Dump that chooses which pickle to use:
+
+
 def dump(o, f):
     if renpy.config.use_cpickle:
         cPickle.dump(o, f, cPickle.HIGHEST_PROTOCOL)
     else:
         pickle.dump(o, f, pickle.HIGHEST_PROTOCOL)
 
+
 def dumps(o):
     if renpy.config.use_cpickle:
         return cPickle.dumps(o, cPickle.HIGHEST_PROTOCOL)
     else:
         return pickle.dumps(o, pickle.HIGHEST_PROTOCOL)
 
+
 def loads(s):
     if renpy.config.use_cpickle:
         return cPickle.loads(s)
@@ -60,6 +64,7 @@ def loads(s):
 # files.
 savegame_suffix = renpy.savegame_suffix
 
+
 def save_dump(roots, log):
     """
     Dumps information about the save to save_dump.txt. We dump the size
@@ -69,7 +74,6 @@ def save_dump(roots, log):
 
     o_repr_cache = { }
 
-
     def visit(o, path):
         ido = id(o)
 
@@ -101,7 +105,6 @@ def save_dump(roots, log):
         else:
             o_repr = "BAD TYPE <{0}>".format(type(o).__name__)
 
-
         o_repr_cache[ido] = o_repr
 
         if isinstance(o, (int, float, types.NoneType, types.ModuleType, types.ClassType)):
@@ -167,7 +170,6 @@ def save_dump(roots, log):
                 size += 2
                 size += visit(v, "{0}[{1!r}]".format(path, k))
 
-
         f.write("{0: 7d} {1} = {2}\n".format(size, path, o_repr_cache[ido]))
 
         return size
@@ -185,9 +187,12 @@ def save_dump(roots, log):
 
 # Used to indicate an aborted save, due to the game being mutated
 # while the save is in progress.
+
+
 class SaveAbort(Exception):
     pass
 
+
 def safe_rename(old, new):
     """
     Safely rename old to new.
@@ -198,6 +203,7 @@ def safe_rename(old, new):
 
     os.rename(old, new)
 
+
 class SaveRecord(object):
     """
     This is passed to the save locations. It contains the information that
@@ -250,7 +256,6 @@ class SaveRecord(object):
         self.first_filename = filename
 
 
-
 def save(slotname, extra_info='', mutate_flag=False):
     """
     :doc: loadsave
@@ -299,7 +304,6 @@ def save(slotname, extra_info='', mutate_flag=False):
     clear_slot(slotname)
 
 
-
 # Flag that lets us know if an autosave is in progress.
 autosave_not_running = threading.Event()
 autosave_not_running.set()
@@ -307,6 +311,7 @@ autosave_not_running.set()
 # The number of times autosave has been called without a save occuring.
 autosave_counter = 0
 
+
 def autosave_thread(take_screenshot):
 
     global autosave_counter
@@ -335,7 +340,6 @@ def autosave_thread(take_screenshot):
         autosave_not_running.set()
 
 
-
 def autosave():
     global autosave_counter
 
@@ -375,7 +379,6 @@ def force_autosave(take_screenshot=False):
         screenshot will be used.
     """
 
-
     # That is, autosave is running.
     if not autosave_not_running.isSet():
         return
@@ -496,6 +499,7 @@ def list_slots(regexp=None):
 # A cache for newest slot info.
 newest_slot_cache = { }
 
+
 def newest_slot(regexp=None):
     """
     :doc: loadsave
@@ -540,6 +544,7 @@ def slot_mtime(slotname):
 
     return get_cache(slotname).get_mtime()
 
+
 def slot_json(slotname):
     """
     :doc: loadsave
@@ -550,6 +555,7 @@ def slot_json(slotname):
 
     return get_cache(slotname).get_json()
 
+
 def slot_screenshot(slotname):
     """
     :doc: loadsave
@@ -560,6 +566,7 @@ def slot_screenshot(slotname):
 
     return get_cache(slotname).get_screenshot()
 
+
 def can_load(filename, test=False):
     """
     :doc: loadsave
@@ -574,6 +581,7 @@ def can_load(filename, test=False):
     else:
         return False
 
+
 def load(filename):
     """
     :doc: loadsave
@@ -585,6 +593,7 @@ def load(filename):
     roots, log = loads(location.load(filename))
     log.unfreeze(roots, label="_after_load")
 
+
 def unlink_save(filename):
     """
     :doc: loadsave
@@ -609,6 +618,7 @@ def rename_save(old, new):
     clear_slot(old)
     clear_slot(new)
 
+
 def copy_save(old, new):
     """
     :doc: loadsave
@@ -642,6 +652,7 @@ def cycle_saves(name, count):
 # None is a possible value for some of the attributes.
 unknown = renpy.object.Sentinel("unknown")
 
+
 class Cache(object):
     """
     This represents cached information about a save slot.
@@ -692,6 +703,7 @@ class Cache(object):
 # data until the slot changes.
 cache = { }
 
+
 def get_cache(slotname):
 
     rv = cache.get(slotname, None)
@@ -713,6 +725,7 @@ def clear_slot(slotname):
 
     renpy.exports.restart_interaction()
 
+
 def clear_cache():
     """
     Clears the entire cache.
@@ -732,6 +745,3 @@ location = None
 
 if False:
     location = renpy.savelocation.FileLocation("blah")
-
-
-
diff --git a/renpy/log.py b/renpy/log.py
index b1b87c0..5f21e09 100644
--- a/renpy/log.py
+++ b/renpy/log.py
@@ -21,6 +21,7 @@
 
 # This module handles the logging of messages to a file.
 
+from __future__ import print_function
 import os.path
 import codecs
 import traceback
@@ -34,6 +35,7 @@ import sys
 # The file events are logged to.
 log_file = None
 
+
 class LogFile(object):
     """
     This manages one of our logfiles.
@@ -68,11 +70,14 @@ class LogFile(object):
         if renpy.ios:
             self.file = sys.stdout
 
-    def open(self): #@ReservedAssignment
+    def open(self):  # @ReservedAssignment
 
         if self.file:
             return True
 
+        if renpy.macapp:
+            return False
+
         if self.developer and not renpy.config.developer:
             return False
 
@@ -86,7 +91,7 @@ class LogFile(object):
             altfn = os.path.join(tempfile.gettempdir(), "renpy-" + self.name + ".txt")
 
             if renpy.android:
-                print "Logging to", fn
+                print("Logging to", fn)
 
             if self.append:
                 mode = "a"
@@ -152,7 +157,8 @@ class LogFile(object):
 # A map from the log name to a log object.
 log_cache = { }
 
-def open(name, append=False, developer=False, flush=False): #@ReservedAssignment
+
+def open(name, append=False, developer=False, flush=False):  # @ReservedAssignment
     rv = log_cache.get(name, None)
 
     if rv is None:
diff --git a/renpy/main.py b/renpy/main.py
index 825377b..13e727c 100644
--- a/renpy/main.py
+++ b/renpy/main.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
 import renpy.display
 import renpy.style
 import renpy.sl2
@@ -34,6 +35,7 @@ import __main__
 
 last_clock = time.time()
 
+
 def log_clock(s):
     global last_clock
     now = time.time()
@@ -41,10 +43,11 @@ def log_clock(s):
 
     renpy.display.log.write(s)
     if renpy.android and not renpy.config.log_to_stdout:
-        print s
+        print(s)
 
     last_clock = now
 
+
 def reset_clock():
     global last_clock
     last_clock = time.time()
@@ -67,7 +70,7 @@ def run(restart):
     log_clock("Init translation")
 
     # Rebuild the various style caches.
-    renpy.style.build_styles() # @UndefinedVariable
+    renpy.style.build_styles()  # @UndefinedVariable
     log_clock("Build styles")
 
     renpy.sl2.slast.load_cache()
@@ -153,6 +156,7 @@ def load_rpe(fn):
     sys.path.insert(0, fn)
     exec autorun in dict()
 
+
 def choose_variants():
 
     if "RENPY_VARIANT" in os.environ:
@@ -161,18 +165,17 @@ def choose_variants():
 
     renpy.config.variants = [ None ]
 
-    if renpy.android: #@UndefinedVariable
+    if renpy.android:  # @UndefinedVariable
 
         renpy.config.variants.insert(0, 'mobile')
         renpy.config.variants.insert(0, 'android')
 
-        import android #@UnresolvedImport
+        import android  # @UnresolvedImport
         import math
         import pygame_sdl2 as pygame
 
         from jnius import autoclass  # @UnresolvedImport
 
-
         # Manufacturer/Model-specific variants.
         try:
             Build = autoclass("android.os.Build")
@@ -180,10 +183,10 @@ def choose_variants():
             manufacturer = Build.MANUFACTURER
             model = Build.MODEL
 
-            print "Manufacturer", manufacturer, "model", model
+            print("Manufacturer", manufacturer, "model", model)
 
             if manufacturer == "Amazon" and model.startswith("AFT"):
-                print "Running on a Fire TV."
+                print("Running on a Fire TV.")
                 renpy.config.variants.insert(0, "firetv")
         except:
             pass
@@ -192,7 +195,7 @@ def choose_variants():
         package_manager = android.activity.getPackageManager()
 
         if package_manager.hasSystemFeature("android.hardware.type.television"):
-            print "Running on a television."
+            print("Running on a television.")
             renpy.config.variants.insert(0, "tv")
             renpy.config.variants.insert(0, "small")
             return
@@ -204,7 +207,7 @@ def choose_variants():
 
         info = renpy.display.get_info()
         diag = math.hypot(info.current_w, info.current_h) / android.get_dpi()
-        print "Screen diagonal is", diag, "inches."
+        print("Screen diagonal is", diag, "inches.")
 
         if diag >= 6:
             renpy.config.variants.insert(0, 'tablet')
@@ -217,12 +220,12 @@ def choose_variants():
         renpy.config.variants.insert(0, 'ios')
         renpy.config.variants.insert(0, 'touch')
 
-        from pyobjus import autoclass # @UnresolvedImport @Reimport
+        from pyobjus import autoclass  # @UnresolvedImport @Reimport
         UIDevice = autoclass("UIDevice")
 
         idiom = UIDevice.currentDevice().userInterfaceIdiom
 
-        print "iOS device idiom", idiom
+        print("iOS device idiom", idiom)
 
         # idiom 0 is iPhone, 1 is iPad. We assume any bigger idiom will
         # be tablet-like.
@@ -238,7 +241,6 @@ def choose_variants():
         renpy.config.variants.insert(0, 'large')
 
 
-
 def main():
 
     log_clock("Bootstrap to the start of init.init")
@@ -265,7 +267,7 @@ def main():
     renpy.config.searchpath = [ renpy.config.gamedir ]
 
     # Find the common directory.
-    commondir = __main__.path_to_common(renpy.config.renpy_base) # E1101 @UndefinedVariable
+    commondir = __main__.path_to_common(renpy.config.renpy_base)  # E1101 @UndefinedVariable
 
     if os.path.isdir(commondir):
         renpy.config.searchpath.append(commondir)
@@ -278,12 +280,11 @@ def main():
         renpy.config.commondir = None
 
     # Load Ren'Py extensions.
-    for dir in renpy.config.searchpath: #@ReservedAssignment
+    for dir in renpy.config.searchpath:  # @ReservedAssignment
         for fn in os.listdir(dir):
             if fn.lower().endswith(".rpe"):
                 load_rpe(dir + "/" + fn)
 
-
     # The basename is the final component of the path to the gamedir.
     for i in sorted(os.listdir(renpy.config.gamedir)):
 
@@ -310,7 +311,7 @@ def main():
     renpy.store.store = sys.modules['store']
 
     # Set up styles.
-    game.style = renpy.style.StyleManager() # @UndefinedVariable
+    game.style = renpy.style.StyleManager()  # @UndefinedVariable
     renpy.store.style = game.style
 
     # Run init code in its own context. (Don't log.)
@@ -328,14 +329,19 @@ def main():
 
     # Set up error handling.
     renpy.exports.load_module("_errorhandling")
-    renpy.style.build_styles() # @UndefinedVariable
+
+    if renpy.exports.loadable("tl/None/common.rpym") or renpy.exports.loadable("tl/None/common.rpymc"):
+        renpy.exports.load_module("tl/None/common")
+
+    renpy.config.init_system_styles()
+    renpy.style.build_styles()  # @UndefinedVariable
 
     log_clock("Loading error handling")
 
     # If recompiling everything, remove orphan .rpyc files.
     # Otherwise, will fail in case orphan .rpyc have same
     # labels as in other scripts (usually happens on script rename).
-    if (renpy.game.args.command == 'compile') and not (renpy.game.args.keep_orphan_rpyc): # @UndefinedVariable
+    if (renpy.game.args.command == 'compile') and not (renpy.game.args.keep_orphan_rpyc):  # @UndefinedVariable
 
         for (fn, _dir) in renpy.game.script.script_files:
 
@@ -355,10 +361,10 @@ def main():
         renpy.game.script.scan_script_files()
 
     # Load all .rpy files.
-    renpy.game.script.load_script() # sets renpy.game.script.
+    renpy.game.script.load_script()  # sets renpy.game.script.
     log_clock("Loading script")
 
-    if renpy.game.args.command == 'load-test': # @UndefinedVariable
+    if renpy.game.args.command == 'load-test':  # @UndefinedVariable
         start = time.time()
 
         for i in range(5):
@@ -366,17 +372,17 @@ def main():
             renpy.game.script = renpy.script.Script()
             renpy.game.script.load_script()
 
-        print time.time() - start
+        print(time.time() - start)
         sys.exit(0)
 
     renpy.game.exception_info = 'After loading the script.'
 
     # Find the save directory.
     if renpy.config.savedir is None:
-        renpy.config.savedir = __main__.path_to_saves(renpy.config.gamedir) # E1101 @UndefinedVariable
+        renpy.config.savedir = __main__.path_to_saves(renpy.config.gamedir)  # E1101 @UndefinedVariable
 
-    if renpy.game.args.savedir: #@UndefinedVariable
-        renpy.config.savedir = renpy.game.args.savedir #@UndefinedVariable
+    if renpy.game.args.savedir:  # @UndefinedVariable
+        renpy.config.savedir = renpy.game.args.savedir  # @UndefinedVariable
 
     # Init preferences.
     game.persistent = renpy.persistent.init()
@@ -393,6 +399,7 @@ def main():
 
         # Load persistent data from all save locations.
         renpy.persistent.update()
+        game.preferences = game.persistent._preferences
         log_clock("Loading persistent")
 
         # Clear the list of seen statements in this game.
@@ -414,15 +421,17 @@ def main():
         renpy.game.exception_info = 'After initialization, but before game start.'
 
         # Check if we should simulate android.
-        renpy.android = renpy.android or renpy.config.simulate_android #@UndefinedVariable
+        renpy.android = renpy.android or renpy.config.simulate_android  # @UndefinedVariable
 
         # Run the post init code, if any.
         for i in renpy.game.post_init:
             i()
 
+        renpy.game.script.report_duplicate_labels()
+
         game.persistent._virtual_size = renpy.config.screen_width, renpy.config.screen_height
 
-        for i in renpy.game.persistent._seen_translates: # @UndefinedVariable
+        for i in renpy.game.persistent._seen_translates:  # @UndefinedVariable
             if i in renpy.game.script.translator.default_translates:
                 renpy.game.seen_translates_count += 1
 
@@ -500,4 +509,3 @@ def main():
     # This is stuff we do on a normal, non-error return.
     if not renpy.display.error.error_handled:
         renpy.display.render.check_at_shutdown()
-
diff --git a/renpy/memory.py b/renpy/memory.py
index 89928b4..60892de 100644
--- a/renpy/memory.py
+++ b/renpy/memory.py
@@ -22,6 +22,7 @@
 # This file contains functions used to help debug memory leaks. They aren't
 # called by default, but can be used when problems occur.
 
+from __future__ import print_function
 import time
 import weakref
 import types
@@ -33,10 +34,12 @@ import renpy
 
 memory_log = renpy.log.open("memory")
 
+
 def write(s):
     sys.stdout.write(s + "\n")
     memory_log.write("%s", s)
 
+
 def walk_memory(roots, seen=None):
     """
     Walks over memory, trying to account it to the objects in `roots`. Each
@@ -102,6 +105,7 @@ def walk_memory(roots, seen=None):
 
     return size, seen
 
+
 def profile_memory_common(packages=[ "renpy", "store" ]):
     """
     Profiles object, surface, and texture memory used in the renpy and store
@@ -191,6 +195,7 @@ def profile_memory(fraction=1.0, minimum=0):
 old_usage = { }
 old_total = 0
 
+
 def diff_memory(update=True):
     """
     :doc: memory
@@ -342,15 +347,15 @@ def find_parents(cls):
 
             objects.append(o)
 
-            print prefix + str(id(o)), type(o),
+            print(prefix + str(id(o)), type(o), end=' ')
 
             try:
                 if isinstance(o, dict) and "__name__" in o:
-                    print "with name", o["__name__"]
+                    print("with name", o["__name__"])
                 else:
-                    print repr(o)#[:1000]
+                    print(repr(o))  # [:1000]
             except:
-                print "Bad repr."
+                print("Bad repr.")
 
             found = False
 
@@ -388,7 +393,7 @@ def find_parents(cls):
                 break
 
             if not found:
-                print "<no parent, popping>"
+                print("<no parent, popping>")
 
             o, prefix = queue.pop()
 
@@ -397,8 +402,8 @@ def find_parents(cls):
             import random
             if random.random() < .1:
 
-                print
-                print "==================================================="
-                print
+                print()
+                print("===================================================")
+                print()
 
                 print_path(o)
diff --git a/renpy/minstore.py b/renpy/minstore.py
index 4fa179b..36526ce 100644
--- a/renpy/minstore.py
+++ b/renpy/minstore.py
@@ -27,23 +27,24 @@ python_set = _set = set
 _type = type
 
 from renpy.python import RevertableList as __renpy__list__
-list = __renpy__list__ #@ReservedAssignment
+list = __renpy__list__  # @ReservedAssignment
 
 from renpy.python import RevertableDict as __renpy__dict__
-dict = __renpy__dict__ #@ReservedAssignment
+dict = __renpy__dict__  # @ReservedAssignment
 
 from renpy.python import RevertableSet as __renpy__set__
-set = __renpy__set__ # @ReservedAssignment
+set = __renpy__set__  # @ReservedAssignment
 Set = __renpy__set__
 
-from renpy.python import RevertableObject as object #@UnusedImport
+from renpy.python import RevertableObject as object  # @UnusedImport
 
-from renpy.python import revertable_range as range #@UnusedImport
-from renpy.python import revertable_sorted as sorted #@UnusedImport
+from renpy.python import revertable_range as range  # @UnusedImport
+from renpy.python import revertable_sorted as sorted  # @UnusedImport
+
+import renpy.ui as ui  # @UnusedImport
+import renpy.exports as renpy  # @Reimport @UnusedImport
+from renpy.translation import translate_string as __  # @UnusedImport
 
-import renpy.ui as ui #@UnusedImport
-import renpy.exports as renpy #@Reimport @UnusedImport
-from renpy.translation import translate_string as __ # @UnusedImport
 
 def _(s):
     """
@@ -54,4 +55,3 @@ def _(s):
     """
 
     return s
-
diff --git a/renpy/object.py b/renpy/object.py
index a347781..8eb7e01 100644
--- a/renpy/object.py
+++ b/renpy/object.py
@@ -19,6 +19,7 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+
 class Object(object):
     """
     Our own base class. Contains methods to simplify serialization.
@@ -35,12 +36,10 @@ class Object(object):
             if f in rv:
                 del rv[f]
 
-
         rv["__version__"] = self.__version__
 
         return rv
 
-
     # None, to prevent this from being called when unnecessary.
     after_setstate = None
 
@@ -51,16 +50,17 @@ class Object(object):
         self.__dict__.update(new_dict)
 
         if version != self.__version__:
-            self.after_upgrade(version) # E1101
+            self.after_upgrade(version)  # E1101
 
         if self.after_setstate:
-            self.after_setstate() # E1102
+            self.after_setstate()  # E1102
 
 # We don't handle slots with this mechanism, since the call to vars should
 # throw an error.
 
 sentinels = { }
 
+
 class Sentinel(object):
     """
     This is used to represent a sentinel object. There will be exactly one
@@ -81,4 +81,3 @@ class Sentinel(object):
 
     def __reduce__(self):
         return (Sentinel, (self.name, ))
-
diff --git a/renpy/parser.py b/renpy/parser.py
index 0c254e0..9716b04 100644
--- a/renpy/parser.py
+++ b/renpy/parser.py
@@ -22,6 +22,7 @@
 # This module contains the parser for the Ren'Py script language. It's
 # called when parsing is necessary, and creates an AST from the script.
 
+from __future__ import print_function
 import codecs
 import re
 import os
@@ -35,6 +36,7 @@ import renpy.sl2
 # A list of parse error messages.
 parse_errors = [ ]
 
+
 class ParseError(Exception):
 
     def __init__(self, filename, number, msg, line=None, pos=None, first=False):
@@ -85,6 +87,8 @@ class ParseError(Exception):
         return self.message
 
 # Something to hold the expected line number.
+
+
 class LineNumberHolder(object):
     """
     Holds the expected line number.
@@ -93,6 +97,7 @@ class LineNumberHolder(object):
     def __init__(self):
         self.line = 0
 
+
 def unicode_filename(fn):
     """
     Converts the supplied filename to unicode.
@@ -120,6 +125,7 @@ def unicode_filename(fn):
 # before this.
 lllword = re.compile(r'__(\w+)|\w+| +|.', re.S)
 
+
 def munge_filename(fn):
     # The prefix that's used when __ is found in the file.
     rv = os.path.basename(fn)
@@ -133,6 +139,7 @@ def munge_filename(fn):
 
     return "_m1_" + rv + "__"
 
+
 def elide_filename(fn):
     """
     Returns a version of fn that is either relative to the base directory,
@@ -150,6 +157,7 @@ def elide_filename(fn):
     else:
         return fn.replace("\\", "/")
 
+
 def unelide_filename(fn):
     fn1 = os.path.join(renpy.config.basedir, fn)
     if os.path.exists(fn1):
@@ -164,6 +172,7 @@ def unelide_filename(fn):
 # The filename that the start and end positions are relative to.
 original_filename = ""
 
+
 def list_logical_lines(filename, filedata=None, linenumber=1):
     """
     Reads `filename`, and divides it into logical lines.
@@ -344,14 +353,12 @@ def list_logical_lines(filename, filedata=None, linenumber=1):
 
             pos = m.end(0)
 
-
     if not line == "":
         raise ParseError(filename, start_number, "is not terminated with a newline. (Check strings and parenthesis.)", line=line, first=True)
 
     return rv
 
 
-
 def group_logical_lines(lines):
     """
     This takes as input the list of logical line triples output from
@@ -419,64 +426,64 @@ def group_logical_lines(lines):
 # A list of keywords which should not be parsed as names, because
 # there is a huge chance of confusion.
 #
-# Note: We need to be careful with what's in here, because thse
+# Note: We need to be careful with what's in here, because these
 # are banned in simple_expressions, where we might want to use
 # some of them.
 KEYWORDS = set([
-            '$',
-            'as',
-            'at',
-            'behind',
-            'call',
-            'expression',
-            'hide',
-            'if',
-            'in',
-            'image',
-            'init',
-            'jump',
-            'menu',
-            'onlayer',
-            'python',
-            'return',
-            'scene',
-            'set',
-            'show',
-            'with',
-            'while',
-            'zorder',
-            'transform',
-            ])
+    '$',
+    'as',
+    'at',
+    'behind',
+    'call',
+    'expression',
+    'hide',
+    'if',
+    'in',
+    'image',
+    'init',
+    'jump',
+    'menu',
+    'onlayer',
+    'python',
+    'return',
+    'scene',
+    'set',
+    'show',
+    'with',
+    'while',
+    'zorder',
+    'transform',
+    ])
 
 OPERATORS = [
-        '<',
-        '<=',
-        '>',
-        '>=',
-        '<>',
-        '!=',
-        '==',
-        '|',
-        '^',
-        '&',
-        '<<',
-        '>>',
-        '+',
-        '-',
-        '*',
-        '/',
-        '//',
-        '%',
-        '~',
-        '**',
-        ]
+    '<',
+    '<=',
+    '>',
+    '>=',
+    '<>',
+    '!=',
+    '==',
+    '|',
+    '^',
+    '&',
+    '<<',
+    '>>',
+    '+',
+    '-',
+    '*',
+    '/',
+    '//',
+    '%',
+    '~',
+    '**',
+    ]
 
 ESCAPED_OPERATORS = [
-        r'\bor\b',
-        r'\band\b',
-        r'\bnot\b',
-        r'\bin\b',
-        r'\bis\b',
+    r'\bor\b',
+    r'\band\b',
+    r'\bnot\b',
+    r'\bin\b',
+    r'\bis\b',
     ]
 
 operator_regexp = "|".join([ re.escape(i) for i in OPERATORS ] + ESCAPED_OPERATORS)
@@ -484,6 +491,7 @@ operator_regexp = "|".join([ re.escape(i) for i in OPERATORS ] + ESCAPED_OPERATO
 word_regexp = ur'[a-zA-Z_\u00a0-\ufffd][0-9a-zA-Z_\u00a0-\ufffd]*'
 image_word_regexp = ur'[-0-9a-zA-Z_\u00a0-\ufffd][-0-9a-zA-Z_\u00a0-\ufffd]*'
 
+
 class Lexer(object):
     """
     The lexer that is used to lex script files. This works on the idea
@@ -515,8 +523,6 @@ class Lexer(object):
         self.word_cache_newpos = -1
         self.word_cache = ""
 
-
-
     def advance(self):
         """
         Advances this lexer to the next line in the block. The lexer
@@ -583,7 +589,6 @@ class Lexer(object):
         self.skip_whitespace()
         return self.match_regexp(regexp)
 
-
     def keyword(self, word):
         """
         Matches a keyword at the current position. A keyword is a word
@@ -598,7 +603,6 @@ class Lexer(object):
         self.pos = oldpos
         return ''
 
-
     def error(self, msg):
         """
         Convenience function for reporting a parse error at the current
@@ -645,7 +649,6 @@ class Lexer(object):
         if not self.subblock:
             self.error('%s expects a non-empty block.' % stmt)
 
-
     def subblock_lexer(self, init=False):
         """
         Returns a new lexer object, equiped to parse the block
@@ -709,7 +712,7 @@ class Lexer(object):
 
         return self.match(r'(\+|\-)?\d+')
 
-    def float(self): #@ReservedAssignment
+    def float(self):  # @ReservedAssignment
         """
         Tries to parse a number (float). Returns a string containing the
         number, or None.
@@ -719,7 +722,7 @@ class Lexer(object):
 
     def hash(self):
         """
-        Matches the chatacters in an md5 hash, and then some.
+        Matches the characters in an md5 hash, and then some.
         """
 
         return self.match(r'\w+')
@@ -740,7 +743,6 @@ class Lexer(object):
 
         return rv
 
-
     def name(self):
         """
         This tries to parse a name. Returns the name or None.
@@ -825,7 +827,6 @@ class Lexer(object):
 
         return rv
 
-
     def python_string(self):
         """
         This tries to match a python string at the current
@@ -875,7 +876,6 @@ class Lexer(object):
         self.pos += 1
         return True
 
-
     def dotted_name(self):
         """
         This tries to match a dotted name, which is one or more names,
@@ -918,7 +918,7 @@ class Lexer(object):
             if c in delim:
                 return renpy.ast.PyExpr(self.text[start:self.pos], self.filename, self.number)
 
-            if c == '"' or c == "'":
+            if c in "'\"":
                 self.python_string()
                 continue
 
@@ -940,7 +940,7 @@ class Lexer(object):
         if not pe:
             self.error("expected python_expression")
 
-        rv = renpy.ast.PyExpr(pe.strip(), pe.filename, pe.linenumber) # E1101
+        rv = renpy.ast.PyExpr(pe.strip(), pe.filename, pe.linenumber)  # E1101
 
         return rv
 
@@ -948,7 +948,7 @@ class Lexer(object):
         """
         Tries to match a parenthesised python expression. If it can,
         returns true and updates the current position to be after the
-        closing parenthesis. Returns False otherewise.
+        closing parenthesis. Returns False otherwise.
         """
 
         c = self.text[self.pos]
@@ -965,7 +965,6 @@ class Lexer(object):
             self.pos += 1
             return True
 
-
         if c == '{':
             self.pos += 1
             self.delimited_python('}')
@@ -974,7 +973,6 @@ class Lexer(object):
 
         return False
 
-
     def simple_expression(self, comma=False):
         """
         Tries to parse a simple_expression. Returns the text if it can, or
@@ -995,9 +993,9 @@ class Lexer(object):
             # We start with either a name, a python_string, or parenthesized
             # python
             if not (self.python_string() or
-                self.name() or
-                self.float() or
-                self.parenthesised_python()):
+                    self.name() or
+                    self.float() or
+                    self.parenthesised_python()):
 
                 break
 
@@ -1044,7 +1042,6 @@ class Lexer(object):
 
         return self.simple_expression(comma=True)
 
-
     def checkpoint(self):
         """
         Returns an opaque representation of the lexer state. This can be
@@ -1134,6 +1131,7 @@ class Lexer(object):
         process(self.subblock, '')
         return ''.join(rv)
 
+
 def parse_image_name(l, string=False, nodash=False):
     """
     This parses an image name, and returns it as a tuple. It requires
@@ -1174,6 +1172,7 @@ def parse_image_name(l, string=False, nodash=False):
 
     return tuple(rv)
 
+
 def parse_simple_expression_list(l):
     """
     This parses a comma-separated list of simple_expressions, and
@@ -1196,6 +1195,7 @@ def parse_simple_expression_list(l):
 
     return rv
 
+
 def parse_image_specifier(l):
     """
     This parses an image specifier.
@@ -1268,6 +1268,7 @@ def parse_image_specifier(l):
 
     return image_name, expression, tag, at_list, layer, zorder, behind
 
+
 def parse_with(l, node):
     """
     Tries to parse the with clause associated with this statement. If
@@ -1298,7 +1299,7 @@ def parse_menu(stmtl, loc):
     has_caption = False
 
     with_ = None
-    set = None #@ReservedAssignment
+    set = None  # @ReservedAssignment
 
     say_who = None
     say_what = None
@@ -1319,7 +1320,7 @@ def parse_menu(stmtl, loc):
             continue
 
         if l.keyword('set'):
-            set = l.require(l.simple_expression) #@ReservedAssignment
+            set = l.require(l.simple_expression)  # @ReservedAssignment
             l.expect_eol()
             l.expect_noblock('set menuitem')
             l.advance()
@@ -1353,7 +1354,6 @@ def parse_menu(stmtl, loc):
 
         l.revert(state)
 
-
         label = l.string()
 
         if label is None:
@@ -1437,7 +1437,6 @@ def parse_parameters(l):
 
             names.add(extrakw)
 
-
         elif l.match(r'\*'):
 
             if not add_positional:
@@ -1506,7 +1505,6 @@ def parse_arguments(l):
 
             extrakw = l.delimited_python("),")
 
-
         elif l.match(r'\*'):
             if extrapos is not None:
                 l.error('a call may have only one * argument')
@@ -1564,7 +1562,7 @@ class ParseTrie(object):
 
         word = l.word() or l.match(r'\$')
 
-        if not word in self.words:
+        if word not in self.words:
             l.pos = old_pos
             return self.default
 
@@ -1735,10 +1733,11 @@ def call_statement(l, loc):
         l.set_global_label(name)
         rv.append(ast.Label(loc, name, [], None))
     else:
-        if expression:
-            renpy.add_from.report_missing("expression", original_filename, renpy.scriptedit.lines[loc].end)
-        else:
-            renpy.add_from.report_missing(target, original_filename, renpy.scriptedit.lines[loc].end)
+        if renpy.scriptedit.lines and (loc in renpy.scriptedit.lines):
+            if expression:
+                renpy.add_from.report_missing("expression", original_filename, renpy.scriptedit.lines[loc].end)
+            else:
+                renpy.add_from.report_missing(target, original_filename, renpy.scriptedit.lines[loc].end)
 
     rv.append(ast.Pass(loc))
 
@@ -1791,6 +1790,7 @@ def show_statement(l, loc):
 
     return rv
 
+
 @statement("show layer")
 def show_layer_statement(l, loc):
 
@@ -1990,7 +1990,7 @@ def python_statement(l, loc):
         hide = True
 
     if l.keyword('in'):
-        store = "store." + l.require(l.name)
+        store = "store." + l.require(l.dotted_name)
 
     l.require(':')
     l.expect_block('python block')
@@ -2027,6 +2027,7 @@ def label_statement(l, loc, init=False):
     l.advance()
     return ast.Label(loc, name, block, parameters, hide=hide)
 
+
 @statement("init offset")
 def init_offset_statement(l, loc):
 
@@ -2040,10 +2041,12 @@ def init_offset_statement(l, loc):
     l.init_offset = int(offset)
     return [ ]
 
+
 @statement("init label")
 def init_label_statement(l, loc):
     return label_statement(l, loc, init=True)
 
+
 @statement("init")
 def init_statement(l, loc):
 
@@ -2114,6 +2117,7 @@ def screen2_statement(l, loc):
 # The version of screen language to use by default.
 default_screen_language = int(os.environ.get("RENPY_SCREEN_LANGUAGE", "2"))
 
+
 @statement("screen")
 def screen_statement(l, loc):
 
@@ -2209,6 +2213,7 @@ def translate_strings(init_loc, language, l):
 
     return ast.Init(init_loc, block, l.init_offset)
 
+
 @statement("translate")
 def translate_statement(l, loc):
 
@@ -2228,7 +2233,7 @@ def translate_statement(l, loc):
             l.init = True
 
             block = [ python_statement(l, loc) ]
-            return [ ast.TranslateBlock(loc, language, block) ]
+            return [ ast.TranslateEarlyBlock(loc, language, block) ]
         finally:
             l.init = old_init
 
@@ -2242,7 +2247,6 @@ def translate_statement(l, loc):
         finally:
             l.init = old_init
 
-
     l.require(':')
     l.expect_eol()
 
@@ -2289,7 +2293,7 @@ def style_statement(l, loc):
         if l.keyword("del"):
             propname = l.require(l.name)
 
-            if propname not in renpy.style.prefixed_all_properties: # @UndefinedVariable
+            if propname not in renpy.style.prefixed_all_properties:  # @UndefinedVariable
                 l.error("style property %s is not known." % propname)
 
             rv.delattr.append(propname)
@@ -2306,7 +2310,7 @@ def style_statement(l, loc):
         propname = l.name()
 
         if propname is not None:
-            if (propname != "properties") and (propname not in renpy.style.prefixed_all_properties): # @UndefinedVariable
+            if (propname != "properties") and (propname not in renpy.style.prefixed_all_properties):  # @UndefinedVariable
                 l.error("style property %s is not known." % propname)
 
             if propname in rv.properties:
@@ -2432,7 +2436,6 @@ def parse_statement(l):
     return pf(l, loc)
 
 
-
 def parse_block(l):
     """
     This parses a block of Ren'Py statements. It returns a list of the
@@ -2453,12 +2456,13 @@ def parse_block(l):
             else:
                 rv.append(stmt)
 
-        except ParseError, e:
+        except ParseError as e:
             parse_errors.append(e.message)
             l.advance()
 
     return rv
 
+
 def parse(fn, filedata=None, linenumber=1):
     """
     Parses a Ren'Py script contained within the file `fn`.
@@ -2493,12 +2497,14 @@ def parse(fn, filedata=None, linenumber=1):
 
     return rv
 
+
 def get_parse_errors():
     global parse_errors
     rv = parse_errors
     parse_errors = [ ]
     return rv
 
+
 def report_parse_errors():
 
     if not parse_errors:
@@ -2509,9 +2515,9 @@ def report_parse_errors():
     f, error_fn = renpy.error.open_error_file("errors.txt", "w")
     f.write(codecs.BOM_UTF8)
 
-    print >>f, "I'm sorry, but errors were detected in your script. Please correct the"
-    print >>f, "errors listed below, and try again."
-    print >>f
+    print("I'm sorry, but errors were detected in your script. Please correct the", file=f)
+    print("errors listed below, and try again.", file=f)
+    print(file=f)
 
     for i in parse_errors:
 
@@ -2523,21 +2529,20 @@ def report_parse_errors():
         except:
             pass
 
-        print
-        print >>f
-        print i
-        print >>f, i
-
+        print()
+        print(file=f)
+        print(i)
+        print(i, file=f)
 
-    print >>f
-    print >>f, "Ren'Py Version:", renpy.version
+    print(file=f)
+    print("Ren'Py Version:", renpy.version, file=f)
 
     f.close()
 
     renpy.display.error.report_parse_errors(full_text, error_fn)
 
     try:
-        if renpy.game.args.command == "run": #@UndefinedVariable
+        if renpy.game.args.command == "run":  # @UndefinedVariable
             renpy.exports.launch_editor([ error_fn ], 1, transient=1)
     except:
         pass
diff --git a/renpy/persistent.py b/renpy/persistent.py
index 5b23aac..aab6070 100644
--- a/renpy/persistent.py
+++ b/renpy/persistent.py
@@ -19,6 +19,8 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
+
 import os
 import copy
 import time
@@ -28,6 +30,8 @@ import renpy
 from renpy.loadsave import dump, dumps, loads
 
 # The class that's used to hold the persistent data.
+
+
 class Persistent(object):
 
     def __init__(self):
@@ -99,7 +103,13 @@ class Persistent(object):
         # A map from the name of a field to the time that field was last
         # changed at.
         if self._changed is None:
-            self._changed = { }
+            self._changed = {
+                "_preferences" : 0,
+                "_seen_ever" : 0,
+                "_chosen" : 0,
+                "_seen_audio" : 0,
+                "_seen_translates" : 0,
+            }
 
 
 renpy.game.Persistent = Persistent
@@ -131,6 +141,7 @@ def safe_deepcopy(o):
 # object.
 backup = { }
 
+
 def find_changes():
     """
     This finds changes in the persistent object. When it finds a change, it
@@ -197,10 +208,14 @@ def init():
     disk, so that we can configure the savelocation system.
     """
 
-    filename = os.path.join(renpy.config.savedir, "persistent")
+    filename = os.path.join(renpy.config.savedir, "persistent.new")
     persistent = load(filename)
 
     if persistent is None:
+        filename = os.path.join(renpy.config.savedir, "persistent")
+        persistent = load(filename)
+
+    if persistent is None:
         persistent = Persistent()
 
     # Create the backup of the persistent data.
@@ -215,6 +230,7 @@ def init():
 # A map from field name to merge function.
 registry = { }
 
+
 def register_persistent(field, func):
     """
     :doc: persistent
@@ -246,9 +262,11 @@ def register_persistent(field, func):
 
     registry[field] = func
 
+
 def default_merge(old, new, current):
     return new
 
+
 def dictset_merge(old, new, current):
     current.update(old)
     current.update(new)
@@ -259,10 +277,11 @@ register_persistent("_seen_images", dictset_merge)
 register_persistent("_seen_audio", dictset_merge)
 register_persistent("_chosen", dictset_merge)
 
+
 def merge(other):
     """
     Merges `other` (which must be a persistent object) into the
-    current persistent object. This updates deep
+    current persistent object.
     """
 
     now = time.time()
@@ -298,6 +317,7 @@ def merge(other):
         merge_func = registry.get(f, default_merge)
 
         val = merge_func(old, new, pval)
+
         pvars[f] = val
         backup[f] = safe_deepcopy(val)
         persistent._changed[f] = t
@@ -359,6 +379,7 @@ def update(force_save=False):
 
 should_save_persistent = True
 
+
 def save():
     """
     Saves the persistent data to disk.
@@ -440,7 +461,7 @@ def MultiPersistent(name):
     except:
         pass
 
-    fn = "" # prevent a warning from happening.
+    fn = ""  # prevent a warning from happening.
 
     # Find the first file that actually exists. Otherwise, use the last
     # file.
@@ -454,7 +475,7 @@ def MultiPersistent(name):
     except:
         rv = _MultiPersistent()
 
-    rv._filename = fn # W0201
+    rv._filename = fn  # W0201
     return rv
 
 renpy.loadsave._MultiPersistent = _MultiPersistent
diff --git a/renpy/preferences.py b/renpy/preferences.py
index 2d3adce..9937c7a 100644
--- a/renpy/preferences.py
+++ b/renpy/preferences.py
@@ -46,7 +46,7 @@ pad_bindings = {
     "pad_rightx_pos" : [ "focus_right", "bar_right" ],
 
     "pad_dpup_press" : [ "focus_up", "bar_up" ],
-    "pad_lefty_neg" :  [ "focus_up", "bar_up" ],
+    "pad_lefty_neg" : [ "focus_up", "bar_up" ],
     "pad_righty_neg" : [ "focus_up", "bar_up" ],
 
     "pad_dpdown_press" : [ "focus_down", "bar_down" ],
@@ -54,6 +54,7 @@ pad_bindings = {
     "pad_righty_pos" : [ "focus_down", "bar_down" ],
 }
 
+
 class Preferences(renpy.object.Object):
     """
     Stores preferences that will one day be persisted.
@@ -198,7 +199,7 @@ class Preferences(renpy.object.Object):
         return renpy.audio.music.get_all_mixers()
 
     def __eq__(self, other):
-        return True
+        return vars(self) == vars(other)
 
 renpy.game.Preferences = Preferences
 renpy.game.preferences = Preferences()
diff --git a/renpy/pyanalysis.py b/renpy/pyanalysis.py
index 9b2e1d0..b644444 100644
--- a/renpy/pyanalysis.py
+++ b/renpy/pyanalysis.py
@@ -24,7 +24,7 @@ from __future__ import unicode_literals
 from __future__ import division
 from __future__ import absolute_import
 
-import renpy # @UnusedImport
+import renpy  # @UnusedImport
 from renpy.python import py_compile
 
 # Import the Python AST module, instead of the Ren'Py ast module.
@@ -92,6 +92,7 @@ not_constants = set()
 # The base set for the local constants.
 local_constants = set()
 
+
 def const(name):
     """
     :doc: const
@@ -175,12 +176,13 @@ class Control(object):
         self.imagemap = imagemap
 
 # Three levels of constness.
-GLOBAL_CONST = 2 # Expressions that are const everywhere.
+GLOBAL_CONST = 2  # Expressions that are const everywhere.
 LOCAL_CONST = 1  # Expressions that are const with regard to a screen + parameters.
 NOT_CONST = 0    # Expressions that are not const.
 
 
 class DeltaSet(object):
+
     def __init__(self, base, copy=None):
         """
         Represents a set that stores its contents as differences from a base
@@ -232,8 +234,6 @@ class DeltaSet(object):
             yield i
 
 
-
-
 class Analysis(object):
     """
     Represents the result of code analysis, and provides tools to perform
@@ -320,11 +320,10 @@ class Analysis(object):
             if not i.at_fixed_point():
                 return False
 
-
         if (self.not_constant.changed or
-            self.global_constant.changed or
-            self.local_constant.changed or
-            self.pure_functions.changed):
+                self.global_constant.changed or
+                self.local_constant.changed or
+                self.pure_functions.changed):
 
             self.not_constant.changed = False
             self.global_constant.changed = False
@@ -365,7 +364,7 @@ class Analysis(object):
         object equality.
         """
 
-        def check_slice(slice): # @ReservedAssignment
+        def check_slice(slice):  # @ReservedAssignment
 
             if isinstance(slice, ast.Index):
                 return check_node(slice.value)
@@ -467,7 +466,7 @@ class Analysis(object):
                 const, name = check_name(node.func)
 
                 # The function must have a name, and must be declared pure.
-                if (const != GLOBAL_CONST) or  (name not in self.pure_functions):
+                if (const != GLOBAL_CONST) or (name not in self.pure_functions):
                     return NOT_CONST
 
                 consts = [ ]
@@ -646,6 +645,7 @@ class PyAnalysis(ast.NodeVisitor):
     def visit_Continue(self, node):
         self.analysis.exit_loop()
 
+
 class CompilerCache(object):
     """
     Objects of this class are used to cache the compiliation of Python code.
@@ -719,8 +719,9 @@ ccache = CompilerCache()
 
 CACHE_FILENAME = "cache/pyanalysis.rpyb"
 
+
 def load_cache():
-    if renpy.game.args.compile: # @UndefinedVariable
+    if renpy.game.args.compile:  # @UndefinedVariable
         return
 
     try:
@@ -734,10 +735,14 @@ def load_cache():
     except:
         pass
 
+
 def save_cache():
     if not ccache.updated:
         return
 
+    if renpy.macapp:
+        return
+
     try:
         data = zlib.compress(dumps(ccache, 2), 9)
 
diff --git a/renpy/python.py b/renpy/python.py
index 89750fe..b2ca31a 100644
--- a/renpy/python.py
+++ b/renpy/python.py
@@ -23,9 +23,14 @@
 # contained within the script file. It also handles rolling back the
 # game state to some time in the past.
 
+from __future__ import print_function
+
 # Import the python ast module, not ours.
 ast = __import__("ast", { })
 
+# Import the future module itself.
+import __future__
+
 import marshal
 import random
 import weakref
@@ -42,12 +47,15 @@ import renpy.audio
 # Deleted is a singleton object that's used to represent an object that has
 # been deleted from the store.
 
+
 class StoreDeleted(object):
+
     def __reduce__(self):
         return "deleted"
 
 deleted = StoreDeleted()
 
+
 class StoreModule(object):
     """
     This class represents one of the modules containing the store of data.
@@ -69,9 +77,12 @@ class StoreModule(object):
         del self.__dict__[key]
 
 # Used to unpickle a store module.
+
+
 def get_store_module(name):
     return sys.modules[name]
 
+
 class StoreDict(dict):
     """
     This class represents the dictionary of a store module. It logs
@@ -146,11 +157,17 @@ store_modules = { }
 # run.
 initialized_store_dicts = set()
 
+
 def create_store(name):
     """
     Creates the store with `name`.
     """
 
+    parent, _, var = name.rpartition('.')
+
+    if parent:
+        create_store(parent)
+
     name = str(name)
 
     if name in initialized_store_dicts:
@@ -179,9 +196,9 @@ def create_store(name):
     else:
         store_modules[name] = sys.modules[name] = StoreModule(d)
 
-    # If we're a module in the store, add us to the store.
-    if name.startswith("store."):
-        store_dicts["store"][name[6:]] = sys.modules[name]
+    if parent:
+        store_dicts[parent][var] = sys.modules[name]
+
 
 class StoreBackup():
     """
@@ -200,7 +217,6 @@ class StoreBackup():
         # The contents of ever_been_changed for each store.
         self.ever_been_changed = { }
 
-
         for k, v in store_dicts.iteritems():
             self.store[k] = dict(v)
             self.old[k] = dict(v.old)
@@ -226,6 +242,7 @@ class StoreBackup():
 
 clean_store_backup = None
 
+
 def make_clean_stores():
     """
     Copy the clean stores.
@@ -240,6 +257,7 @@ def make_clean_stores():
 
     clean_store_backup = StoreBackup()
 
+
 def clean_stores():
     """
     Revert the store to the clean copy.
@@ -247,6 +265,7 @@ def clean_stores():
 
     clean_store_backup.restore()
 
+
 def clean_store(name):
     """
     Reverts the named store to its clean copy.
@@ -257,6 +276,7 @@ def clean_store(name):
 
     clean_store_backup.restore_one(name)
 
+
 def reset_store_changes(name):
 
     if not name.startswith("store."):
@@ -265,8 +285,9 @@ def reset_store_changes(name):
     sd = store_dicts[name]
     sd.begin()
 
-##### Code that computes reachable objects, which is used to filter
-##### the rollback list before rollback or serialization.
+# Code that computes reachable objects, which is used to filter
+# the rollback list before rollback or serialization.
+
 
 class NoRollback(object):
     """
@@ -338,6 +359,7 @@ def reached(obj, reachable, wait):
 
     # parents.pop()
 
+
 def reached_vars(store, reachable, wait):
     """
     Marks everything reachable from the variables in the store
@@ -359,68 +381,68 @@ def reached_vars(store, reachable, wait):
                 reached(v, reachable, wait)
 
 
-##### Code that replaces literals will calls to magic constructors.
+# Code that replaces literals will calls to magic constructors.
 
 class WrapNode(ast.NodeTransformer):
 
     def visit_SetComp(self, n):
         return ast.Call(
-            func = ast.Name(
+            func=ast.Name(
                 id="__renpy__set__",
                 ctx=ast.Load()
                 ),
-            args = [ self.generic_visit(n) ],
-            keywords = [ ],
-            starargs = None,
-            kwargs = None)
+            args=[ self.generic_visit(n) ],
+            keywords=[ ],
+            starargs=None,
+            kwargs=None)
 
     def visit_ListComp(self, n):
         return ast.Call(
-            func = ast.Name(
+            func=ast.Name(
                 id="__renpy__list__",
                 ctx=ast.Load()
                 ),
-            args = [ self.generic_visit(n) ],
-            keywords = [ ],
-            starargs = None,
-            kwargs = None)
+            args=[ self.generic_visit(n) ],
+            keywords=[ ],
+            starargs=None,
+            kwargs=None)
 
     def visit_List(self, n):
         if not isinstance(n.ctx, ast.Load):
             return self.generic_visit(n)
 
         return ast.Call(
-            func = ast.Name(
+            func=ast.Name(
                 id="__renpy__list__",
                 ctx=ast.Load()
                 ),
-            args = [ self.generic_visit(n) ],
-            keywords = [ ],
-            starargs = None,
-            kwargs = None)
+            args=[ self.generic_visit(n) ],
+            keywords=[ ],
+            starargs=None,
+            kwargs=None)
 
     def visit_DictComp(self, n):
         return ast.Call(
-            func = ast.Name(
+            func=ast.Name(
                 id="__renpy__dict__",
                 ctx=ast.Load()
                 ),
-            args = [ self.generic_visit(n) ],
-            keywords = [ ],
-            starargs = None,
-            kwargs = None)
+            args=[ self.generic_visit(n) ],
+            keywords=[ ],
+            starargs=None,
+            kwargs=None)
 
     def visit_Dict(self, n):
 
         return ast.Call(
-            func = ast.Name(
+            func=ast.Name(
                 id="__renpy__dict__",
                 ctx=ast.Load()
                 ),
-            args = [ self.generic_visit(n) ],
-            keywords = [ ],
-            starargs = None,
-            kwargs = None)
+            args=[ self.generic_visit(n) ],
+            keywords=[ ],
+            starargs=None,
+            kwargs=None)
 
 wrap_node = WrapNode()
 
@@ -441,6 +463,7 @@ def set_filename(filename, offset, tree):
 
 unicode_re = re.compile(ur'[\u0080-\uffff]')
 
+
 def unicode_sub(m):
     """
     If the string s contains a unicode character, make it into a
@@ -466,12 +489,26 @@ def unicode_sub(m):
 
 string_re = re.compile(r'([uU]?[rR]?)("""|"|\'\'\'|\')((\\.|.)*?)\2')
 
+
 def escape_unicode(s):
     if unicode_re.search(s):
         s = string_re.sub(unicode_sub, s)
 
     return s
 
+
+# Flags used by py_compile.
+old_compile_flags = ( __future__.nested_scopes.compiler_flag
+                      | __future__.with_statement.compiler_flag
+                      )
+
+new_compile_flags = (  old_compile_flags
+                       | __future__.absolute_import.compiler_flag
+                       | __future__.print_function.compiler_flag
+                       | __future__.unicode_literals.compiler_flag
+                       )
+
+
 def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False):
     """
     Compiles the given source code using the supplied codegenerator.
@@ -512,7 +549,12 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False):
     try:
         line_offset = lineno - 1
 
-        tree = ast.parse(source, filename, mode)
+        try:
+            flags = new_compile_flags
+            tree = compile(source, filename, mode, ast.PyCF_ONLY_AST | flags, 1)
+        except:
+            flags = old_compile_flags
+            tree = compile(source, filename, mode, ast.PyCF_ONLY_AST | flags, 1)
 
         tree = wrap_node.visit(tree)
 
@@ -524,7 +566,7 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False):
         if ast_node:
             return tree.body
 
-        return compile(tree, filename, mode)
+        return compile(tree, filename, mode, flags, 1)
 
     except SyntaxError, e:
 
@@ -545,21 +587,21 @@ def py_compile_eval_bytecode(source, **kwargs):
     return marshal.dumps(code)
 
 
-
-##### Classes that are exported in place of the normal list, dict, and
-##### object.
+# Classes that are exported in place of the normal list, dict, and
+# object.
 
 # This is set to True whenever a mutation occurs. The save code uses
 # this to check to see if a background-save is valid.
 mutate_flag = True
 
+
 def mutator(method):
 
     def do_mutation(self, *args, **kwargs):
 
         global mutate_flag
 
-        mutated = renpy.game.log.mutated #@UndefinedVariable
+        mutated = renpy.game.log.mutated  # @UndefinedVariable
 
         if id(self) not in mutated:
             mutated[id(self)] = ( weakref.ref(self), self._clean())
@@ -666,9 +708,9 @@ class RevertableList(list):
     reverse = mutator(list.reverse)
     sort = mutator(list.sort)
 
-    def wrapper(method): # E0213 @NoSelf
+    def wrapper(method):  # E0213 @NoSelf
         def newmethod(*args, **kwargs):
-            return RevertableList(method(*args, **kwargs)) # E1102
+            return RevertableList(method(*args, **kwargs))  # E1102
 
         return newmethod
 
@@ -716,12 +758,15 @@ class RevertableList(list):
         else:
             self[:] = compressed
 
+
 def revertable_range(*args):
     return RevertableList(range(*args))
 
+
 def revertable_sorted(*args, **kwargs):
     return RevertableList(sorted(*args, **kwargs))
 
+
 class RevertableDict(dict):
 
     def __init__(self, *args, **kwargs):
@@ -739,9 +784,9 @@ class RevertableDict(dict):
     popitem = mutator(dict.popitem)
     setdefault = mutator(dict.setdefault)
 
-    def list_wrapper(method): # E0213 @NoSelf
+    def list_wrapper(method):  # E0213 @NoSelf
         def newmethod(*args, **kwargs):
-            return RevertableList(method(*args, **kwargs)) # E1102
+            return RevertableList(method(*args, **kwargs))  # E1102
 
         return newmethod
 
@@ -794,9 +839,9 @@ class RevertableSet(sets.Set):
     union_update = mutator(sets.Set.union_update)
     update = mutator(sets.Set.update)
 
-    def wrapper(method): # E0213 @NoSelf
+    def wrapper(method):  # E0213 @NoSelf
         def newmethod(*args, **kwargs):
-            rv = method(*args, **kwargs) # E1102
+            rv = method(*args, **kwargs)  # E1102
             if isinstance(rv, sets.Set):
                 return RevertableSet(rv)
             else:
@@ -860,7 +905,7 @@ class RevertableObject(object):
         self.__dict__.update(compressed)
 
 
-##### An object that handles deterministic randomness, or something.
+# An object that handles deterministic randomness, or something.
 
 class DetRandom(random.Random):
 
@@ -900,7 +945,7 @@ class DetRandom(random.Random):
 
         self.stack = [ ]
 
-    def Random(self,seed=None):
+    def Random(self, seed=None):
         """
         Returns a new RNG object separate from the main one.
         """
@@ -911,12 +956,13 @@ class DetRandom(random.Random):
 
 rng = DetRandom()
 
-##### This is the code that actually handles the logging and managing
-##### of the rollbacks.
+# This is the code that actually handles the logging and managing
+# of the rollbacks.
 
 generation = time.time()
 serial = 0
 
+
 class Rollback(renpy.object.Object):
     """
     Allows the state of the game to be rolled back to the point just
@@ -998,7 +1044,6 @@ class Rollback(renpy.object.Object):
         if version < 4:
             self.hard_checkpoint = self.checkpoint
 
-
     def purge_unreachable(self, reachable, wait):
         """
         Adds objects that are reachable from the store of this
@@ -1039,7 +1084,7 @@ class Rollback(renpy.object.Object):
                 reached(rb, reachable, wait)
             else:
                 if renpy.config.debug:
-                    print "Removing unreachable:", o
+                    print(("Removing unreachable:", o))
 
                     pass
 
@@ -1047,7 +1092,6 @@ class Rollback(renpy.object.Object):
 
         return True
 
-
     def rollback(self):
         """
         Reverts the state of the game to what it was at the start of the
@@ -1085,7 +1129,6 @@ class Rollback(renpy.object.Object):
         renpy.game.contexts.append(self.context)
 
 
-
 class RollbackLog(renpy.object.Object):
     """
     This class manages the list of Rollback objects.
@@ -1104,7 +1147,7 @@ class RollbackLog(renpy.object.Object):
     (weakref to object, information needed to rollback that object)
     """
 
-    __version__ = 4
+    __version__ = 5
 
     nosave = [ 'old_store', 'mutated', 'identifier_cache' ]
     identifier_cache = None
@@ -1146,6 +1189,19 @@ class RollbackLog(renpy.object.Object):
         if version < 4:
             self.retain_after_load_flag = False
 
+        if version < 5:
+
+            # We changed what the rollback limit represents, so recompute it
+            # here.
+            if self.rollback_limit:
+                nrbl = 0
+
+                for rb in self.log[-self.rollback_limit:]:
+                    if rb.hard_checkpoint:
+                        nrbl += 1
+
+                self.rollback_limit = nrbl
+
     def begin(self):
         """
         Called before a node begins executing, to indicate that the
@@ -1241,8 +1297,6 @@ class RollbackLog(renpy.object.Object):
                 # iterating over it.
                 pass
 
-
-
     def get_roots(self):
         """
         Return a map giving the current roots of the store. This is a
@@ -1323,11 +1377,12 @@ class RollbackLog(renpy.object.Object):
         if not renpy.game.context().rollback:
             return
 
-        if self.rollback_limit < renpy.config.hard_rollback_limit:
-            self.rollback_limit += 1
-
         self.current.checkpoint = True
-        self.current.hard_checkpoint = hard
+
+        if hard and (not self.current.hard_checkpoint):
+            if self.rollback_limit < renpy.config.hard_rollback_limit:
+                self.rollback_limit += 1
+            self.current.hard_checkpoint = hard
 
         if self.in_fixed_rollback() and self.forward:
             # use data from the forward stack
@@ -1392,7 +1447,7 @@ class RollbackLog(renpy.object.Object):
 
         return self.rollback_limit > 0
 
-    def rollback(self, checkpoints, force=False, label=None, greedy=True, on_load=False):
+    def rollback(self, checkpoints, force=False, label=None, greedy=True, on_load=False, abnormal=True):
         """
         This rolls the system back to the first valid rollback point
         after having rolled back past the specified number of checkpoints.
@@ -1416,15 +1471,19 @@ class RollbackLog(renpy.object.Object):
         `on_load`
             Should be true if this rollback is being called in response to a
             load. Used to implement .retain_after_load()
+
+        `abnormal`
+            If true, treats this as an abnormal event, suppresisng rollback
+            and so on.
         """
 
         # If we have exceeded the rollback limit, and don't have force,
         # give up.
-        if checkpoints and not self.rollback_limit > 0 and not force:
+        if checkpoints and (self.rollback_limit <= 0) and (not force):
             return
 
         self.suspend_checkpointing(False)
-            # will always rollback to before suspension
+        # will always rollback to before suspension
 
         self.purge_unreachable(self.get_roots())
 
@@ -1435,7 +1494,7 @@ class RollbackLog(renpy.object.Object):
             rb = self.log.pop()
             revlog.append(rb)
 
-            if rb.checkpoint:
+            if rb.hard_checkpoint:
                 self.rollback_limit -= 1
 
             if rb.hard_checkpoint or (on_load and rb.checkpoint):
@@ -1451,7 +1510,7 @@ class RollbackLog(renpy.object.Object):
 
             # Otherwise, just give up.
 
-            print "Can't find a place to rollback to. Not rolling back."
+            print("Can't find a place to rollback to. Not rolling back.")
 
             revlog.reverse()
             self.log = self.log + revlog
@@ -1468,9 +1527,6 @@ class RollbackLog(renpy.object.Object):
             if not renpy.game.script.has_label(rb.context.current):
                 break
 
-            if self.rollback_limit <= 0:
-                break
-
             revlog.append(self.log.pop())
 
         # Decide if we're replacing the current context (rollback command),
@@ -1503,7 +1559,7 @@ class RollbackLog(renpy.object.Object):
             self.log.append(retained)
 
         # Disable the next transition, as it's pointless. (Only when not used with a label.)
-        renpy.game.interface.suppress_transition = True
+        renpy.game.interface.suppress_transition = abnormal
 
         # If necessary, reset the RNG.
         if force:
@@ -1511,7 +1567,7 @@ class RollbackLog(renpy.object.Object):
             self.forward = [ ]
 
         # Flag that we're in the transition immediately after a rollback.
-        renpy.game.after_rollback = True
+        renpy.game.after_rollback = abnormal
 
         # Stop the sounds.
         renpy.audio.audio.rollback()
@@ -1524,7 +1580,6 @@ class RollbackLog(renpy.object.Object):
         else:
             raise renpy.game.RestartContext(label)
 
-
     def freeze(self, wait=None):
         """
         This is called to freeze the store and the log, in preparation
@@ -1562,7 +1617,7 @@ class RollbackLog(renpy.object.Object):
         """
 
         # Fix up old screens.
-        renpy.display.screen.before_restart() # @UndefinedVariable
+        renpy.display.screen.before_restart()  # @UndefinedVariable
 
         # Set us up as the game log.
         renpy.game.log = self
@@ -1596,7 +1651,6 @@ class RollbackLog(renpy.object.Object):
 
         # Because of the rollback, we never make it this far.
 
-
     def build_identifier_cache(self):
 
         if self.identifier_cache is not None:
@@ -1627,16 +1681,16 @@ class RollbackLog(renpy.object.Object):
         return self.identifier_cache.get(identifier, None)
 
 
-def py_exec_bytecode(bytecode, hide=False, globals=None, locals=None, store="store"): #@ReservedAssignment
+def py_exec_bytecode(bytecode, hide=False, globals=None, locals=None, store="store"):  # @ReservedAssignment
 
     if hide:
-        locals = { } #@ReservedAssignment
+        locals = { }  # @ReservedAssignment
 
     if globals is None:
-        globals = store_dicts[store] #@ReservedAssignment
+        globals = store_dicts[store]  # @ReservedAssignment
 
     if locals is None:
-        locals = globals #@ReservedAssignment
+        locals = globals  # @ReservedAssignment
 
     exec bytecode in globals, locals
 
@@ -1647,24 +1701,25 @@ def py_exec(source, hide=False, store=None):
         store = store_dicts["store"]
 
     if hide:
-        locals = { } #@ReservedAssignment
+        locals = { }  # @ReservedAssignment
     else:
-        locals = store #@ReservedAssignment
+        locals = store  # @ReservedAssignment
 
     exec py_compile(source, 'exec') in store, locals
 
 
-def py_eval_bytecode(bytecode, globals=None, locals=None): #@ReservedAssignment
+def py_eval_bytecode(bytecode, globals=None, locals=None):  # @ReservedAssignment
 
     if globals is None:
-        globals = store_dicts["store"] #@ReservedAssignment
+        globals = store_dicts["store"]  # @ReservedAssignment
 
     if locals is None:
-        locals = globals #@ReservedAssignment
+        locals = globals  # @ReservedAssignment
 
     return eval(bytecode, globals, locals)
 
-def py_eval(code, globals=None, locals=None): #@ReservedAssignment
+
+def py_eval(code, globals=None, locals=None):  # @ReservedAssignment
     if isinstance(code, basestring):
         code = py_compile(code, 'eval')
     return py_eval_bytecode(code, globals, locals)
@@ -1693,13 +1748,13 @@ def raise_at_location(e, loc):
 class StoreProxy(object):
 
     def __getattr__(self, k):
-        return getattr(renpy.store, k) #@UndefinedVariable
+        return getattr(renpy.store, k)  # @UndefinedVariable
 
     def __setattr__(self, k, v):
-        setattr(renpy.store, k, v) #@UndefinedVariable
+        setattr(renpy.store, k, v)  # @UndefinedVariable
 
     def __delattr__(self, k):
-        delattr(renpy.store, k) #@UndefinedVariable
+        delattr(renpy.store, k)  # @UndefinedVariable
 
 
 # Code for pickling bound methods.
@@ -1713,6 +1768,7 @@ def method_pickle(method):
 
     return method_unpickle, (obj, name)
 
+
 def method_unpickle(obj, name):
     return getattr(obj, name)
 
diff --git a/renpy/savelocation.py b/renpy/savelocation.py
index 40248d2..70c700d 100644
--- a/renpy/savelocation.py
+++ b/renpy/savelocation.py
@@ -36,6 +36,7 @@ import shutil
 
 disk_lock = threading.RLock()
 
+
 class FileLocation(object):
     """
     A location that saves files to a directory on disk.
@@ -75,14 +76,12 @@ class FileLocation(object):
         # The data loaded from the persistent file.
         self.persistent_data = None
 
-
     def filename(self, slotname):
         """
         Given a slot name, returns a filename.
         """
 
-        return os.path.join(self.directory, slotname + renpy.savegame_suffix)
-
+        return os.path.join(self.directory, renpy.exports.fsencode(slotname + renpy.savegame_suffix))
 
     def scan(self):
         """
@@ -121,14 +120,16 @@ class FileLocation(object):
                 if slotname not in new_mtimes:
                     clear_slot(slotname)
 
-            if os.path.exists(self.persistent):
-                mtime = os.path.getmtime(self.persistent)
-
-                if mtime != self.persistent_mtime:
-                    data = renpy.persistent.load(self.persistent)
-                    self.persistent_mtime = mtime
-                    self.persistent_data = data
+            for pfn in [ self.persistent + ".new", self.persistent ]:
+                if os.path.exists(pfn):
+                    mtime = os.path.getmtime(pfn)
 
+                    if mtime != self.persistent_mtime:
+                        data = renpy.persistent.load(pfn)
+                        if data is not None:
+                            self.persistent_mtime = mtime
+                            self.persistent_data = data
+                            break
 
     def save(self, slotname, record):
         """
@@ -150,7 +151,6 @@ class FileLocation(object):
 
         return list(self.mtimes)
 
-
     def mtime(self, slotname):
         """
         For a slot, returns the time the object was saved in that
@@ -161,7 +161,6 @@ class FileLocation(object):
 
         return self.mtimes.get(slotname, None)
 
-
     def json(self, slotname):
         """
         Returns the JSON data for slotname.
@@ -197,7 +196,6 @@ class FileLocation(object):
             finally:
                 zf.close()
 
-
     def screenshot(self, slotname):
         """
         Returns a displayable that show the screenshot for this slot.
@@ -263,7 +261,6 @@ class FileLocation(object):
 
             self.scan()
 
-
     def rename(self, old, new):
         """
         If old exists, renames it to new.
@@ -324,11 +321,13 @@ class FileLocation(object):
                 return
 
             fn = self.persistent
+            fn_tmp = fn + ".tmp"
             fn_new = fn + ".new"
 
-            with open(fn_new, "wb") as f:
+            with open(fn_tmp, "wb") as f:
                 f.write(data)
 
+            safe_rename(fn_tmp, fn_new)
             safe_rename(fn_new, fn)
 
     def unlink_persistent(self):
@@ -347,6 +346,7 @@ class FileLocation(object):
 
         return self.directory == other.directory
 
+
 class MultiLocation(object):
     """
     A location that saves in multiple places. When loading or otherwise
@@ -425,7 +425,6 @@ class MultiLocation(object):
 
         return l.json(slotname)
 
-
     def screenshot(self, slotname):
         l = self.newest(slotname)
 
@@ -491,6 +490,7 @@ quit_scan_thread = False
 # The condition we wait on.
 scan_thread_condition = threading.Condition()
 
+
 def run_scan_thread():
     global quit_scan_thread
 
@@ -506,6 +506,7 @@ def run_scan_thread():
         with scan_thread_condition:
             scan_thread_condition.wait(5.0)
 
+
 def quit():  # @ReservedAssignment
     global quit_scan_thread
 
@@ -515,6 +516,7 @@ def quit():  # @ReservedAssignment
 
     scan_thread.join()
 
+
 def init():
     global scan_thread
 
@@ -524,7 +526,7 @@ def init():
     location.add(FileLocation(renpy.config.savedir))
 
     # 2. Game-local savedir.
-    if not renpy.mobile:
+    if (not renpy.mobile) and (not renpy.macapp):
         path = os.path.join(renpy.config.gamedir, "saves")
         location.add(FileLocation(path))
 
@@ -535,4 +537,3 @@ def init():
 
     scan_thread = threading.Thread(target=run_scan_thread)
     scan_thread.start()
-
diff --git a/renpy/screenlang.py b/renpy/screenlang.py
index 2a5d0b1..53adc46 100644
--- a/renpy/screenlang.py
+++ b/renpy/screenlang.py
@@ -31,6 +31,8 @@ filename = None
 new_variable_serial = 0
 
 # Returns the name of a new variable.
+
+
 @contextlib.contextmanager
 def new_variable():
     global new_variable_serial
@@ -39,11 +41,13 @@ def new_variable():
     yield "_%d" % new_variable_serial
     new_variable_serial -= 1
 
+
 def increment_lineno(node, amount):
     for node in ast.walk(node):
         if hasattr(node, 'lineno'):
             node.lineno += amount
 
+
 class LineNumberNormalizer(ast.NodeVisitor):
 
     def __init__(self):
@@ -64,6 +68,7 @@ class LineNumberNormalizer(ast.NodeVisitor):
 # The parser that things are being added to.
 parser = None
 
+
 class Positional(object):
     """
     This represents a positional parameter to a function.
@@ -78,6 +83,7 @@ class Positional(object):
 # Used to generate the documentation
 all_keyword_names = set()
 
+
 class Keyword(object):
     """
     This represents an optional keyword parameter to a function.
@@ -104,6 +110,7 @@ STYLE_PREFIXES = [
     'selected_activate_',
 ]
 
+
 class Style(object):
     """
     This represents a style parameter to a function.
@@ -222,7 +229,6 @@ class Parser(object):
                 rv.extend(c)
                 count += 1
 
-
         return rv
 
     def parse_eval(self, expr, lineno=1):
@@ -236,7 +242,7 @@ class Parser(object):
 
         try:
             rv = ast.parse(expr, 'eval').body[0].value
-        except SyntaxError, e:
+        except SyntaxError as e:
             raise renpy.parser.ParseError(
                 filename,
                 lineno + e[1][1] - 1,
@@ -259,7 +265,7 @@ class Parser(object):
 
         try:
             rv = ast.parse(code, 'exec')
-        except SyntaxError, e:
+        except SyntaxError as e:
 
             raise renpy.parser.ParseError(
                 filename,
@@ -301,6 +307,7 @@ class Parser(object):
 # A singleton value.
 many = renpy.object.Sentinel("many")
 
+
 class FunctionStatementParser(Parser):
     """
     This is responsible for parsing function statements.
@@ -494,139 +501,139 @@ all_statements = [ ]
 childbearing_statements = [ ]
 
 position_property_names = [
-        "anchor",
-        "xanchor",
-        "yanchor",
-        "pos",
-        "xpos",
-        "ypos",
-        "align",
-        "xalign",
-        "yalign",
-        "xoffset",
-        "yoffset",
-        "maximum",
-        "xmaximum",
-        "ymaximum",
-        "area",
-        "clipping",
-        "xfill",
-        "yfill",
-        # no center, since it can conflict with the center transform.
-        "xcenter",
-        "ycenter",
-        "xsize",
-        "ysize",
-        "xysize",
-        "alt",
-        "debug",
-        ]
+    "anchor",
+    "xanchor",
+    "yanchor",
+    "pos",
+    "xpos",
+    "ypos",
+    "align",
+    "xalign",
+    "yalign",
+    "xoffset",
+    "yoffset",
+    "maximum",
+    "xmaximum",
+    "ymaximum",
+    "area",
+    "clipping",
+    "xfill",
+    "yfill",
+    # no center, since it can conflict with the center transform.
+    "xcenter",
+    "ycenter",
+    "xsize",
+    "ysize",
+    "xysize",
+    "alt",
+    "debug",
+    ]
 
 position_properties = [ Style(i) for i in position_property_names ]
 text_position_properties = [ PrefixStyle("text_", i) for i in position_property_names ]
 side_position_properties = [ PrefixStyle("side_", i) for i in position_property_names ]
 
 text_property_names = [
-        "antialias",
-        "vertical",
-        "black_color",
-        "bold",
-        "color",
-        "drop_shadow",
-        "drop_shadow_color",
-        "first_indent",
-        "font",
-        "size",
-        "hyperlink_functions",
-        "italic",
-        "justify",
-        "kerning",
-        "language",
-        "layout",
-        "line_leading",
-        "line_spacing",
-        "minwidth",
-        "min_width",
-        "newline_indent",
-        "outlines",
-        "rest_indent",
-        "ruby_style",
-        "slow_cps",
-        "slow_cps_multiplier",
-        "slow_abortable",
-        "strikethrough",
-        "text_align",
-        "text_y_fudge",
-        "underline",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        ]
+    "antialias",
+    "vertical",
+    "black_color",
+    "bold",
+    "color",
+    "drop_shadow",
+    "drop_shadow_color",
+    "first_indent",
+    "font",
+    "size",
+    "hyperlink_functions",
+    "italic",
+    "justify",
+    "kerning",
+    "language",
+    "layout",
+    "line_leading",
+    "line_spacing",
+    "minwidth",
+    "min_width",
+    "newline_indent",
+    "outlines",
+    "rest_indent",
+    "ruby_style",
+    "slow_cps",
+    "slow_cps_multiplier",
+    "slow_abortable",
+    "strikethrough",
+    "text_align",
+    "text_y_fudge",
+    "underline",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    ]
 
 text_properties = [ Style(i) for i in text_property_names ]
 text_text_properties = [ PrefixStyle("text_", i) for i in text_property_names ]
 
 window_properties = [ Style(i) for i in [
-        "background",
-        "foreground",
-        "left_margin",
-        "right_margin",
-        "bottom_margin",
-        "top_margin",
-        "xmargin",
-        "ymargin",
-        "left_padding",
-        "right_padding",
-        "top_padding",
-        "bottom_padding",
-        "xpadding",
-        "ypadding",
-        "size_group",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        ] ]
+    "background",
+    "foreground",
+    "left_margin",
+    "right_margin",
+    "bottom_margin",
+    "top_margin",
+    "xmargin",
+    "ymargin",
+    "left_padding",
+    "right_padding",
+    "top_padding",
+    "bottom_padding",
+    "xpadding",
+    "ypadding",
+    "size_group",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    ] ]
 
 button_properties = [ Style(i) for i in [
-        "sound",
-        "mouse",
-        "focus_mask",
-        "child",
-        "keyboard_focus",
-        ] ]
+    "sound",
+    "mouse",
+    "focus_mask",
+    "child",
+    "keyboard_focus",
+    ] ]
 
 bar_properties = [ Style(i) for i in [
-        "bar_vertical",
-        "bar_invert",
-        "bar_resizing",
-        "left_gutter",
-        "right_gutter",
-        "top_gutter",
-        "bottom_gutter",
-        "left_bar",
-        "right_bar",
-        "top_bar",
-        "bottom_bar",
-        "thumb",
-        "thumb_shadow",
-        "thumb_offset",
-        "mouse",
-        "unscrollable",
-        "keyboard_focus",
-        ] ]
+    "bar_vertical",
+    "bar_invert",
+    "bar_resizing",
+    "left_gutter",
+    "right_gutter",
+    "top_gutter",
+    "bottom_gutter",
+    "left_bar",
+    "right_bar",
+    "top_bar",
+    "bottom_bar",
+    "thumb",
+    "thumb_shadow",
+    "thumb_offset",
+    "mouse",
+    "unscrollable",
+    "keyboard_focus",
+    ] ]
 
 box_properties = [ Style(i) for i in [
-        "box_layout",
-        "box_wrap",
-        "box_reverse",
-        "order_reverse",
-        "spacing",
-        "first_spacing",
-        "fit_first",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        ] ]
+    "box_layout",
+    "box_wrap",
+    "box_reverse",
+    "order_reverse",
+    "spacing",
+    "first_spacing",
+    "fit_first",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    ] ]
 
 ui_properties = [
     Keyword("at"),
@@ -1101,12 +1108,12 @@ class ForParser(Parser):
             rv = self.parse_exec("%s = 0" % counter_name)
 
             rv.append(ast.For(
-                    target=pattern,
-                    iter=expression,
-                    body=children,
-                    orelse=[],
-                    lineno=lineno,
-                    col_offset=0))
+                target=pattern,
+                iter=expression,
+                body=children,
+                orelse=[],
+                lineno=lineno,
+                col_offset=0))
 
         return rv
 
@@ -1214,10 +1221,10 @@ class ScreenLangScreen(renpy.object.Object):
         self.code = None
 
         # The variant of screen we're defining.
-        self.variant = "None" # expr.
+        self.variant = "None"  # expr.
 
         # Should we predict this screen?
-        self.predict = "None" # expr.
+        self.predict = "None"  # expr.
 
         # The parameters this screen takes.
         self.parameters = None
@@ -1258,7 +1265,6 @@ class ScreenLangScreen(renpy.object.Object):
         renpy.python.py_exec_bytecode(self.code.bytecode, locals=scope)
 
 
-
 class ScreenParser(Parser):
 
     def __init__(self):
@@ -1354,6 +1360,7 @@ class ScreenParser(Parser):
 screen_parser = ScreenParser()
 screen_parser.add(all_statements)
 
+
 def parse_screen(l):
     """
     Parses the screen statement.
diff --git a/renpy/script.py b/renpy/script.py
index f02d5bf..c040a8c 100644
--- a/renpy/script.py
+++ b/renpy/script.py
@@ -22,12 +22,13 @@
 # This file contains code that is responsible for storing and executing a
 # Ren'Py script.
 
+from __future__ import print_function
 import renpy
 
+import hashlib
 import os
 import imp
 import difflib
-import md5
 import time
 import marshal
 import struct
@@ -51,12 +52,14 @@ RPYC2_HEADER = "RENPY RPC2"
 # A string
 BYTECODE_FILE = "cache/bytecode.rpyb"
 
+
 class ScriptError(Exception):
     """
     Exception that is raised if the script is somehow inconsistent,
     or otherwise wrong.
     """
 
+
 def collapse_stmts(stmts):
     """
     Returns a flat list containing every statement in the tree
@@ -70,6 +73,7 @@ def collapse_stmts(stmts):
 
     return rv
 
+
 class Script(object):
     """
     This class represents a Ren'Py script, which is parsed out of a
@@ -130,11 +134,13 @@ class Script(object):
 
         self.serial = 0
 
-        self.digest = md5.md5(renpy.version_only)
+        self.digest = hashlib.md5(renpy.version_only)
 
         self.loaded_rpy = False
         self.backup_list = [ ]
 
+        self.duplicate_labels = [ ]
+
     def choose_backupdir(self):
 
         if renpy.mobile:
@@ -145,7 +151,7 @@ class Script(object):
                 return None
 
         import __main__
-        backups = __main__.path_to_saves(renpy.config.gamedir, "backups") # @UndefinedVariable
+        backups = __main__.path_to_saves(renpy.config.gamedir, "backups")  # @UndefinedVariable
 
         if backups is None:
             return
@@ -195,7 +201,7 @@ class Script(object):
                 continue
 
             try:
-                os.makedirs(os.path.dirname(target_fn), 0700)
+                os.makedirs(os.path.dirname(target_fn), 0o700)
             except:
                 pass
 
@@ -204,7 +210,6 @@ class Script(object):
             except:
                 pass
 
-
     def scan_script_files(self):
         """
         Scan the directories for script files.
@@ -220,7 +225,7 @@ class Script(object):
         # Similar, but for modules:
         self.module_files = [ ]
 
-        for dir, fn in dirlist: #@ReservedAssignment
+        for dir, fn in dirlist:  # @ReservedAssignment
 
             if fn.endswith(".rpy"):
                 if dir is None:
@@ -255,7 +260,7 @@ class Script(object):
 
         initcode = [ ]
 
-        for fn, dir in script_files: #@ReservedAssignment
+        for fn, dir in script_files:  # @ReservedAssignment
             self.load_appropriate_file(".rpyc", ".rpy", dir, fn, initcode)
 
         # Make the sort stable.
@@ -266,10 +271,9 @@ class Script(object):
 
         self.initcode = [ (prio, code) for prio, index, code in initcode ]
 
-
     def load_module(self, name):
 
-        files = [ (fn, dir) for fn, dir in self.module_files if fn == name ] #@ReservedAssignment
+        files = [ (fn, dir) for fn, dir in self.module_files if fn == name ]  # @ReservedAssignment
 
         if not files:
             raise Exception("Module %s could not be loaded." % name)
@@ -277,7 +281,7 @@ class Script(object):
         if len(files) > 2:
             raise Exception("Module %s ambiguous, multiple variants exist." % name)
 
-        fn, dir = files[0] #@ReservedAssignment
+        fn, dir = files[0]  # @ReservedAssignment
         initcode = [ ]
 
         self.load_appropriate_file(".rpymc", ".rpym", dir, fn, initcode)
@@ -301,7 +305,6 @@ class Script(object):
                 s.name = (fn, version, self.serial)
                 self.serial += 1
 
-
     def merge_names(self, old_stmts, new_stmts):
 
         old_stmts = collapse_stmts(old_stmts)
@@ -402,16 +405,25 @@ class Script(object):
                 name = node.name
 
                 if name in self.namemap:
+
+                    bad_name = name
+                    bad_node = node
+                    old_node = self.namemap[name]
+
                     if not isinstance(bad_name, basestring):
-                        bad_name = name
-                        bad_node = node
-                        old_node = self.namemap[name]
 
-            if bad_name is not None:
-                raise ScriptError("Name %s is defined twice, at %s:%d and %s:%d." %
-                                  (repr(bad_name),
-                                   old_node.filename, old_node.linenumber,
-                                   bad_node.filename, bad_node.linenumber))
+                        raise ScriptError("Name %s is defined twice, at %s:%d and %s:%d." %
+                                          (repr(bad_name),
+                                           old_node.filename, old_node.linenumber,
+                                           bad_node.filename, bad_node.linenumber))
+
+                    else:
+                        self.duplicate_labels.append(
+                            u'The label {} is defined twice, at\n  File "{}", line {} and\n  File "{}", line {}.'.format(
+                                bad_name, old_node.filename, old_node.linenumber, bad_node.filename, bad_node.linenumber))
+
+                # Add twice, so we can find duplicates in the same file.
+                self.namemap[name] = node
 
         self.update_bytecode()
 
@@ -448,7 +460,6 @@ class Script(object):
         for _i in range(3):
             f.write(struct.pack("III", 0, 0, 0))
 
-
     def write_rpyc_data(self, f, slot, data):
         """
         Writes data into `slot` of a .rpyc file. The data should be a binary
@@ -524,8 +535,7 @@ class Script(object):
         # Generate translate nodes.
         renpy.translation.restructure(stmts)
 
-
-    def load_file(self, dir, fn): #@ReservedAssignment
+    def load_file(self, dir, fn):  # @ReservedAssignment
 
         if fn.endswith(".rpy") or fn.endswith(".rpym"):
 
@@ -565,27 +575,31 @@ class Script(object):
 
             self.assign_names(stmts, fullfn)
 
-            try:
-                f = file(rpycfn, "wb")
+            if not renpy.macapp:
 
-                self.write_rpyc_header(f)
-                self.write_rpyc_data(f, 1, dumps((data, stmts), 2))
-            except:
-                pass
+                try:
+                    f = file(rpycfn, "wb")
+
+                    self.write_rpyc_header(f)
+                    self.write_rpyc_data(f, 1, dumps((data, stmts), 2))
+                except:
+                    pass
 
             self.static_transforms(stmts)
 
-            try:
-                self.write_rpyc_data(f, 2, dumps((data, stmts), 2))
+            if not renpy.macapp:
 
-                with open(fullfn, "rU") as fullf:
-                    rpydigest = md5.md5(fullf.read()).digest()
+                try:
+                    self.write_rpyc_data(f, 2, dumps((data, stmts), 2))
 
-                self.write_rpyc_md5(f, rpydigest)
+                    with open(fullfn, "rU") as fullf:
+                        rpydigest = hashlib.md5(fullf.read()).digest()
 
-                f.close()
-            except:
-                pass
+                    self.write_rpyc_md5(f, rpydigest)
+
+                    f.close()
+                except:
+                    pass
 
             self.loaded_rpy = True
 
@@ -615,7 +629,7 @@ class Script(object):
                     return None, None
 
                 if data is None:
-                    print "Failed to load", fn
+                    print("Failed to load", fn)
                     return None, None
 
                 if not isinstance(data, dict):
@@ -638,7 +652,7 @@ class Script(object):
 
         return data, stmts
 
-    def load_appropriate_file(self, compiled, source, dir, fn, initcode): #@ReservedAssignment
+    def load_appropriate_file(self, compiled, source, dir, fn, initcode):  # @ReservedAssignment
         # This can only be a .rpyc file, since we're loading it
         # from an archive.
 
@@ -652,8 +666,8 @@ class Script(object):
                 raise Exception("Could not load from archive %s." % (lastfn,))
 
             f = renpy.loader.load(fn + compiled)
-            f.seek(-md5.digest_size, 2)
-            digest = f.read(md5.digest_size)
+            f.seek(-hashlib.md5().digest_size, 2)
+            digest = f.read(hashlib.md5().digest_size)
             f.close()
 
         else:
@@ -667,15 +681,15 @@ class Script(object):
 
             if os.path.exists(rpyfn):
                 with open(rpyfn, "rU") as f:
-                    rpydigest = md5.md5(f.read()).digest()
+                    rpydigest = hashlib.md5(f.read()).digest()
             else:
                 rpydigest = None
 
             try:
                 if os.path.exists(rpycfn):
                     with open(rpycfn, "rb") as f:
-                        f.seek(-md5.digest_size, 2)
-                        rpycdigest = f.read(md5.digest_size)
+                        f.seek(-hashlib.md5().digest_size, 2)
+                        rpycdigest = f.read(hashlib.md5().digest_size)
                 else:
                     rpycdigest = None
             except:
@@ -684,7 +698,7 @@ class Script(object):
             if os.path.exists(rpyfn) and os.path.exists(rpycfn):
 
                 # Are we forcing a compile?
-                force_compile = renpy.game.args.compile # @UndefinedVariable
+                force_compile = renpy.game.args.compile  # @UndefinedVariable
 
                 # Use the source file here since it'll be loaded if it exists.
                 lastfn = rpyfn
@@ -698,11 +712,11 @@ class Script(object):
                         data, stmts = self.load_file(dir, fn + compiled)
 
                         if data is None:
-                            print "Could not load " + rpycfn
+                            print("Could not load " + rpycfn)
 
                 except:
                     if "RENPY_RPYC_EXCEPTIONS" in os.environ:
-                        print "While loading", rpycfn
+                        print("While loading", rpycfn)
                         raise
 
                     pass
@@ -739,7 +753,6 @@ class Script(object):
 
         self.digest.update(digest)
 
-
     def init_bytecode(self):
         """
         Init/Loads the bytecode cache.
@@ -781,7 +794,7 @@ class Script(object):
                     elif i.mode == 'eval':
                         code = renpy.python.py_compile_eval_bytecode(i.source, filename=i.location[0], lineno=i.location[1])
 
-                except SyntaxError, e:
+                except SyntaxError as e:
 
                     text = e.text
 
@@ -794,11 +807,11 @@ class Script(object):
                         text = text.decode("latin-1")
 
                     pem = renpy.parser.ParseError(
-                        filename = e.filename,
-                        number = e.lineno,
-                        msg = e.msg,
-                        line = text,
-                        pos = e.offset)
+                        filename=e.filename,
+                        number=e.lineno,
+                        msg=e.msg,
+                        line=text,
+                        pos=e.offset)
 
                     renpy.parser.parse_errors.append(pem.message)
 
@@ -811,8 +824,10 @@ class Script(object):
 
         self.all_pycode = [ ]
 
-
     def save_bytecode(self):
+        if renpy.macapp:
+            return
+
         if self.bytecode_dirty:
             try:
                 fn = renpy.loader.get_path(BYTECODE_FILE)
@@ -823,7 +838,6 @@ class Script(object):
             except:
                 pass
 
-
     def lookup(self, label):
         """
         Looks up the given label in the game. If the label is not found,
@@ -862,3 +876,15 @@ class Script(object):
             i.analyze()
 
         self.need_analysis = [ ]
+
+    def report_duplicate_labels(self):
+        if not renpy.config.developer:
+            return
+
+        if renpy.config.ignore_duplicate_labels:
+            return
+
+        renpy.parser.parse_errors = self.duplicate_labels
+
+        if renpy.parser.report_parse_errors():
+            raise SystemExit(-1)
diff --git a/renpy/scriptedit.py b/renpy/scriptedit.py
index f14c9ac..ed063d8 100644
--- a/renpy/scriptedit.py
+++ b/renpy/scriptedit.py
@@ -31,6 +31,7 @@ import codecs
 # that line.
 lines = { }
 
+
 class Line(object):
     """
     Represents a logical line in a file.
@@ -116,7 +117,7 @@ def insert_line_before(code, filename, linenumber):
     if renpy.config.clear_lines:
         raise Exception("config.clear_lines must be False for script editing to work.")
 
-    if not renpy.game.args.compile: # @UndefinedVariable
+    if not renpy.game.args.compile:  # @UndefinedVariable
         raise Exception("The compile flag must have been given for script editing to work.")
 
     old_line = lines[filename, linenumber]
@@ -148,6 +149,7 @@ def insert_line_before(code, filename, linenumber):
 
     lines[filename, linenumber] = new_line
 
+
 def remove_line(filename, linenumber):
     """
     Removes `linenumber` from `filename`. The line must exist and correspond
@@ -157,10 +159,9 @@ def remove_line(filename, linenumber):
     if renpy.config.clear_lines:
         raise Exception("config.clear_lines must be False for script editing to work.")
 
-    if not renpy.game.args.compile: # @UndefinedVariable
+    if not renpy.game.args.compile:  # @UndefinedVariable
         raise Exception("The compile flag must have been given for script editing to work.")
 
-
     line = lines[filename, linenumber]
 
     with codecs.open(line.filename, "r", "utf-8") as f:
@@ -179,6 +180,7 @@ def remove_line(filename, linenumber):
 
         renpy.loader.add_auto(line.filename, force=True)
 
+
 def nodes_on_line(filename, linenumber):
     """
     Returns a list of nodes that are found on the given line.
@@ -192,6 +194,7 @@ def nodes_on_line(filename, linenumber):
 
     return rv
 
+
 def first_and_last_nodes(nodes):
     """
     Finds the first and last nodes in `nodes`, a list of nodes. This assumes
@@ -269,6 +272,7 @@ def add_to_ast_before(code, filename, linenumber):
 
     renpy.ast.chain_block(block, old)
 
+
 def remove_from_ast(filename, linenumber):
     """
     Removes from the AST all statements that happen to be at `filename`
@@ -294,12 +298,21 @@ def remove_from_ast(filename, linenumber):
 
     renpy.game.script.all_stmts = new_stmts
 
-    adjust_ast_linenumbers(filename, linenumber, -1)
+    namemap = renpy.game.script.namemap
+
+    # This is fairly slow - when we remove a node, we have to replace it with
+    # the next node. But if we then remove the next node, we have to replace it
+    # again. So we just walk all the known names to do this.
+    for k in list(namemap):
+        if namemap[k] in nodes:
+            namemap[k] = last.next
 
+    adjust_ast_linenumbers(filename, linenumber, -1)
 
 
 serial = 1
 
+
 def test_add():
 
     global serial
@@ -314,6 +327,7 @@ def test_add():
     insert_line_before(s, filename, linenumber)
     renpy.exports.restart_interaction()
 
+
 def test_remove():
 
     node = renpy.game.script.lookup(renpy.game.context().current)
diff --git a/renpy/sl2/slast.py b/renpy/sl2/slast.py
index a36cda7..cd5112b 100644
--- a/renpy/sl2/slast.py
+++ b/renpy/sl2/slast.py
@@ -43,7 +43,7 @@ from renpy.display.predict import displayable as predict_displayable
 
 from renpy.python import py_eval_bytecode
 from renpy.pyanalysis import Analysis, NOT_CONST, GLOBAL_CONST, ccache
-import md5
+import hashlib
 
 # This file contains the abstract syntax tree for a screen language
 # screen.
@@ -61,6 +61,7 @@ filename = '<screen language>'
 # A log that's used for profiling information.
 profile_log = renpy.log.open("profile_screen", developer=True, append=False, flush=False)
 
+
 def compile_expr(node):
     """
     Wraps the node in a python AST, and compiles it.
@@ -203,7 +204,6 @@ class SLNode(object):
 
         raise Exception("copy not implemented by " + type(self).__name__)
 
-
     def report_traceback(self, name, last):
         if last:
             return None
@@ -288,6 +288,7 @@ class SLNode(object):
 # A sentinel used to indicate a keyword argument was not given.
 NotGiven = renpy.object.Sentinel("NotGiven")
 
+
 class SLBlock(SLNode):
     """
     Represents a screen language block that can contain keyword arguments
@@ -340,7 +341,7 @@ class SLBlock(SLNode):
                 keyword_values[k] = py_eval_bytecode(compile_expr(node))
             else:
                 keyword_keys.append(ast.Str(s=k))
-                keyword_exprs.append(node) # Will be compiled as part of ast.Dict below.
+                keyword_exprs.append(node)  # Will be compiled as part of ast.Dict below.
 
             self.constant = min(self.constant, const)
 
@@ -368,7 +369,6 @@ class SLBlock(SLNode):
                 self.last_keyword = True
                 break
 
-
     def execute(self, context):
 
         # Note: SLBlock.execute() is inlined in various locations for performance
@@ -423,6 +423,7 @@ class SLBlock(SLNode):
 
 list_or_tuple = (list, tuple)
 
+
 class SLCache(object):
     """
     The type of cache associated with an SLDisplayable.
@@ -479,6 +480,7 @@ class SLCache(object):
 # the parent.
 NO_DISPLAYABLE = renpy.display.layout.Null()
 
+
 class SLDisplayable(SLBlock):
     """
     A screen language AST node that corresponds to a displayable being
@@ -604,7 +606,7 @@ class SLDisplayable(SLBlock):
                 has_values = True
             else:
                 values.append(use_expression)
-                exprs.append(node) # Will be compiled as part of the tuple.
+                exprs.append(node)  # Will be compiled as part of the tuple.
                 has_exprs = True
 
             self.constant = min(self.constant, const)
@@ -821,8 +823,8 @@ class SLDisplayable(SLBlock):
 
                 imagemap = self.imagemap
 
-                cache.copy_on_change = False # We no longer need to copy on change.
-                cache.children = None # Re-add the children.
+                cache.copy_on_change = False  # We no longer need to copy on change.
+                cache.children = None  # Re-add the children.
 
             if debug:
                 if reused:
@@ -1217,6 +1219,7 @@ class SLIf(SLNode):
 
         return False
 
+
 class SLShowIf(SLNode):
     """
     The AST node that corresponds to the showif statement.
@@ -1339,7 +1342,6 @@ class SLFor(SLBlock):
 
         analysis.pop_control()
 
-
     def prepare(self, analysis):
         node = ccache.ast_eval(self.expression)
 
@@ -1457,6 +1459,7 @@ class SLPass(SLNode):
 
         return rv
 
+
 class SLDefault(SLNode):
 
     def __init__(self, loc, variable, expression):
@@ -1641,7 +1644,6 @@ class SLUse(SLNode):
             if cache is None:
                 context.cache[self.serial] = cache = { }
 
-
         # Evaluate the arguments.
         try:
             if self.args:
@@ -1711,7 +1713,6 @@ class SLTransclude(SLNode):
     def __init__(self, loc):
         SLNode.__init__(self, loc)
 
-
     def copy(self, transclude):
         rv = self.instantiate(transclude)
         rv.constant = transclude
@@ -1798,10 +1799,10 @@ class SLScreen(SLBlock):
         self.tag = None
 
         # The variant of screen we're defining.
-        self.variant = "None" # expr.
+        self.variant = "None"  # expr.
 
         # Should we predict this screen?
-        self.predict = "None" # expr.
+        self.predict = "None"  # expr.
 
         # The parameters this screen takes.
         self.parameters = None
@@ -1874,7 +1875,6 @@ class SLScreen(SLBlock):
             self.not_const_ast = self.const_ast
             targets = [ self.const_ast ]
 
-
         for ast in targets:
             analysis = ast.analysis = Analysis(None)
 
@@ -1978,6 +1978,7 @@ class SLScreen(SLBlock):
         for i in context.children:
             renpy.ui.implicit_add(i)
 
+
 class ScreenCache(object):
 
     def __init__(self):
@@ -1992,14 +1993,15 @@ scache = ScreenCache()
 
 CACHE_FILENAME = "cache/screens.rpyb"
 
+
 def load_cache():
-    if renpy.game.args.compile: # @UndefinedVariable
+    if renpy.game.args.compile:  # @UndefinedVariable
         return
 
     try:
         f = renpy.loader.load(CACHE_FILENAME)
 
-        digest = f.read(md5.digest_size)
+        digest = f.read(hashlib.md5().digest_size)
         if digest != renpy.game.script.digest.digest():
             return
 
@@ -2014,10 +2016,14 @@ def load_cache():
     except:
         pass
 
+
 def save_cache():
     if not scache.updated:
         return
 
+    if renpy.macapp:
+        return
+
     try:
         data = zlib.compress(dumps(scache, 2), 9)
 
@@ -2026,5 +2032,3 @@ def save_cache():
             f.write(data)
     except:
         pass
-
-
diff --git a/renpy/sl2/sldisplayables.py b/renpy/sl2/sldisplayables.py
index 85be711..a1d6f81 100644
--- a/renpy/sl2/sldisplayables.py
+++ b/renpy/sl2/sldisplayables.py
@@ -34,6 +34,7 @@ from renpy.sl2.slproperties import bar_properties, button_properties
 from renpy.sl2.slproperties import text_position_properties, text_text_properties
 from renpy.sl2.slproperties import side_position_properties
 
+
 class ShowIf(renpy.display.layout.Container):
     """
     This is a displayable that wraps displayables that are
@@ -102,7 +103,6 @@ class ShowIf(renpy.display.layout.Container):
         return self.child.get_placement()
 
 
-
 DisplayableParser("null", renpy.display.layout.Null, "default", 0)
 Keyword("width")
 Keyword("height")
@@ -210,8 +210,9 @@ add(window_properties)
 add(text_position_properties)
 add(text_text_properties)
 
+
 def sl2bar(context=None, **properties):
-    range = 1 #@ReservedAssignment
+    range = 1  # @ReservedAssignment
     value = 0
     width = None
     height = None
@@ -221,7 +222,7 @@ def sl2bar(context=None, **properties):
     if "height" in properties:
         height  = properties.pop("height")
     if "range" in properties:
-        range = properties.pop("range") #@ReservedAssignment
+        range = properties.pop("range")  # @ReservedAssignment
     if "value" in properties:
         value = properties.pop("value")
 
@@ -243,7 +244,7 @@ add(bar_properties)
 
 
 def sl2vbar(context=None, **properties):
-    range = 1 #@ReservedAssignment
+    range = 1  # @ReservedAssignment
     value = 0
     width = None
     height = None
@@ -253,7 +254,7 @@ def sl2vbar(context=None, **properties):
     if "height" in properties:
         height  = properties.pop("height")
     if "range" in properties:
-        range = properties.pop("range") #@ReservedAssignment
+        range = properties.pop("range")  # @ReservedAssignment
     if "value" in properties:
         value = properties.pop("value")
 
@@ -274,7 +275,6 @@ Keyword("unhovered")
 add(bar_properties)
 
 
-
 # Omit autobar. (behavior)
 
 def sl2viewport(**kwargs):
@@ -294,6 +294,7 @@ def sl2viewport(**kwargs):
 
     return rv
 
+
 def sl2vpgrid(**kwargs):
     """
     This converts the output of renpy.ui.viewport into something that
@@ -376,6 +377,7 @@ Keyword("id")
 for i in renpy.atl.PROPERTIES:
     Style(i)
 
+
 def sl2add(d, replaces=None, scope=None, **kwargs):
 
     if d is None:
diff --git a/renpy/sl2/slparser.py b/renpy/sl2/slparser.py
index 5a7f836..f576f01 100644
--- a/renpy/sl2/slparser.py
+++ b/renpy/sl2/slparser.py
@@ -48,6 +48,7 @@ all_statements = [ ]
 # Statements that can contain children.
 childbearing_statements = set()
 
+
 class Positional(object):
     """
     This represents a positional parameter to a function.
@@ -62,6 +63,7 @@ class Positional(object):
 # Used to generate the documentation
 all_keyword_names = set()
 
+
 class Keyword(object):
     """
     This represents an optional keyword parameter to a function.
@@ -75,6 +77,7 @@ class Keyword(object):
         if parser:
             parser.add(self)
 
+
 class Style(object):
     """
     This represents a style parameter to a function.
@@ -108,6 +111,11 @@ class PrefixStyle(object):
 
 class Parser(object):
 
+    # The number of children this statement takes, out of 0, 1, or "many".
+    # This defaults to "many" so the has statement errors out when not
+    # inside something that takes a single child.
+    nchildren = "many"
+
     def __init__(self, name):
 
         # The name of this object.
@@ -233,7 +241,6 @@ class Parser(object):
 
             seen_keywords.add(name)
 
-
             expr = l.comma_expression()
 
             target.keyword.append((name, expr))
@@ -261,7 +268,6 @@ class Parser(object):
 
                 parse_keyword(l, 'expected a keyword argument, colon, or end of line.')
 
-
         # The index of the child we're adding to this statement.
         child_index = 0
 
@@ -320,7 +326,6 @@ class Parser(object):
                 while not l.eol():
                     parse_keyword(l, "expected a keyword argument or end of line.")
 
-
     def add_positional(self, name):
         global parser
         parser = self
@@ -483,9 +488,8 @@ def register_sl_displayable(*args, **kwargs):
 class DisplayableParser(Parser):
 
     def __init__(self, name, displayable, style, nchildren=0, scope=False,
-        pass_context=False, imagemap=False, replaces=False, default_keywords={},
-        hotspot=False, default_properties=True):
-
+                 pass_context=False, imagemap=False, replaces=False, default_keywords={},
+                 hotspot=False, default_properties=True):
         """
         `scope`
             If true, the scope is passed into the displayable functionas a keyword
@@ -536,7 +540,6 @@ class DisplayableParser(Parser):
             add(renpy.sl2.slproperties.ui_properties)
             add(renpy.sl2.slproperties.position_properties)
 
-
     def parse_layout(self, loc, l, parent):
         return self.parse(loc, l, parent, True)
 
@@ -575,6 +578,7 @@ class DisplayableParser(Parser):
 
         return rv
 
+
 class IfParser(Parser):
 
     def __init__(self, name, node_type, parent_contents):
@@ -595,7 +599,6 @@ class IfParser(Parser):
         if not parent_contents:
             childbearing_statements.add(self)
 
-
     def parse(self, loc, l, parent):
 
         if self.parent_contents:
@@ -826,6 +829,7 @@ UseParser("use")
 Keyword("style_prefix")
 Keyword("style_group")
 
+
 class TranscludeParser(Parser):
 
     def parse(self, loc, l, parent):
@@ -953,6 +957,7 @@ Keyword("style_group")
 Keyword("style_prefix")
 Keyword("layer")
 
+
 def init():
     screen_parser.add(all_statements)
 
@@ -970,4 +975,3 @@ def parse_screen(l, loc):
     """
 
     return screen_parser.parse(loc, l, None)
-
diff --git a/renpy/sl2/slproperties.py b/renpy/sl2/slproperties.py
index ceae8e4..98dc989 100644
--- a/renpy/sl2/slproperties.py
+++ b/renpy/sl2/slproperties.py
@@ -22,111 +22,111 @@
 from renpy.sl2.slparser import Keyword, Style, PrefixStyle
 
 position_property_names = [
-        "anchor",
-        "xanchor",
-        "yanchor",
-        "pos",
-        "xpos",
-        "ypos",
-        "align",
-        "xalign",
-        "yalign",
-        "offset",
-        "xoffset",
-        "yoffset",
-        "maximum",
-        "xmaximum",
-        "ymaximum",
-        "area",
-        "clipping",
-        "xfill",
-        "yfill",
-        # no center, since it can conflict with the center transform.
-        "xcenter",
-        "ycenter",
-        "xsize",
-        "ysize",
-        "xysize",
-        "alt",
-        "debug",
-        ]
+    "anchor",
+    "xanchor",
+    "yanchor",
+    "pos",
+    "xpos",
+    "ypos",
+    "align",
+    "xalign",
+    "yalign",
+    "offset",
+    "xoffset",
+    "yoffset",
+    "maximum",
+    "xmaximum",
+    "ymaximum",
+    "area",
+    "clipping",
+    "xfill",
+    "yfill",
+    # no center, since it can conflict with the center transform.
+    "xcenter",
+    "ycenter",
+    "xsize",
+    "ysize",
+    "xysize",
+    "alt",
+    "debug",
+    ]
 
 position_properties = [ Style(i) for i in position_property_names ]
 text_position_properties = [ PrefixStyle("text_", i) for i in position_property_names ]
 side_position_properties = [ PrefixStyle("side_", i) for i in position_property_names ]
 
 text_property_names = [
-        "antialias",
-        "vertical",
-        "black_color",
-        "bold",
-        "color",
-        "drop_shadow",
-        "drop_shadow_color",
-        "first_indent",
-        "font",
-        "size",
-        "hyperlink_functions",
-        "italic",
-        "justify",
-        "kerning",
-        "language",
-        "layout",
-        "line_leading",
-        "line_spacing",
-        "minwidth",
-        "min_width",
-        "newline_indent",
-        "outlines",
-        "rest_indent",
-        "ruby_style",
-        "slow_cps",
-        "slow_cps_multiplier",
-        "slow_abortable",
-        "strikethrough",
-        "text_align",
-        "text_y_fudge",
-        "underline",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        "hinting",
-        "adjust_spacing",
-        ]
+    "antialias",
+    "vertical",
+    "black_color",
+    "bold",
+    "color",
+    "drop_shadow",
+    "drop_shadow_color",
+    "first_indent",
+    "font",
+    "size",
+    "hyperlink_functions",
+    "italic",
+    "justify",
+    "kerning",
+    "language",
+    "layout",
+    "line_leading",
+    "line_spacing",
+    "minwidth",
+    "min_width",
+    "newline_indent",
+    "outlines",
+    "rest_indent",
+    "ruby_style",
+    "slow_cps",
+    "slow_cps_multiplier",
+    "slow_abortable",
+    "strikethrough",
+    "text_align",
+    "text_y_fudge",
+    "underline",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    "hinting",
+    "adjust_spacing",
+    ]
 
 text_properties = [ Style(i) for i in text_property_names ]
 text_text_properties = [ PrefixStyle("text_", i) for i in text_property_names ]
 
 window_properties = [ Style(i) for i in [
-        "background",
-        "foreground",
-        "left_margin",
-        "right_margin",
-        "bottom_margin",
-        "top_margin",
-        "xmargin",
-        "ymargin",
-        "margin",
-        "left_padding",
-        "right_padding",
-        "top_padding",
-        "bottom_padding",
-        "xpadding",
-        "ypadding",
-        "padding",
-        "size_group",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        ] ]
+    "background",
+    "foreground",
+    "left_margin",
+    "right_margin",
+    "bottom_margin",
+    "top_margin",
+    "xmargin",
+    "ymargin",
+    "margin",
+    "left_padding",
+    "right_padding",
+    "top_padding",
+    "bottom_padding",
+    "xpadding",
+    "ypadding",
+    "padding",
+    "size_group",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    ] ]
 
 button_properties = [ Style(i) for i in [
-        "sound",
-        "mouse",
-        "focus_mask",
-        "child",
-        "keyboard_focus",
-        "key_events",
+    "sound",
+    "mouse",
+    "focus_mask",
+    "child",
+    "keyboard_focus",
+    "key_events",
     ] ] + [
         Keyword("action"),
         Keyword("clicked"),
@@ -140,40 +140,40 @@ button_properties = [ Style(i) for i in [
     ]
 
 bar_properties = [ Style(i) for i in [
-        "bar_vertical",
-        "bar_invert",
-        "bar_resizing",
-        "left_gutter",
-        "right_gutter",
-        "top_gutter",
-        "bottom_gutter",
-        "left_bar",
-        "right_bar",
-        "top_bar",
-        "bottom_bar",
-        "base_bar",
-        "thumb",
-        "thumb_shadow",
-        "thumb_offset",
-        "mouse",
-        "unscrollable",
-        "keyboard_focus",
-        ] ]
+    "bar_vertical",
+    "bar_invert",
+    "bar_resizing",
+    "left_gutter",
+    "right_gutter",
+    "top_gutter",
+    "bottom_gutter",
+    "left_bar",
+    "right_bar",
+    "top_bar",
+    "bottom_bar",
+    "base_bar",
+    "thumb",
+    "thumb_shadow",
+    "thumb_offset",
+    "mouse",
+    "unscrollable",
+    "keyboard_focus",
+    ] ]
 
 box_properties = [ Style(i) for i in [
-        "box_layout",
-        "box_wrap",
-        "box_reverse",
-        "order_reverse",
-        "spacing",
-        "first_spacing",
-        "fit_first",
-        "xfit",
-        "yfit",
-        "minimum",
-        "xminimum",
-        "yminimum",
-        ] ]
+    "box_layout",
+    "box_wrap",
+    "box_reverse",
+    "order_reverse",
+    "spacing",
+    "first_spacing",
+    "fit_first",
+    "xfit",
+    "yfit",
+    "minimum",
+    "xminimum",
+    "yminimum",
+    ] ]
 
 ui_properties = [
     Keyword("at"),
diff --git a/renpy/statements.py b/renpy/statements.py
index 052cbfc..28d7c9c 100644
--- a/renpy/statements.py
+++ b/renpy/statements.py
@@ -29,7 +29,8 @@ registry = { }
 
 parsers = renpy.parser.ParseTrie()
 
-def register(name, parse=None, lint=None, execute=None, predict=None, next=None, scry=None, block=False, init=False, translatable=False): #@ReservedAssignment
+
+def register(name, parse=None, lint=None, execute=None, predict=None, next=None, scry=None, block=False, init=False, translatable=False):  # @ReservedAssignment
     """
     :doc: statement_register
     :name: renpy.register_statement
@@ -143,6 +144,7 @@ def call(method, parsed, *args, **kwargs):
 
     return method(parsed, *args, **kwargs)
 
+
 def get_name(parsed):
     name, _parsed = parsed
     return " ".join(name)
diff --git a/renpy/style.pyx b/renpy/style.pyx
index 779375b..c38db80 100644
--- a/renpy/style.pyx
+++ b/renpy/style.pyx
@@ -751,17 +751,13 @@ def reset():
 
     styles.clear()
 
-#     import gc
-#
-#     for i in gc.get_objects():
-#         if isinstance(i, Style):
-#             unbuild_style(i)
-
 
 def build_styles():
     """
     Builds or rebuilds all styles.
     """
+    for i in renpy.config.build_styles_callbacks:
+        i()
 
     for s in styles.values():
         unbuild_style(s)
@@ -809,11 +805,23 @@ def restore(o):
 
     cdef StyleCore s
 
+    keys = list(styles.keys())
+
+    for i in keys:
+        if i not in o:
+            del styles[i]
+
+
     for k, v in o.iteritems():
-        s = get_full_style(k)
+
+        s = get_or_create_style(k[0])
+
+        for i in k[1:]:
+            s = s[i]
 
         parent, properties = v
 
+        s.clear()
         s.set_parent(parent)
         s.properties = copy_properties(properties)
 
diff --git a/renpy/styledata/__init__.py b/renpy/styledata/__init__.py
index 061922b..7c4626d 100644
--- a/renpy/styledata/__init__.py
+++ b/renpy/styledata/__init__.py
@@ -19,20 +19,21 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+
 def import_style_functions():
-    import renpy.styledata.stylesets # @UnresolvedImport
+    import renpy.styledata.stylesets  # @UnresolvedImport
 
-    import renpy.styledata.style_functions # @UnresolvedImport
-    import renpy.styledata.style_activate_functions # @UnresolvedImport
-    import renpy.styledata.style_hover_functions # @UnresolvedImport
-    import renpy.styledata.style_idle_functions # @UnresolvedImport
-    import renpy.styledata.style_insensitive_functions # @UnresolvedImport
+    import renpy.styledata.style_functions  # @UnresolvedImport
+    import renpy.styledata.style_activate_functions  # @UnresolvedImport
+    import renpy.styledata.style_hover_functions  # @UnresolvedImport
+    import renpy.styledata.style_idle_functions  # @UnresolvedImport
+    import renpy.styledata.style_insensitive_functions  # @UnresolvedImport
 
-    import renpy.styledata.style_selected_functions # @UnresolvedImport
-    import renpy.styledata.style_selected_activate_functions # @UnresolvedImport
-    import renpy.styledata.style_selected_hover_functions # @UnresolvedImport
-    import renpy.styledata.style_selected_idle_functions # @UnresolvedImport
-    import renpy.styledata.style_selected_insensitive_functions # @UnresolvedImport
+    import renpy.styledata.style_selected_functions  # @UnresolvedImport
+    import renpy.styledata.style_selected_activate_functions  # @UnresolvedImport
+    import renpy.styledata.style_selected_hover_functions  # @UnresolvedImport
+    import renpy.styledata.style_selected_idle_functions  # @UnresolvedImport
+    import renpy.styledata.style_selected_insensitive_functions  # @UnresolvedImport
 
-    import renpy.styledata.styleclass # @UnresolvedImport
-    renpy.style.Style = renpy.styledata.styleclass.Style # @UndefinedVariable
+    import renpy.styledata.styleclass  # @UnresolvedImport
+    renpy.style.Style = renpy.styledata.styleclass.Style  # @UndefinedVariable
diff --git a/renpy/styledata/styleutil.py b/renpy/styledata/styleutil.py
index 162e2fd..32cd5d5 100644
--- a/renpy/styledata/styleutil.py
+++ b/renpy/styledata/styleutil.py
@@ -23,12 +23,14 @@
 
 import renpy
 
+
 def none_is_null(o):
     if o is None:
-        return renpy.display.layout.Null() # @UndefinedVariable
+        return renpy.display.layout.Null()  # @UndefinedVariable
     else:
         return renpy.easy.displayable(o)
 
+
 def expand_focus_mask(v):
     if v is None:
         return v
@@ -41,6 +43,7 @@ def expand_focus_mask(v):
     else:
         return renpy.easy.displayable(v)
 
+
 def expand_outlines(l):
     rv = [ ]
 
@@ -61,6 +64,7 @@ ANCHORS = dict(
     bottom=1.0,
     )
 
+
 def expand_anchor(v):
     """
     Turns an anchor into a number.
diff --git a/renpy/substitutions.py b/renpy/substitutions.py
index f6b4ab3..455a254 100644
--- a/renpy/substitutions.py
+++ b/renpy/substitutions.py
@@ -28,6 +28,7 @@ import os
 
 update_translations = "RENPY_UPDATE_TRANSLATIONS" in os.environ
 
+
 class Formatter(string.Formatter):
     """
     A string formatter that uses Ren'Py's formatting rules. Ren'Py uses
@@ -55,7 +56,7 @@ class Formatter(string.Formatter):
         # The parts we've seen.
         literal = ''
         value = ''
-        format = '' #@ReservedAssignment
+        format = ''  # @ReservedAssignment
         conversion = None
 
         state = LITERAL
@@ -101,7 +102,7 @@ class Formatter(string.Formatter):
                         state = LITERAL
                         literal = ''
                         value = ''
-                        format = '' #@ReservedAssignment
+                        format = ''  # @ReservedAssignment
                         conversion = None
                         continue
 
@@ -125,7 +126,7 @@ class Formatter(string.Formatter):
                     state = LITERAL
                     literal = ''
                     value = ''
-                    format = '' #@ReservedAssignment
+                    format = ''  # @ReservedAssignment
                     conversion = None
                     continue
 
@@ -138,14 +139,13 @@ class Formatter(string.Formatter):
                     format += c
                     continue
 
-
             elif state == CONVERSION:
                 if c == ']':
                     yield (literal, value, format, conversion)
                     state = LITERAL
                     literal = ''
                     value = ''
-                    format = '' #@ReservedAssignment
+                    format = ''  # @ReservedAssignment
                     conversion = None
                     continue
 
@@ -180,7 +180,9 @@ class Formatter(string.Formatter):
 # The instance of Formatter we use.
 formatter = Formatter()
 
+
 class MultipleDict(object):
+
     def __init__(self, *dicts):
         self.dicts = dicts
 
@@ -191,6 +193,7 @@ class MultipleDict(object):
 
         raise KeyError(key)
 
+
 def substitute(s, scope=None, force=False, translate=True):
     """
     Performs translation and formatting on `s`, as necessary.
@@ -222,9 +225,9 @@ def substitute(s, scope=None, force=False, translate=True):
     old_s = s
 
     if scope is not None:
-        kwargs = MultipleDict(scope, renpy.store.__dict__) #@UndefinedVariable
+        kwargs = MultipleDict(scope, renpy.store.__dict__)  # @UndefinedVariable
     else:
-        kwargs = renpy.store.__dict__ #@UndefinedVariable
+        kwargs = renpy.store.__dict__  # @UndefinedVariable
 
     s = formatter.vformat(s, (), kwargs)
 
diff --git a/renpy/test/testast.py b/renpy/test/testast.py
index d9a4e0b..aa5ac48 100644
--- a/renpy/test/testast.py
+++ b/renpy/test/testast.py
@@ -35,6 +35,7 @@ _test.timeout = 5.0
 # Should we force the test to proceed despite suppress_underlay?
 _test.force = False
 
+
 class Node(object):
     """
     An AST node for a test script.
@@ -141,12 +142,14 @@ class Click(Pattern):
         click_mouse(self.button, x, y)
         return None
 
+
 class Move(Pattern):
 
     def perform(self, x, y, state, t):
         move_mouse(x, y)
         return None
 
+
 class Drag(Node):
 
     def __init__(self, loc, points):
@@ -214,7 +217,6 @@ class Drag(Node):
             x, y = interpoints.pop(0)
             renpy.test.testmouse.move_mouse(x, y)
 
-
         if not interpoints:
             renpy.test.testmouse.release_mouse(self.button)
             return None
@@ -222,7 +224,6 @@ class Drag(Node):
         else:
             return interpoints
 
-
     def ready(self):
 
         if self.pattern is None:
@@ -236,7 +237,6 @@ class Drag(Node):
             return False
 
 
-
 class Type(Pattern):
 
     interval = .05
@@ -261,6 +261,7 @@ class Type(Pattern):
 
         return state + 1
 
+
 class Action(Node):
 
     def __init__(self, loc, expr):
@@ -306,6 +307,7 @@ class Pause(Node):
         else:
             return None
 
+
 class Label(Node):
 
     def __init__(self, loc, name):
@@ -325,7 +327,6 @@ class Label(Node):
         return self.name in renpy.test.testexecution.labels
 
 
-
 ################################################################################
 # Non-clause statements.
 
@@ -442,7 +443,6 @@ class Call(Node):
         return (node, child_state, start)
 
 
-
 ################################################################################
 # Control structures.
 
@@ -472,4 +472,3 @@ class Block(Node):
             i += 1
 
         return i, start, s
-
diff --git a/renpy/test/testexecution.py b/renpy/test/testexecution.py
index adfde8f..d66ec46 100644
--- a/renpy/test/testexecution.py
+++ b/renpy/test/testexecution.py
@@ -52,6 +52,7 @@ action = None
 # has been called.
 labels = set()
 
+
 def take_name(name):
     """
     Takes the name of a statement that is about to run.
@@ -63,6 +64,7 @@ def take_name(name):
     if isinstance(name, basestring):
         labels.add(name)
 
+
 class TestJump(Exception):
     """
     An exception that is raised in order to jump to `node`.
@@ -71,6 +73,7 @@ class TestJump(Exception):
     def __init__(self, node):
         self.node = node
 
+
 def lookup(name, from_node):
     """
     Tries to look up the name with `target`. If found, returns it, otherwise
@@ -82,6 +85,7 @@ def lookup(name, from_node):
 
     raise Exception("Testcase {} not found at {}:{}.".format(name, from_node.filename, from_node.linenumber))
 
+
 def execute_node(now, node, state, start):
     """
     Performs one execution cycle of a node.
@@ -138,7 +142,7 @@ def execute():
         renpy.exports.maximum_framerate(None)
 
     # Make sure there are no test events in the event queue.
-    for e in pygame_sdl2.event.copy_event_queue(): # @UndefinedVariable
+    for e in pygame_sdl2.event.copy_event_queue():  # @UndefinedVariable
         if getattr(e, "test", False):
             return
 
diff --git a/renpy/test/testfocus.py b/renpy/test/testfocus.py
index 63b6757..36db374 100644
--- a/renpy/test/testfocus.py
+++ b/renpy/test/testfocus.py
@@ -19,14 +19,13 @@
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-
+from __future__ import print_function
 import renpy.test
 import renpy.display
 import random
 
 
 def find_focus(pattern):
-
     """
     Trues to find the focus with the shortest alt text containing `pattern`.
     If found, returns a random coordinate within that displayable.
@@ -46,7 +45,7 @@ def find_focus(pattern):
                 return None
 
         if f.x is None:
-            t = renpy.display.tts.root._tts_all() # @UndefinedVariable
+            t = renpy.display.tts.root._tts_all()  # @UndefinedVariable
         else:
             t = f.widget._tts_all()
 
@@ -55,7 +54,6 @@ def find_focus(pattern):
         else:
             return None
 
-
     # A list of alt_text_length, focus pairs.
     matching = [ ]
 
@@ -141,8 +139,6 @@ def find_position(f, position):
         y = random.randrange(f.y, f.y + f.h)
 
     else:
-        print
+        print()
 
         raise Exception("Could not locate the displayable.")
-
-
diff --git a/renpy/test/testkey.py b/renpy/test/testkey.py
index d7eb718..f51b2f5 100644
--- a/renpy/test/testkey.py
+++ b/renpy/test/testkey.py
@@ -267,6 +267,7 @@ for k, v in sorted(code_to_unicode.items()):
     if v and (v not in unicode_to_code):
         unicode_to_code[v] = k
 
+
 def get_keycode(node, keysym):
 
     c = keysym.split("_")
@@ -349,6 +350,7 @@ def down(node, keysym):
             repeat=False,
             test=True))
 
+
 def up(node, keysym):
     code, _, mods = get_keycode(node, keysym)
 
diff --git a/renpy/test/testmouse.py b/renpy/test/testmouse.py
index e174093..bfb17a1 100644
--- a/renpy/test/testmouse.py
+++ b/renpy/test/testmouse.py
@@ -27,6 +27,7 @@ mouse_pos = None
 # The mouse buttons.
 mouse_buttons = [ 0, 0, 0 ]
 
+
 def get_mouse_pos(x, y):
     """
     Called to get the overridden mouse position.
@@ -37,9 +38,11 @@ def get_mouse_pos(x, y):
 
     return mouse_pos
 
+
 def post(event_type, **kwargs):
     pygame.event.post(pygame.event.Event(event_type, test=True, **kwargs))
 
+
 def move_mouse(x, y):
     """
     Moves the mouse to x, y.
@@ -59,6 +62,7 @@ def move_mouse(x, y):
 
     mouse_pos = pos
 
+
 def press_mouse(button):
     """
     Presses mouse button `button`.
@@ -69,6 +73,7 @@ def press_mouse(button):
     if button < 3:
         mouse_buttons[button - 1] = 1
 
+
 def release_mouse(button):
     """
     Releases mouse button `button`.
@@ -78,6 +83,7 @@ def release_mouse(button):
     if button < 3:
         mouse_buttons[button - 1] = 0
 
+
 def click_mouse(button, x, y):
     """
     Clicks the mouse at x, y
@@ -87,6 +93,7 @@ def click_mouse(button, x, y):
     press_mouse(button)
     release_mouse(button)
 
+
 def reset():
     """
     Resets mouse handling once the test has ended.
diff --git a/renpy/test/testparser.py b/renpy/test/testparser.py
index 4894a83..658f0fd 100644
--- a/renpy/test/testparser.py
+++ b/renpy/test/testparser.py
@@ -76,7 +76,6 @@ def parse_move(l, loc):
     return rv
 
 
-
 def parse_drag(l, loc):
 
     points = l.require(l.simple_expression)
@@ -143,6 +142,7 @@ def parse_clause(l, loc):
     l.error("Expected a test language statement or clause.")
     return testast.Click(loc, target)
 
+
 def parse_statement(l, loc):
 
     if l.keyword('python'):
@@ -187,6 +187,7 @@ def parse_statement(l, loc):
 
     return rv
 
+
 def parse_block(l, loc):
     """
     Parses a named block of testcase statements.
diff --git a/renpy/text/extras.py b/renpy/text/extras.py
index 24cb9fb..50e2145 100644
--- a/renpy/text/extras.py
+++ b/renpy/text/extras.py
@@ -21,6 +21,8 @@
 
 # Other text-related things.
 
+from __future__ import print_function
+
 import renpy.text
 
 from renpy.text.textsupport import TAG
@@ -78,7 +80,7 @@ def check_text_tags(s):
 
     tag_stack = [ ]
 
-    for type, text in tokens: #@ReservedAssignment
+    for type, text in tokens:  # @ReservedAssignment
         if type != TAG:
             continue
 
@@ -149,3 +151,46 @@ class ParameterizedText(object):
         string = renpy.python.py_eval(param)
 
         return renpy.text.text.Text(string, style=self.style, **self.properties)
+
+
+def textwrap(s, width=78, asian=False):
+    """
+    Wraps the unicode string `s`, and returns a list of strings.
+
+    `width`
+        The number of half-width characters that fit on a line.
+    `asian`
+        True if we should make ambiguous width characters full-width, as is
+        done in Asian encodings.
+    """
+
+    import unicodedata
+
+    glyphs = [ ]
+
+    for c in unicode(s):
+
+        eaw = unicodedata.east_asian_width(c)
+
+        if (eaw == "F") or (eaw =="W"):
+            gwidth = 20
+        elif (eaw == "A"):
+            if asian:
+                gwidth = 20
+            else:
+                gwidth = 10
+        else:
+            gwidth = 10
+
+        g = textsupport.Glyph()
+        g.character = ord(c)
+        g.ascent = 10
+        g.line_spacing = 10
+        g.width = gwidth
+        g.advance = gwidth
+
+        glyphs.append(g)
+
+    textsupport.annotate_unicode(glyphs, False, 2)
+    renpy.text.texwrap.linebreak_tex(glyphs, width * 10, width * 10, False)
+    return textsupport.linebreak_list(glyphs)
diff --git a/renpy/text/font.py b/renpy/text/font.py
index 844b02f..f7cf716 100644
--- a/renpy/text/font.py
+++ b/renpy/text/font.py
@@ -30,11 +30,12 @@ import renpy.display
 import renpy.text.ftfont as ftfont
 import renpy.text.textsupport as textsupport
 
-ftfont.init() #@UndefinedVariable
+ftfont.init()  # @UndefinedVariable
 
 WHITE = (255, 255, 255, 255)
 BLACK = (0, 0, 0, 255)
 
+
 class ImageFont(object):
 
     # ImageFonts are expected to have the following fields defined by
@@ -52,7 +53,6 @@ class ImageFont(object):
     # offsets - The x and y offsets of each character.
     # chars - A map from a character to the surface containing that character.
 
-
     def glyphs(self, s):
 
         rv = [ ]
@@ -61,7 +61,7 @@ class ImageFont(object):
             return rv
 
         for c in s:
-            g = textsupport.Glyph() #@UndefinedVariable
+            g = textsupport.Glyph()  # @UndefinedVariable
 
             g.character = ord(c)
             g.ascent = self.height
@@ -129,18 +129,18 @@ class SFont(ImageFont):
 
     def load(self):
 
-        self.chars = { } # W0201
-        self.width = { } # W0201
-        self.advance = { } # W0201
-        self.offsets = { } # W0201
+        self.chars = { }  # W0201
+        self.width = { }  # W0201
+        self.advance = { }  # W0201
+        self.offsets = { }  # W0201
 
         # Load in the image.
         surf = renpy.display.im.Image(self.filename).load(unscaled=True)
 
         sw, sh = surf.get_size()
         height = sh
-        self.height = height # W0201
-        self.baseline = height # W0201
+        self.height = height  # W0201
+        self.baseline = height  # W0201
 
         # Create space characters.
         self.chars[u' '] = renpy.display.pgrender.surface((self.spacewidth, height), True)
@@ -214,10 +214,10 @@ class MudgeFont(ImageFont):
 
     def load(self):
 
-        self.chars = { } # W0201
-        self.width = { } # W0201
-        self.advance = { } # W0201
-        self.offsets = { } # W0201
+        self.chars = { }  # W0201
+        self.width = { }  # W0201
+        self.advance = { }  # W0201
+        self.offsets = { }  # W0201
 
         # Load in the image.
         surf = renpy.display.im.Image(self.filename).load(unscaled=True)
@@ -250,8 +250,8 @@ class MudgeFont(ImageFont):
 
             height = max(height, h)
 
-        self.height = height # W0201
-        self.baseline = height # W0201
+        self.height = height  # W0201
+        self.baseline = height  # W0201
 
         # Create space characters.
         if u' ' not in self.chars:
@@ -272,7 +272,6 @@ class MudgeFont(ImageFont):
         self.offsets[u'\u200b'] = (0, 0)
 
 
-
 def parse_bmfont_line(l):
     w = ""
     line = [ ]
@@ -298,9 +297,10 @@ def parse_bmfont_line(l):
     if w:
         line.append(w)
 
-    map = dict(i.split("=", 1) for i in line[1:]) #@ReservedAssignment
+    map = dict(i.split("=", 1) for i in line[1:])  # @ReservedAssignment
     return line[0], map
 
+
 class BMFont(ImageFont):
 
     def __init__(self, filename):
@@ -310,12 +310,12 @@ class BMFont(ImageFont):
 
     def load(self):
 
-        self.chars = { } # W0201
-        self.width = { } # W0201
-        self.advance = { } # W0201
-        self.offsets = { } # W0201
-        self.kerns = { } # W0201
-        self.default_kern = 0 # W0201
+        self.chars = { }  # W0201
+        self.width = { }  # W0201
+        self.advance = { }  # W0201
+        self.offsets = { }  # W0201
+        self.kerns = { }  # W0201
+        self.default_kern = 0  # W0201
 
         pages = { }
 
@@ -325,8 +325,8 @@ class BMFont(ImageFont):
             kind, args = parse_bmfont_line(l)
 
             if kind == "common":
-                self.height = int(args["lineHeight"]) # W0201
-                self.baseline = int(args["base"]) # W0201
+                self.height = int(args["lineHeight"])  # W0201
+                self.baseline = int(args["base"])  # W0201
             elif kind == "page":
                 pages[int(args["id"])] = renpy.display.im.Image(args["file"]).load(unscaled=True)
             elif kind == "char":
@@ -356,12 +356,12 @@ class BMFont(ImageFont):
             self.advance[u'\u00a0'] = self.advance[u' ']
             self.offsets[u'\u00a0'] = self.offsets[u' ']
 
-
         self.chars[u'\u200b'] = renpy.display.pgrender.surface((0, self.height), True)
         self.width[u'\u200b'] = 0
         self.advance[u'\u200b'] = 0
         self.offsets[u'\u200b'] = (0, 0)
 
+
 class ScaledImageFont(ImageFont):
     """
     Represents an imagefont scaled by a given factor.
@@ -393,7 +393,6 @@ class ScaledImageFont(ImageFont):
 def register_sfont(name=None, size=None, bold=False, italics=False, underline=False,
                    filename=None, spacewidth=10, default_kern=0, kerns={},
                    charset=u"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"):
-
     """
     :doc: image_fonts
 
@@ -446,9 +445,9 @@ def register_sfont(name=None, size=None, bold=False, italics=False, underline=Fa
     sf = SFont(filename, spacewidth, default_kern, kerns, charset)
     image_fonts[(name, size, bold, italics)] = sf
 
-def register_mudgefont(name=None, size=None, bold=False, italics=False, underline=False,
-                   filename=None, xml=None, spacewidth=10, default_kern=0, kerns={}):
 
+def register_mudgefont(name=None, size=None, bold=False, italics=False, underline=False,
+                       filename=None, xml=None, spacewidth=10, default_kern=0, kerns={}):
     """
     :doc: image_fonts
 
@@ -500,9 +499,9 @@ def register_mudgefont(name=None, size=None, bold=False, italics=False, underlin
     mf = MudgeFont(filename, xml, spacewidth, default_kern, kerns)
     image_fonts[(name, size, bold, italics)] = mf
 
+
 def register_bmfont(name=None, size=None, bold=False, italics=False, underline=False,
                     filename=None):
-
     """
     :doc: image_fonts
 
@@ -545,6 +544,7 @@ def register_bmfont(name=None, size=None, bold=False, italics=False, underline=F
 # A map from face name to ftfont.FTFace
 face_cache = { }
 
+
 def load_face(fn):
 
     if fn in face_cache:
@@ -584,11 +584,10 @@ def load_face(fn):
             if font_file:
                 break
 
-
     if font_file is None:
         raise Exception("Could not find font {0!r}.".format(orig_fn))
 
-    rv = ftfont.FTFace(font_file, index) #@UndefinedVariable
+    rv = ftfont.FTFace(font_file, index)  # @UndefinedVariable
 
     face_cache[orig_fn] = rv
 
@@ -606,6 +605,7 @@ font_cache = { }
 # The last_scale we last accessed fonts at. (Used to clear caches.)
 last_scale = 1.0
 
+
 def get_font(fn, size, bold, italics, outline, antialias, vertical, hinting, scale):
 
     # If the scale changed, invalidate caches of scaled fonts.
@@ -644,12 +644,13 @@ def get_font(fn, size, bold, italics, outline, antialias, vertical, hinting, sca
 
     # Load a TTF.
     face = load_face(fn)
-    rv = ftfont.FTFont(face, int(size * scale), bold, italics, outline, antialias, vertical, hinting) #@UndefinedVariable
+    rv = ftfont.FTFont(face, int(size * scale), bold, italics, outline, antialias, vertical, hinting)  # @UndefinedVariable
 
     font_cache[key] = rv
 
     return rv
 
+
 def free_memory():
     """
     Clears the font cache.
@@ -760,4 +761,3 @@ class FontGroup(object):
             pos += 1
 
         yield self.fonts[old_index], s[mark:]
-
diff --git a/renpy/text/text.py b/renpy/text/text.py
index 6aad2e5..ec6594a 100644
--- a/renpy/text/text.py
+++ b/renpy/text/text.py
@@ -30,10 +30,11 @@ import renpy.text.font as font
 import renpy.text.extras as extras
 
 try:
-    from _renpybidi import log2vis, WRTL, RTL, ON # @UnresolvedImport
+    from _renpybidi import log2vis, WRTL, RTL, ON  # @UnresolvedImport
 except:
     pass
 
+
 class Blit(object):
     """
     Represents a blit command, which can be used to render a texture to a
@@ -97,7 +98,6 @@ def outline_blits(blits, outline):
     # The y coordinate of the bottom of the current line.
     bottom_y = 0
 
-
     # The maximum x coordinate of the previous blit on this line.
     max_x = 0
 
@@ -288,7 +288,6 @@ class TextSegment(object):
         on the font group.
         """
 
-
         if not isinstance(self.font, font.FontGroup):
             yield (self, s)
             return
@@ -320,6 +319,7 @@ class TextSegment(object):
         fo = font.get_font(self.font, self.size, self.bold, self.italic, 0, self.antialias, self.vertical, self.hinting, layout.oversample)
         return fo.bounds(glyphs, bounds)
 
+
 class SpaceSegment(object):
     """
     A segment that's used to render horizontal or vertical whitespace.
@@ -423,6 +423,7 @@ class DisplayableSegment(object):
     def bounds(self, glyphs, bounds, layout):
         return bounds
 
+
 class FlagSegment(object):
     """
     A do-nothing segment that just exists so we can flag the start and end
@@ -441,6 +442,7 @@ class FlagSegment(object):
     def bounds(self, glyphs, bounds, layout):
         return bounds
 
+
 class Layout(object):
     """
     Represents the layout of text.
@@ -590,7 +592,7 @@ class Layout(object):
             self.paragraph_glyphs.append(list(par_glyphs))
 
             if splits_from:
-                textsupport.copy_splits(splits_from.paragraph_glyphs[p_num], par_glyphs) # @UndefinedVariable
+                textsupport.copy_splits(splits_from.paragraph_glyphs[p_num], par_glyphs)  # @UndefinedVariable
 
             else:
 
@@ -686,7 +688,7 @@ class Layout(object):
             target_x = self.scale_int(splits_from.size[0] - splits_from.xborder)
             target_y = self.scale_int(splits_from.size[1] - splits_from.yborder)
 
-            textsupport.tweak_glyph_spacing(all_glyphs, lines, target_x - maxx, target_y - y, maxx, y) # @UndefinedVariable
+            textsupport.tweak_glyph_spacing(all_glyphs, lines, target_x - maxx, target_y - y, maxx, y)  # @UndefinedVariable
 
             maxx = target_x
             y = target_y
@@ -751,7 +753,6 @@ class Layout(object):
 
                 ts.draw(glyphs, di, self.add_left, self.add_top, self)
 
-
             renpy.display.draw.mutated_surface(surf)
             tex = renpy.display.draw.load_texture(surf)
 
@@ -782,7 +783,6 @@ class Layout(object):
                 renpy.display.to_log.write("     Available: (%d, %d) Laid-out: (%d, %d)", width, height, sw, sh)
                 renpy.display.to_log.write("     Text: %r", text.text)
 
-
     def scale(self, n):
         if n is None:
             return n
@@ -807,7 +807,6 @@ class Layout(object):
 
         return n * int(self.oversample)
 
-
     def unscale_pair(self, x, y):
         return x / self.oversample, y / self.oversample
 
@@ -854,7 +853,7 @@ class Layout(object):
 
             line.extend(tss[-1].subsegment(u" "))
 
-        for type, text in tokens: #@ReservedAssignment
+        for type, text in tokens:  # @ReservedAssignment
 
             if type == PARAGRAPH:
 
@@ -1070,7 +1069,6 @@ class Layout(object):
 
         return l, rtl
 
-
     def figure_outlines(self, style):
         """
         Return a list containing the outlines, including an outline
@@ -1095,7 +1093,6 @@ class Layout(object):
             for dsx, dsy in dslist:
                 outlines.append((0, style.drop_shadow_color, self.scale_outline(dsx), self.scale_outline(dsy)))
 
-
         for size, color, xo, yo in style_outlines:
             outlines.append((self.scale_outline(size), color, self.scale_outline(xo), self.scale_outline(yo)))
 
@@ -1128,7 +1125,6 @@ class Layout(object):
 
         return outlines, right - left, bottom - top, -left, -top
 
-
     def blits_typewriter(self, st):
         """
         Given a st and an outline, returns a list of blit objects that
@@ -1171,7 +1167,6 @@ class Layout(object):
         min_x = width
         max_x = 0
 
-
         left = False
         right = False
 
@@ -1227,7 +1222,6 @@ virtual_layout_cache_old = { }
 virtual_layout_cache_new = { }
 
 
-
 def layout_cache_clear():
     """
     Clears the old and new layout caches.
@@ -1258,6 +1252,7 @@ def layout_cache_tick():
 VERT_REVERSE = renpy.display.render.Matrix2D(0, -1, 1, 0)
 VERT_FORWARD = renpy.display.render.Matrix2D(0, 1, -1, 0)
 
+
 class Text(renpy.display.core.Displayable):
 
     """
@@ -1288,6 +1283,7 @@ class Text(renpy.display.core.Displayable):
 
     _uses_scope = True
     _duplicatable = False
+    locked = False
 
     def after_upgrade(self, version):
 
@@ -1369,6 +1365,20 @@ class Text(renpy.display.core.Displayable):
 
         return self
 
+    def _in_current_store(self):
+        if not self._uses_scope:
+            return self
+
+        rv = self._copy()
+
+        if rv.displayables is not None:
+            rv.displayables = [ i._in_current_store() for i in rv.displayables ]
+
+        rv.slow_done = None
+        rv.locked = True
+
+        return rv
+
     def __unicode__(self):
         s = ""
 
@@ -1388,10 +1398,16 @@ class Text(renpy.display.core.Displayable):
         Called to update the scope, when necessary.
         """
 
+        if self.locked:
+            return False
+
         return self.set_text(self.text_parameter, scope, self.substitute, update)
 
     def set_text(self, text, scope=None, substitute=False, update=True):
 
+        if self.locked:
+            return
+
         old_text = self.text
 
         if not isinstance(text, list):
@@ -1499,7 +1515,6 @@ class Text(renpy.display.core.Displayable):
         # Text.
         self.tokens, self.displayables = self.get_displayables(tokens)
 
-
     def visit(self):
 
         if self.dirty or self.displayables is None:
@@ -1546,7 +1561,6 @@ class Text(renpy.display.core.Displayable):
         virtual_layout_cache_old.pop(key, None)
         virtual_layout_cache_new.pop(key, None)
 
-
     def get_layout(self):
         """
         Gets the layout of this text, if one exists.
@@ -1594,7 +1608,6 @@ class Text(renpy.display.core.Displayable):
         if hyperlink_focus:
             return hyperlink_focus(target)
 
-
     def set_style_prefix(self, prefix, root):
         if prefix != self.style.prefix:
             self.kill_layout()
@@ -1645,7 +1658,7 @@ class Text(renpy.display.core.Displayable):
                 return rv
 
         if (self.is_focused() and
-            renpy.display.behavior.map_event(ev, "button_select")):
+                renpy.display.behavior.map_event(ev, "button_select")):
 
             clicked = self.style.hyperlink_functions[1]
 
@@ -1811,13 +1824,12 @@ class Text(renpy.display.core.Displayable):
                 else:
                     b_y += layout.add_top
 
-
                 # Blit.
                 rv.absolute_blit(
                     tex.subsurface((b_x, b_y, b_w, b_h)),
                     layout.unscale_pair(b_x + xo + layout.xoffset - o - layout.add_left,
-                     b_y + yo + layout.yoffset - o - layout.add_top)
-                     )
+                                        b_y + yo + layout.yoffset - o - layout.add_top)
+                    )
 
         # Blit displayables.
         if layout.displayable_blits:
@@ -1862,7 +1874,6 @@ class Text(renpy.display.core.Displayable):
 
         return rv
 
-
     def tokenize(self, text):
         """
         Convert the text into a list of tokens.
@@ -1886,7 +1897,6 @@ class Text(renpy.display.core.Displayable):
 
         return tokens
 
-
     def apply_custom_tags(self, tokens):
         """
         Apply new-style custom text tags.
@@ -1999,4 +2009,3 @@ language_tailor = textsupport.language_tailor
 
 # Compatibility, in case one of these was pickled.
 ParameterizedText = extras.ParameterizedText
-
diff --git a/renpy/text/textsupport.pyx b/renpy/text/textsupport.pyx
index ff9d788..3d53f3b 100644
--- a/renpy/text/textsupport.pyx
+++ b/renpy/text/textsupport.pyx
@@ -399,6 +399,33 @@ def linebreak_debug(list glyphs):
     return rv
 
 
+def linebreak_list(list glyphs):
+    """
+    Returns a list of unicode strings, one per broken line.
+    """
+
+    cdef Glyph g
+
+    rv = [ ]
+    line = u""
+
+    for g in glyphs:
+
+        if g.split == SPLIT_INSTEAD:
+            rv.append(line)
+            line = u""
+        elif g.split == SPLIT_BEFORE:
+            rv.append(line)
+            line = unichr(g.character)
+        else:
+            line += unichr(g.character)
+
+    if line:
+        rv.append(line)
+
+    return rv
+
+
 def place_horizontal(list glyphs, float start_x, float first_indent, float rest_indent):
     """
     Place the glyphs horizontally, without taking into account the indentation
diff --git a/renpy/translation/__init__.py b/renpy/translation/__init__.py
index 967f7f4..60f3b1b 100644
--- a/renpy/translation/__init__.py
+++ b/renpy/translation/__init__.py
@@ -35,6 +35,7 @@ import codecs
 # Script
 ################################################################################
 
+
 class ScriptTranslator(object):
 
     def __init__(self):
@@ -64,6 +65,10 @@ class ScriptTranslator(object):
         # that language.
         self.block = collections.defaultdict(list)
 
+        # A map from language to a list of TranslateEarlyBlock objects for
+        # that language.
+        self.early_block = collections.defaultdict(list)
+
         # A map from language to a list of TranslatePython objects for
         # that language.
         self.python = collections.defaultdict(list)
@@ -92,6 +97,7 @@ class ScriptTranslator(object):
 
         TranslatePython = renpy.ast.TranslatePython
         TranslateBlock = renpy.ast.TranslateBlock
+        TranslateEarlyBlock = renpy.ast.TranslateEarlyBlock
         Menu = renpy.ast.Menu
         Translate = renpy.ast.Translate
 
@@ -114,6 +120,11 @@ class ScriptTranslator(object):
                     self.languages.add(n.language)
                 self.python[n.language].append(n)
 
+            elif type_n is TranslateEarlyBlock:
+                if n.language is not None:
+                    self.languages.add(n.language)
+                self.early_block[n.language].append(n)
+
             elif type_n is TranslateBlock:
                 if n.language is not None:
                     self.languages.add(n.language)
@@ -174,6 +185,7 @@ class ScriptTranslator(object):
 
         return tl.block[0]
 
+
 def encode_say_string(s):
     """
     Encodes a string in the format used by Ren'Py say statements.
@@ -186,6 +198,7 @@ def encode_say_string(s):
 
     return "\"" + s + "\""
 
+
 class Restructurer(object):
 
     def __init__(self, children):
@@ -197,7 +210,7 @@ class Restructurer(object):
         if identifier in self.identifiers:
             return True
 
-        if identifier in renpy.game.script.translator.default_translates: # @UndefinedVariable
+        if identifier in renpy.game.script.translator.default_translates:  # @UndefinedVariable
             return True
 
         return False
@@ -285,6 +298,7 @@ class Restructurer(object):
 
         children[:] = new_children
 
+
 def restructure(children):
     Restructurer(children)
 
@@ -381,7 +395,9 @@ class StringTranslator(object):
 
         f.close()
 
+
 def add_string_translation(language, old, new, newloc):
+
     tl = renpy.game.script.translator
     stl = tl.strings[language]
     tl.languages.add(language)
@@ -389,6 +405,7 @@ def add_string_translation(language, old, new, newloc):
 
 Default = renpy.object.Sentinel("default")
 
+
 def translate_string(s, language=Default):
     """
     Translates interface string `s` to `language`. If `languages` is Default,
@@ -398,11 +415,12 @@ def translate_string(s, language=Default):
     if language is Default:
         language = renpy.game.preferences.language
 
-    stl = renpy.game.script.translator.strings[language] # @UndefinedVariable
+    stl = renpy.game.script.translator.strings[language]  # @UndefinedVariable
     return stl.translate(s)
 
+
 def write_updated_strings():
-    stl = renpy.game.script.translator.strings[renpy.game.preferences.language] # @UndefinedVariable
+    stl = renpy.game.script.translator.strings[renpy.game.preferences.language]  # @UndefinedVariable
     stl.write_updated_strings(renpy.game.preferences.language)
 
 
@@ -458,6 +476,7 @@ def load_rpt(fn):
     if old is not None:
         raise Exception("{0} string {1!r} does not have a translation.".format(language, old))
 
+
 def load_all_rpts():
     """
     Loads all .rpt files.
@@ -473,17 +492,18 @@ def load_all_rpts():
 
 style_backup = None
 
+
 def init_translation():
     """
     Called before the game starts.
     """
 
     global style_backup
-    style_backup = renpy.style.backup() # @UndefinedVariable
+    style_backup = renpy.style.backup()  # @UndefinedVariable
 
     load_all_rpts()
 
-    renpy.store._init_language() # @UndefinedVariable
+    renpy.store._init_language()  # @UndefinedVariable
 
 old_language = "language never set"
 
@@ -491,12 +511,16 @@ old_language = "language never set"
 # styles are run.
 deferred_styles = [ ]
 
+
 def old_change_language(tl, language):
 
     for i in deferred_styles:
         i.apply()
 
     def run_blocks():
+        for i in tl.early_block[language]:
+            renpy.game.context().run(i.block[0])
+
         for i in tl.block[language]:
             renpy.game.context().run(i.block[0])
 
@@ -505,12 +529,26 @@ def old_change_language(tl, language):
     for i in tl.python[language]:
         renpy.python.py_exec_bytecode(i.code.bytecode)
 
+    for i in renpy.config.language_callbacks[language]:
+        i()
+
 
 def new_change_language(tl, language):
 
+    renpy.config.init_system_styles()
+
     for i in tl.python[language]:
         renpy.python.py_exec_bytecode(i.code.bytecode)
 
+    def run_blocks():
+        for i in tl.early_block[language]:
+            renpy.game.context().run(i.block[0])
+
+    renpy.game.invoke_in_new_context(run_blocks)
+
+    for i in renpy.config.language_callbacks[language]:
+        i()
+
     for i in deferred_styles:
         i.apply()
 
@@ -520,6 +558,7 @@ def new_change_language(tl, language):
 
     renpy.game.invoke_in_new_context(run_blocks)
 
+
 def change_language(language):
     """
     :doc: translation_functions
@@ -534,8 +573,8 @@ def change_language(language):
 
     tl = renpy.game.script.translator
 
-    renpy.style.restore(style_backup) # @UndefinedVariable
-    renpy.style.rebuild() # @UndefinedVariable
+    renpy.style.restore(style_backup)  # @UndefinedVariable
+    renpy.style.rebuild()  # @UndefinedVariable
 
     for i in renpy.config.translate_clean_stores:
         renpy.python.clean_store(i)
@@ -555,7 +594,7 @@ def change_language(language):
         renpy.exports.free_memory()
 
         # Rebuild the styles.
-        renpy.style.rebuild() # @UndefinedVariable
+        renpy.style.rebuild()  # @UndefinedVariable
 
         old_language = language
 
@@ -568,6 +607,7 @@ def change_language(language):
     if language != old_language:
         renpy.exports.block_rollback()
 
+
 def check_language():
     """
     Checks to see if the language has changed. If it has, jump to the start
@@ -584,11 +624,12 @@ def check_language():
         tid = ctx.translate_identifier
 
         if tid is not None:
-            node = renpy.game.script.translator.lookup_translate(tid) # @UndefinedVariable
+            node = renpy.game.script.translator.lookup_translate(tid)  # @UndefinedVariable
 
             if node is not None:
                 raise renpy.game.JumpException(node.name)
 
+
 def known_languages():
     """
     :doc: translation_functions
@@ -597,4 +638,4 @@ def known_languages():
     language, None.
     """
 
-    return renpy.game.script.translator.languages # @UndefinedVariable
+    return { i for i in renpy.game.script.translator.languages if i is not None }  # @UndefinedVariable
diff --git a/renpy/translation/dialogue.py b/renpy/translation/dialogue.py
index c4df6d4..9427a8b 100644
--- a/renpy/translation/dialogue.py
+++ b/renpy/translation/dialogue.py
@@ -28,6 +28,7 @@ import os
 from renpy.translation import quote_unicode
 from renpy.translation.generation import scan_strings
 
+
 def notags_filter(s):
 
     def tag_pass(s):
@@ -106,12 +107,12 @@ def notags_filter(s):
 
         return rv
 
-
     return square_pass(s)
 
+
 class DialogueFile(object):
 
-    def __init__(self, filename, output, tdf=True, strings=False, notags=True, escape=True): # @ReservedAssignment
+    def __init__(self, filename, output, tdf=True, strings=False, notags=True, escape=True):  # @ReservedAssignment
         """
         `filename`
             The file we're extracting dialogue from.
@@ -198,7 +199,7 @@ class DialogueFile(object):
             # If we're tab-delimited, we have line number info, which means we
             # can sort the list so everything's in order, for menus and stuff.
             if self.tdf:
-                lines.sort(key = lambda x: int(x[4]))
+                lines.sort(key=lambda x: int(x[4]))
 
         for line in lines:
             self.f.write("\t".join(line).encode("utf-8") + "\n")
@@ -214,7 +215,7 @@ class DialogueFile(object):
 
         for line, s in scan_strings(self.filename):
 
-            stl = renpy.game.script.translator.strings[None] # @UndefinedVariable
+            stl = renpy.game.script.translator.strings[None]  # @UndefinedVariable
 
             if s in stl.translations:
                 continue
@@ -235,6 +236,7 @@ class DialogueFile(object):
 
         return lines
 
+
 def dialogue_command():
     """
     The dialogue command. This updates dialogue.txt, a file giving all the dialogue
diff --git a/renpy/translation/extract.py b/renpy/translation/extract.py
index bb15845..0cfd564 100644
--- a/renpy/translation/extract.py
+++ b/renpy/translation/extract.py
@@ -23,7 +23,28 @@ from __future__ import absolute_import, division, print_function
 
 import renpy
 import json
-import io
+
+
+def extract_strings_core(language, destination, merge=False, force=False):
+
+    if (not force) and (language not in renpy.game.script.translator.strings):  # @UndefinedVariable
+        raise Exception("Language %r does not have any translations." % language)
+
+    st = renpy.game.script.translator.strings[language]  # @UndefinedVariable
+
+    result = { }
+
+    if merge:
+        with open(destination, "r") as f:
+            result.update(json.load(f, "utf-8"))
+
+    for k, v in st.translations.iteritems():
+        if v and v != k:
+            result[k] = v
+
+    with open(destination, "wb") as f:
+        json.dump(result, f, ensure_ascii=True)
+
 
 def extract_strings():
     """
@@ -33,27 +54,18 @@ def extract_strings():
     ap = renpy.arguments.ArgumentParser(description="Extracts translated strings.")
     ap.add_argument("language", help="The language to extract translated strings from.")
     ap.add_argument("destination", help="The json file to store the translated strings into.")
+    ap.add_argument("--merge", help="If given, the current contents of the file are preserved, and new contents are merged into the file.", action="store_true")
+    ap.add_argument("--force", help="If given, noting happens if the language does not exist.", action="store_true")
 
     args = ap.parse_args()
 
     language = args.language
 
-    if language not in renpy.game.script.translator.strings: # @UndefinedVariable
-        raise Exception("Language %r does not have any translations." % language)
-
-    st = renpy.game.script.translator.strings[language] # @UndefinedVariable
-
-    result = { }
-
-    for k, v in st.translations.iteritems():
-        result[k] = v
+    if language == 'None':
+        language = None
 
-    data = json.dumps(result, ensure_ascii=False)
-
-    with io.open(args.destination, "w", encoding="utf-8") as f:
-        f.write(data)
+    extract_strings_core(language, args.destination, args.merge, args.force)
 
     return False
 
 renpy.arguments.register_command("extract_strings", extract_strings)
-
diff --git a/renpy/translation/generation.py b/renpy/translation/generation.py
index 90fb3db..13b92ef 100644
--- a/renpy/translation/generation.py
+++ b/renpy/translation/generation.py
@@ -21,13 +21,15 @@
 
 from __future__ import print_function
 
-import renpy
+import renpy.translation
 
 import re
 import os
 import time
 import io
 import codecs
+import collections
+import shutil
 
 from renpy.translation import quote_unicode
 
@@ -44,6 +46,7 @@ STRING_RE = r"""(?x)
 )\s*\)
 """
 
+
 def scan_strings(filename):
     """
     Scans `filename`, a file containing Ren'Py script, for translatable
@@ -52,10 +55,9 @@ def scan_strings(filename):
     Generates a list of (line, string) tuples.
     """
 
-
     rv = [ ]
 
-    for line, s in renpy.game.script.translator.additional_strings[filename]: # @UndefinedVariable
+    for line, s in renpy.game.script.translator.additional_strings[filename]:  # @UndefinedVariable
         rv.append((line, s))
 
     line = 1
@@ -73,6 +75,7 @@ def scan_strings(filename):
 
     return rv
 
+
 def scan_comments(filename):
 
     rv = [ ]
@@ -114,8 +117,17 @@ def scan_comments(filename):
     return rv
 
 
+tl_file_cache = { }
+
+# Should we write the TODO marker?
+todo = True
+
+
 def open_tl_file(fn):
 
+    if fn in tl_file_cache:
+        return tl_file_cache[fn]
+
     if not os.path.exists(fn):
         dn = os.path.dirname(fn)
 
@@ -130,197 +142,165 @@ def open_tl_file(fn):
     else:
         f = io.open(fn, "a", encoding="utf-8")
 
-    f.write(u"# TO" + "DO: Translation updated at {}\n".format(time.strftime("%Y-%m-%d %H:%M")))
-    f.write(u"\n")
-
-    return f
-
-
-class TranslateFile(object):
-
-    def __init__(self, filename, language, filter, count=False): # @ReservedAssignment
-        self.filename = filename
-        self.filter = filter
+    if todo:
+        f.write(u"# TO" + "DO: Translation updated at {}\n".format(time.strftime("%Y-%m-%d %H:%M")))
 
-        commondir = os.path.normpath(renpy.config.commondir)
-        gamedir = os.path.normpath(renpy.config.gamedir)
-
-        if filename.startswith(commondir):
-            relfn = os.path.relpath(filename, commondir)
-
-            if relfn == "_developer.rpym":
-                return
-
-            if relfn.startswith("compat"):
-                return
-
-            self.tl_filename = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, "common.rpy")
-
-        elif filename.startswith(gamedir):
-            fn = os.path.relpath(filename, gamedir)
-            self.tl_filename = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, fn)
-
-        else:
+    f.write(u"\n")
 
-            fn = os.path.basename(filename)
-            self.tl_filename = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, fn)
+    tl_file_cache[fn] = f
 
-        if self.tl_filename.endswith(".rpym"):
-            self.tl_filename = self.tl_filename[:-1]
+    return f
 
-        if language == "None":
-            language = None
 
-        self.language = language
-        self.f = None
+def close_tl_files():
 
-        if count:
+    for i in tl_file_cache.values():
+        i.close()
 
-            self.count_missing()
+    tl_file_cache.clear()
 
-        else:
 
-            if language is not None:
-                self.write_translates()
+def shorten_filename(filename):
+    """
+    Shortens a file name. Returns the shortened filename, and a flag that says
+    if the filename is in the common directory.
+    """
 
-            self.write_strings()
+    commondir = os.path.normpath(renpy.config.commondir)
+    gamedir = os.path.normpath(renpy.config.gamedir)
 
-        self.close()
+    if filename.startswith(commondir):
+        fn = os.path.relpath(filename, commondir)
+        common = True
 
-    def open(self):
-        """
-        Opens a translation file.
-        """
+    elif filename.startswith(gamedir):
+        fn = os.path.relpath(filename, gamedir)
+        common = False
 
-        if self.f is not None:
-            return
+    else:
+        fn = os.path.basename(filename)
+        common = False
 
-        self.f = open_tl_file(self.tl_filename)
+    return fn, common
 
-    def close(self):
-        """
-        Closes the translation file, if it's open.
-        """
 
-        if self.f is not None:
-            self.f.close()
+def write_translates(filename, language, filter):  # @ReservedAssignment
 
-    def write_translates(self):
-        """
-        Writes the translates to the file.
-        """
+    fn, common = shorten_filename(filename)
 
-        translator = renpy.game.script.translator
+    # The common directory should not have dialogue in it.
+    if common:
+        return
 
-        for label, t in translator.file_translates[self.filename]:
+    tl_filename = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, fn)
 
-            if (t.identifier, self.language) in translator.language_translates:
-                continue
+    if tl_filename[-1] == "m":
+        tl_filename = tl_filename[:-1]
 
-            self.open()
+    if language == "None":
+        language = None
 
-            if label is None:
-                label = ""
+    translator = renpy.game.script.translator
 
-            self.f.write(u"# {}:{}\n".format(t.filename, t.linenumber))
-            self.f.write(u"translate {} {}:\n".format(self.language, t.identifier.replace('.', '_')))
-            self.f.write(u"\n")
+    for label, t in translator.file_translates[filename]:
 
-            for n in t.block:
-                self.f.write(u"    # " + n.get_code() + "\n")
+        if (t.identifier, language) in translator.language_translates:
+            continue
 
-            for n in t.block:
-                self.f.write(u"    " + n.get_code(self.filter) + "\n")
+        f = open_tl_file(tl_filename)
 
-            self.f.write(u"\n")
+        if label is None:
+            label = ""
 
-    def write_strings(self):
-        """
-        Writes strings to the file.
-        """
+        f.write(u"# {}:{}\n".format(t.filename, t.linenumber))
+        f.write(u"translate {} {}:\n".format(language, t.identifier.replace('.', '_')))
+        f.write(u"\n")
 
-        # If this function changes, count_missing may also need to
-        # change.
+        for n in t.block:
+            f.write(u"    # " + n.get_code() + "\n")
 
-        started = False
-        filename = renpy.parser.elide_filename(self.filename)
+        for n in t.block:
+            f.write(u"    " + n.get_code(filter) + "\n")
 
-        strings = scan_strings(self.filename)
+        f.write(u"\n")
 
-        if renpy.config.translate_comments:
-            strings.extend(scan_comments(self.filename))
 
-        # Sort by line number.
-        strings.sort(key=lambda a : a[0])
+def translation_filename(s):
 
-        for line, s in strings:
+    if renpy.config.translate_launcher:
+        return s.launcher_file
 
-            stl = renpy.game.script.translator.strings[self.language] # @UndefinedVariable
+    if s.common:
+        return "common.rpy"
 
-            if s in stl.translations:
-                continue
+    filename = s.elided
 
-            stl.translations[s] = s
+    if filename[-1] == "m":
+        filename = filename[:-1]
 
-            if not started:
-                started = True
+    return filename
 
-                self.open()
-                self.f.write(u"translate {} strings:\n".format(self.language))
-                self.f.write(u"\n")
 
-            fs = self.filter(s)
+def write_strings(language, filter, min_priority, max_priority, common_only):  # @ReservedAssignment
+    """
+    Writes strings to the file.
+    """
 
-            self.f.write(u"    # {}:{}\n".format(filename, line))
-            self.f.write(u"    old \"{}\"\n".format(quote_unicode(s)))
-            self.f.write(u"    new \"{}\"\n".format(quote_unicode(fs)))
-            self.f.write(u"\n")
+    if language == "None":
+        stl = renpy.game.script.translator.strings[None]  # @UndefinedVariable
+    else:
+        stl = renpy.game.script.translator.strings[language]  # @UndefinedVariable
 
-    def count_missing(self):
-        """
-        Counts the number of missing translations.
-        """
+    # If this function changes, count_missing may also need to
+    # change.
 
-        # Translates.
+    strings = renpy.translation.scanstrings.scan(min_priority, max_priority, common_only)
 
-        missing_translates = 0
+    stringfiles = collections.defaultdict(list)
 
-        translator = renpy.game.script.translator
+    for s in strings:
 
-        for _, t in translator.file_translates[self.filename]:
+        tlfn = translation_filename(s)
 
-            if (t.identifier, self.language) in translator.language_translates:
-                continue
+        if tlfn is None:
+            continue
 
-            missing_translates += 1
+        # Already seen.
+        if s.text in stl.translations:
+            continue
 
-        # Strings.
+        if language == "None" and tlfn == "common.rpy":
+            tlfn = "common.rpym"
 
-        missing_strings = 0
+        stringfiles[tlfn].append(s)
 
-        strings = scan_strings(self.filename)
+    for tlfn, sl in stringfiles.items():
 
-        if renpy.config.translate_comments:
-            strings.extend(scan_comments(self.filename))
+        # sl.sort(key=lambda s : (s.filename, s.line))
 
-        for _, s in strings:
+        tlfn = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, tlfn)
+        f = open_tl_file(tlfn)
 
-            stl = renpy.game.script.translator.strings[self.language] # @UndefinedVariable
+        f.write(u"translate {} strings:\n".format(language))
+        f.write(u"\n")
 
-            if s in stl.translations:
-                continue
+        for s in sl:
+            text = filter(s.text)
 
-            missing_strings += 1
+            f.write(u"    # {}:{}\n".format(s.elided, s.line))
+            f.write(u"    old \"{}\"\n".format(quote_unicode(s.text)))
+            f.write(u"    new \"{}\"\n".format(quote_unicode(text)))
+            f.write(u"\n")
 
-        self.missing_translates = missing_translates
-        self.missing_strings = missing_strings
 
 def null_filter(s):
     return s
 
+
 def empty_filter(s):
     return ""
 
+
 def generic_filter(s, transform):
 
     def remove_special(s, start, end, process):
@@ -372,6 +352,7 @@ def generic_filter(s, transform):
 
     return remove_special(s, "[", "]", remove_braces)
 
+
 def rot13_transform(s):
 
     ROT13 = { }
@@ -388,9 +369,11 @@ def rot13_transform(s):
 
     return "".join(ROT13.get(i, i) for i in s)
 
+
 def rot13_filter(s):
     return generic_filter(s, rot13_transform)
 
+
 def piglatin_transform(s):
     # Based on http://stackoverflow.com/a/23177629/3549890
 
@@ -413,33 +396,16 @@ def piglatin_transform(s):
 
     return re.sub(r'\w+', replace, s)
 
+
 def piglatin_filter(s):
     return generic_filter(s, piglatin_transform)
 
-def translate_command():
+
+def translate_list_files():
     """
-    The translate command. When called from the command line, this generates
-    the translations.
+    Returns a list of files that exist and should be scanned for translations.
     """
 
-    ap = renpy.arguments.ArgumentParser(description="Generates or updates translations.")
-    ap.add_argument("language", help="The language to generate translations for.")
-    ap.add_argument("--rot13", help="Apply rot13 while generating translations.", dest="rot13", action="store_true")
-    ap.add_argument("--piglatin", help="Apply pig latin while generating translations.", dest="piglatin", action="store_true")
-    ap.add_argument("--empty", help="Produce empty strings while generating translations.", dest="empty", action="store_true")
-    ap.add_argument("--count", help="Instead of generating files, print a count of missing translations.", dest="count", action="store_true")
-
-    args = ap.parse_args()
-
-    if args.rot13:
-        filter = rot13_filter #@ReservedAssignment
-    elif args.piglatin:
-        filter = piglatin_filter #@ReservedAssignment
-    elif args.empty:
-        filter = empty_filter # @ReservedAssignment
-    else:
-        filter = null_filter #@ReservedAssignment
-
     filenames = list(renpy.config.translate_files)
 
     for dirname, filename in renpy.loader.listdirfiles():
@@ -451,36 +417,111 @@ def translate_command():
         if not (filename.endswith(".rpy") or filename.endswith(".rpym")):
             continue
 
+        filename = os.path.normpath(filename)
+
+        if not os.path.exists(filename):
+            continue
+
         filenames.append(filename)
 
+    return filenames
+
+
+def count_missing(language, min_priority, max_priority, common_only):
+    """
+    Prints a count of missing translations for `language`.
+    """
+
+    translator = renpy.game.script.translator
 
     missing_translates = 0
+
+    for filename in translate_list_files():
+        for _, t in translator.file_translates[filename]:
+            if (t.identifier, language) not in translator.language_translates:
+                missing_translates += 1
+
     missing_strings = 0
 
+    stl = renpy.game.script.translator.strings[language]  # @UndefinedVariable
 
-    for filename in filenames:
-        filename = os.path.normpath(filename)
+    strings = renpy.translation.scanstrings.scan(min_priority, max_priority, common_only)
 
-        if not os.path.exists(filename):
+    for s in strings:
+
+        tlfn = translation_filename(s)
+
+        if tlfn is None:
             continue
 
-        tf = TranslateFile(filename, args.language, filter, args.count)
+        if s.text in stl.translations:
+            continue
+
+        missing_strings += 1
+
+    print("{}: {} missing dialogue translations, {} missing string translations.".format(
+        language,
+        missing_translates,
+        missing_strings
+        ))
 
-        if args.count:
-            missing_translates += tf.missing_translates
-            missing_strings += tf.missing_strings
+
+def translate_command():
+    """
+    The translate command. When called from the command line, this generates
+    the translations.
+    """
+
+    ap = renpy.arguments.ArgumentParser(description="Generates or updates translations.")
+    ap.add_argument("language", help="The language to generate translations for.")
+    ap.add_argument("--rot13", help="Apply rot13 while generating translations.", dest="rot13", action="store_true")
+    ap.add_argument("--piglatin", help="Apply pig latin while generating translations.", dest="piglatin", action="store_true")
+    ap.add_argument("--empty", help="Produce empty strings while generating translations.", dest="empty", action="store_true")
+    ap.add_argument("--count", help="Instead of generating files, print a count of missing translations.", dest="count", action="store_true")
+    ap.add_argument("--min-priority", help="Translate strings with more than this priority.", dest="min_priority", default=0, type=int)
+    ap.add_argument("--max-priority", help="Translate strings with more than this priority.", dest="max_priority", default=0, type=int)
+    ap.add_argument("--strings-only", help="Only translate strings (not dialogue).", dest="strings_only", default=False, action="store_true")
+    ap.add_argument("--common-only", help="Only translate string from the common code.", dest="common_only", default=False, action="store_true")
+    ap.add_argument("--no-todo", help="Do not include the TODO flag.", dest="todo", default=True, action="store_false")
+
+    args = ap.parse_args()
+
+    global todo
+    todo = args.todo
+
+    if renpy.config.translate_launcher:
+        max_priority = args.max_priority or 499
+    else:
+        max_priority = args.max_priority or 299
 
     if args.count:
+        count_missing(args.language, args.min_priority, max_priority, args.common_only)
+        return False
+
+    if args.rot13:
+        filter = rot13_filter  # @ReservedAssignment
+    elif args.piglatin:
+        filter = piglatin_filter  # @ReservedAssignment
+    elif args.empty:
+        filter = empty_filter  # @ReservedAssignment
+    else:
+        filter = null_filter  # @ReservedAssignment
 
-        print("{}: {} missing dialogue translations, {} missing string translations.".format(
-            args.language,
-            missing_translates,
-            missing_strings
-            ))
+    if not args.strings_only:
+        for filename in translate_list_files():
+            write_translates(filename, args.language, filter)
 
-    return False
+    write_strings(args.language, filter, args.min_priority, max_priority, args.common_only)
 
-renpy.arguments.register_command("translate", translate_command)
+    close_tl_files()
 
+    if renpy.config.translate_launcher and (not args.strings_only):
+        src = os.path.join(renpy.config.renpy_base, "gui", "game", "script.rpy")
+        dst = os.path.join(renpy.config.gamedir, "tl", args.language, "script.rpym")
 
+        if os.path.exists(src) and not os.path.exists(dst):
+            shutil.copy(src, dst)
 
+    return False
+
+renpy.arguments.register_command("translate", translate_command)
diff --git a/renpy/translation/merge.py b/renpy/translation/merge.py
index 99b1401..6a4be9a 100644
--- a/renpy/translation/merge.py
+++ b/renpy/translation/merge.py
@@ -25,13 +25,14 @@ import renpy
 import json
 import io
 
+
 def merge_strings():
     """
     The merge strings command.
     """
 
     ap = renpy.arguments.ArgumentParser(description="Merges translated strings with the game script.")
-    ap.add_argument("language", help="The language to merge translated strings from.")
+    ap.add_argument("language", help="The language to merge translated strings to.")
     ap.add_argument("source", help="The json file to take translated strings from.")
     ap.add_argument("--reverse", action="store_true", help="Reverses the languages in the json file.")
     ap.add_argument("--replace", action="store_true", help="Replaces non-trivial translations.")
@@ -40,7 +41,10 @@ def merge_strings():
 
     language = args.language
 
-    if language not in renpy.game.script.translator.strings: # @UndefinedVariable
+    if language == 'None':
+        language = None
+
+    if language not in renpy.game.script.translator.strings:  # @UndefinedVariable
         raise Exception("Language %r does not have any translations." % language)
 
     with io.open(args.source, "r", encoding="utf-8") as f:
@@ -54,7 +58,7 @@ def merge_strings():
 
         data = new_data
 
-    st = renpy.game.script.translator.strings[language] # @UndefinedVariable
+    st = renpy.game.script.translator.strings[language]  # @UndefinedVariable
 
     renpy.config.clear_lines = False
 
@@ -79,4 +83,3 @@ def merge_strings():
     return False
 
 renpy.arguments.register_command("merge_strings", merge_strings)
-
diff --git a/renpy/translation/scanstrings.py b/renpy/translation/scanstrings.py
new file mode 100644
index 0000000..3701f82
--- /dev/null
+++ b/renpy/translation/scanstrings.py
@@ -0,0 +1,223 @@
+# Copyright 2004-2016 Tom Rothamel <pytom at bishoujo.us>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import print_function, unicode_literals
+
+import os
+import re
+import codecs
+
+import renpy.translation
+
+################################################################################
+
+STRING_RE = r"""(?x)
+\b__?\s*\(\s*[uU]?(
+\"\"\"(?:\\.|\"{1,2}|[^\\"])*?\"\"\"
+|'''(?:\\.|\'{1,2}|[^\\'])*?'''
+|"(?:\\.|[^\\"])*"
+|'(?:\\.|[^\\'])*'
+)\s*\)
+"""
+
+REGULAR_PRIORITIES = [
+    ("script.rpy", 5, "script.rpy"),
+    ("options.rpy", 10, "options.rpy"),
+    ("gui.rpy", 20, "gui.rpy"),
+    ("screens.rpy", 30, "screens.rpy"),
+    ("", 100, "launcher.rpy"),
+]
+
+
+COMMON_PRIORITIES = [
+    ("_compat/", 420, "obsolete.rpy"),
+    ("_layout/", 410, "obsolete.rpy"),
+    ("00layout.rpy", 400, "obsolete.rpy"),
+
+    ("00console.rpy", 320, "developer.rpy"),
+    ("_developer/", 310, "developer.rpy"),
+
+    ("_errorhandling.rpym", 220, "error.rpy"),
+    ("00gamepad.rpy", 210, "error.rpy"),
+    ("00gltest.rpy", 200, "error.rpy"),
+
+    ("00gallery.rpy", 180, "common.rpy"),
+    ("00compat.rpy", 180, "common.rpy"),
+    ("00updater.rpy", 170, "common.rpy"),
+    ("00gamepad.rpy", 160, "common.rpy"),
+    ("00iap.rpy", 150, "common.rpy"),
+    ("", 50, "common.rpy"),
+]
+
+
+class String(object):
+    """
+    This stores information about a translation string or comment.
+    """
+
+    def __init__(self, filename, line, text, comment):
+
+        # The full path to the file the strings came from.
+        self.filename = filename
+
+        # The line number of the translation string.
+        self.line = line
+
+        # The translation text.
+        self.text = text
+
+        # True if this is the translation of a comment.
+        self.comment = comment
+
+        # The elided filename, and if this is in the common directory.
+        self.elided, self.common = renpy.translation.generation.shorten_filename(self.filename)
+
+        if self.common:
+            pl = COMMON_PRIORITIES
+        else:
+            pl = REGULAR_PRIORITIES
+
+        for prefix, priority, launcher_file in pl:
+            if self.elided.startswith(prefix):
+                break
+
+        self.priority = priority
+        self.sort_key = (priority, self.filename, self.line)
+
+        # The launcher translation file this goes into.
+        self.launcher_file = launcher_file
+
+    def __repr__(self):
+        return "<String {self.filename}:{self.line} {self.text!r}>".format(self=self)
+
+
+def scan_strings(filename):
+    """
+    Scans `filename`, a file containing Ren'Py script, for translatable
+    strings.
+
+    Returns a list of TranslationString objects.
+    """
+
+    rv = [ ]
+
+    for line, s in renpy.game.script.translator.additional_strings[filename]:  # @UndefinedVariable
+        rv.append(String(filename, line, s, False))
+
+    for _filename, lineno, text in renpy.parser.list_logical_lines(filename):
+
+        for m in re.finditer(STRING_RE, text):
+
+            s = m.group(1)
+            if s is not None:
+                s = s.strip()
+                s = "u" + s
+                s = eval(s)
+
+                if s:
+                    rv.append(String(filename, lineno, s, False))
+
+    return rv
+
+
+def scan_comments(filename):
+
+    rv = [ ]
+
+    if filename not in renpy.config.translate_comments:
+        return rv
+
+    comment = [ ]
+    start = 0
+
+    with codecs.open(filename, "r", "utf-8") as f:
+        lines = [ i.rstrip() for i in f.read().replace(u"\ufeff", "").split('\n') ]
+
+    for i, l in enumerate(lines):
+
+        if not comment:
+            start = i + 1
+
+        m = re.match(r'\s*## (.*)', l)
+
+        if m:
+            c = m.group(1)
+
+            if comment:
+                c = c.strip()
+
+            comment.append(c)
+
+        elif comment:
+            s = "## " + " ".join(comment)
+
+            if s.endswith("#"):
+                s = s.rstrip("# ")
+
+            comment = [ ]
+
+            rv.append(String(filename, start, s, True))
+
+    return rv
+
+
+def scan(min_priority=0, max_priority=299, common_only=False):
+    """
+    Scans all files for translatable strings and comments. Returns a list
+    of String objects.
+    """
+
+    filenames = renpy.translation.generation.translate_list_files()
+
+    strings = [ ]
+
+    for filename in filenames:
+        filename = os.path.normpath(filename)
+
+        if not os.path.exists(filename):
+            continue
+
+        strings.extend(scan_strings(filename))
+        strings.extend(scan_comments(filename))
+
+    strings.sort(key=lambda s : s.sort_key)
+
+    rv = [  ]
+    seen = set()
+
+    for s in strings:
+
+        if s.priority < min_priority:
+            continue
+
+        if s.priority > max_priority:
+            continue
+
+        if common_only and not s.common:
+            continue
+
+        if s.text in seen:
+            continue
+
+        seen.add(s.text)
+        rv.append(s)
+
+    return rv
diff --git a/renpy/ui.py b/renpy/ui.py
index 9c8a340..9059a32 100644
--- a/renpy/ui.py
+++ b/renpy/ui.py
@@ -35,6 +35,7 @@ from renpy.display.behavior import is_selected, is_sensitive
 ##############################################################################
 # Special classes that can be subclassed from the outside.
 
+
 class Action(renpy.object.Object):
     """
     This can be passed to the clicked method of a button or hotspot. It is
@@ -60,6 +61,7 @@ class Action(renpy.object.Object):
     def __call__(self):
         raise Exception("Not implemented")
 
+
 class BarValue(renpy.object.Object):
     """
     This can be passed to the value method of bar and hotbar.
@@ -93,7 +95,9 @@ class Addable(object):
     def get_layer(self):
         return Exception("Operation can only be performed on a layer.")
 
+
 class Layer(Addable):
+
     def __init__(self, name):
         self.name = name
 
@@ -133,13 +137,13 @@ class Many(Addable):
             imagemap = imagemap_stack.pop()
             imagemap.cache.finish()
 
-
         if d and d != self.displayable:
             raise Exception("ui.close closed %r, not the expected %r." % (self.displayable, d))
 
     def __repr__(self):
         return "<Many: %r>" % self.displayable
 
+
 class One(Addable):
     """
     A widget that expects exactly one child.
@@ -159,6 +163,7 @@ class One(Addable):
     def __repr__(self):
         return "<One: %r>" % self.displayable
 
+
 class Detached(Addable):
     """
     Used to indicate a widget is detached from the stack.
@@ -174,6 +179,7 @@ class Detached(Addable):
     def close(self, d):
         raise Exception("Detached expects to be given a child.")
 
+
 class ChildOrFixed(Addable):
     """
     If one widget is added, then it is added directly to our
@@ -230,7 +236,8 @@ def reset():
 
 renpy.game.post_init.append(reset)
 
-def interact(type='misc', roll_forward=None, **kwargs): #@ReservedAssignment
+
+def interact(type='misc', roll_forward=None, **kwargs):  # @ReservedAssignment
     """
     :doc: ui
     :args: (roll_forward=None, mouse='default')
@@ -284,10 +291,12 @@ def interact(type='misc', roll_forward=None, **kwargs): #@ReservedAssignment
     else:
         return rv
 
+
 def tag(name):
     global add_tag
     add_tag = name
 
+
 def child_or_fixed():
     """
     Causes the current widget to be given child-fixed semantics. This
@@ -298,14 +307,17 @@ def child_or_fixed():
 
     stack.append(ChildOrFixed(stack[-1].style_prefix))
 
+
 def remove(d):
     layer = stack[-1].get_layer()
     renpy.game.context(-1).scene_lists.remove(layer, d)
 
+
 def remove_above(d):
     layer = stack[-1].get_layer()
     renpy.game.context(-1).scene_lists.remove_above(layer, d)
 
+
 def at(transform):
     """
     :doc: ui
@@ -317,10 +329,12 @@ def at(transform):
 
     at_stack.append(transform)
 
+
 def clear():
     layer = stack[-1].get_layer()
     renpy.game.context(-1).scene_lists.clear(layer)
 
+
 def detached():
     """
     :doc: ui
@@ -333,6 +347,7 @@ def detached():
     stack.append(rv)
     return rv
 
+
 def layer(name):
     """
     :doc: ui
@@ -343,6 +358,7 @@ def layer(name):
 
     stack.append(Layer(name))
 
+
 def close(d=None):
     """
     :doc: ui
@@ -358,6 +374,7 @@ def close(d=None):
     if not stack:
         raise Exception("ui.close() called when no layer or widget is open.")
 
+
 def reopen(w, clear):
 
     stack.append(Many(w))
@@ -365,17 +382,20 @@ def reopen(w, clear):
     if clear:
         w.children[:] = [ ]
 
+
 def context_enter(w):
     if isinstance(renpy.ui.stack[-1], renpy.ui.Many) and renpy.ui.stack[-1].displayable is w:
         return
 
     raise Exception("%r cannot be used as a context manager.", type(w).__name__)
 
+
 def context_exit(w):
     close(w)
 
 NoStylePrefixGiven = renpy.object.Sentinel("NoStylePrefixGiven")
 
+
 def combine_style(style_prefix, style_suffix):
     """
     Combines a style prefix and style suffix to create a style name, then
@@ -387,7 +407,8 @@ def combine_style(style_prefix, style_suffix):
     else:
         new_style = style_prefix + "_" + style_suffix
 
-    return renpy.style.get_style(new_style) # @UndefinedVariable
+    return renpy.style.get_style(new_style)  # @UndefinedVariable
+
 
 def prefixed_style(style_suffix):
     """
@@ -401,6 +422,7 @@ def prefixed_style(style_suffix):
 # screen.
 screen = None
 
+
 class Wrapper(renpy.object.Object):
 
     def __reduce__(self):
@@ -438,7 +460,7 @@ class Wrapper(renpy.object.Object):
 
         # Pull out the special kwargs, widget_id, at, and style_prefix.
 
-        widget_id = kwargs.pop("id", None) #@ReservedAssignment
+        widget_id = kwargs.pop("id", None)  # @ReservedAssignment
 
         at_list = kwargs.pop("at", [ ])
         if not isinstance(at_list, (list, tuple)):
@@ -487,13 +509,13 @@ class Wrapper(renpy.object.Object):
 
         try:
             w = self.function(*args, **keyword)
-        except TypeError, e:
+        except TypeError as e:
             etype, e, tb = sys.exc_info(); etype
 
             if tb.tb_next is None:
                 e.args = (e.args[0].replace("__call__", "ui." + self.name), )
 
-            del tb # Important! Prevents memory leaks via our frame.
+            del tb  # Important! Prevents memory leaks via our frame.
             raise
 
         main = w._main or w
@@ -564,6 +586,7 @@ def _add(d, **kwargs):
 
 add = Wrapper(_add)
 
+
 def _implicit_add(d):
     """
     A faster version of add to use when we know `d` is a displayable and isn't
@@ -574,6 +597,7 @@ def _implicit_add(d):
 
 implicit_add = Wrapper(_implicit_add)
 
+
 def _image(im, **properties):
     d = renpy.display.im.image(im, loose=True, **properties)
 
@@ -592,6 +616,7 @@ fixed = Wrapper(renpy.display.layout.MultiBox, layout="fixed", style="fixed", ma
 grid = Wrapper(renpy.display.layout.Grid, style="grid", many=True)
 side = Wrapper(renpy.display.layout.Side, style="side", many=True)
 
+
 def _sizer(maxwidth=None, maxheight=None, **properties):
     return renpy.display.layout.Container(xmaximum=maxwidth, ymaximum=maxheight, **properties)
 
@@ -604,6 +629,7 @@ saybehavior = Wrapper(renpy.display.behavior.SayBehavior)
 pausebehavior = Wrapper(renpy.display.behavior.PauseBehavior)
 soundstopbehavior = Wrapper(renpy.display.behavior.SoundStopBehavior)
 
+
 def _key(key, action=None, activate_sound=None):
 
     if action is None:
@@ -613,6 +639,7 @@ def _key(key, action=None, activate_sound=None):
 
 key = Wrapper(_key)
 
+
 class ChoiceActionBase(Action):
     """
     Base class for choice actions. The choice is identified by a label
@@ -622,6 +649,7 @@ class ChoiceActionBase(Action):
     If a location is supplied, it will check whether the choice was
     previously visited and mark it so if it is chosen.
     """
+
     def __init__(self, label, value, location=None, block_all=None):
         self.label = label
         self.value = value
@@ -640,7 +668,6 @@ class ChoiceActionBase(Action):
             if self.chosen is None:
                 self.chosen = renpy.game.persistent._chosen = { }
 
-
     def get_sensitive(self):
         return not renpy.exports.in_fixed_rollback() or (not self.block_all and self.get_selected())
 
@@ -654,6 +681,7 @@ class ChoiceActionBase(Action):
 
         return (self.location, self.label) in self.chosen
 
+
 class ChoiceReturn(ChoiceActionBase):
     """
     :doc: blockrollback
@@ -691,14 +719,13 @@ class ChoiceReturn(ChoiceActionBase):
         to :func:`ui.interact`.
     """
 
-
-
     def __call__(self):
         if self.chosen is not None:
             self.chosen[(self.location, self.label)] = True
 
         return self.value
 
+
 class ChoiceJump(ChoiceActionBase):
     """
     :doc: blockrollback
@@ -736,7 +763,6 @@ class ChoiceJump(ChoiceActionBase):
         to :func:`ui.interact`.
     """
 
-
     def get_selected(self):
         roll_forward = renpy.exports.roll_forward_info()
 
@@ -754,7 +780,7 @@ class ChoiceJump(ChoiceActionBase):
 
 
 def menu(menuitems,
-         style = 'menu',
+         style='menu',
          caption_style='menu_caption',
          choice_style='menu_choice',
          choice_chosen_style='menu_choice_chosen',
@@ -780,8 +806,8 @@ def menu(menuitems,
             clicked = ChoiceReturn(label, val, location)
 
             if clicked.get_chosen():
-                    text = choice_chosen_style
-                    button = choice_chosen_button_style
+                text = choice_chosen_style
+                button = choice_chosen_button_style
 
             if isinstance(button, basestring):
                 button = getattr(renpy.game.style, button)
@@ -800,7 +826,8 @@ def menu(menuitems,
 
     close()
 
-input = Wrapper(renpy.display.behavior.Input, exclude='{}', style="input", replaces=True) #@ReservedAssignment
+input = Wrapper(renpy.display.behavior.Input, exclude='{}', style="input", replaces=True)  # @ReservedAssignment
+
 
 def imagemap_compat(ground,
                     selected,
@@ -831,8 +858,8 @@ def imagemap_compat(ground,
 
         imagebutton(renpy.display.layout.LiveCrop((x0, y0, x1 - x0, y1 - y0), unselected),
                     selected_img,
-                    selected_idle_image = selected_img,
-                    selected_insensitive_image = selected_img,
+                    selected_idle_image=selected_img,
+                    selected_insensitive_image=selected_img,
                     clicked=action,
                     style=button_style[result],
                     xpos=x0,
@@ -846,14 +873,15 @@ def imagemap_compat(ground,
 
 button = Wrapper(renpy.display.behavior.Button, style='button', one=True)
 
-def _imagebutton(idle_image = None,
-                 hover_image = None,
-                 insensitive_image = None,
-                 activate_image = None,
-                 selected_idle_image = None,
-                 selected_hover_image = None,
-                 selected_insensitive_image = None,
-                 selected_activate_image = None,
+
+def _imagebutton(idle_image=None,
+                 hover_image=None,
+                 insensitive_image=None,
+                 activate_image=None,
+                 selected_idle_image=None,
+                 selected_hover_image=None,
+                 selected_insensitive_image=None,
+                 selected_activate_image=None,
                  idle=None,
                  hover=None,
                  insensitive=None,
@@ -887,18 +915,19 @@ def _imagebutton(idle_image = None,
     selected_insensitive = choice(selected_insensitive, selected_insensitive_image, "selected_insensitive")
 
     return renpy.display.behavior.ImageButton(
-            idle,
-            hover,
-            insensitive_image = insensitive,
-            activate_image = activate_image,
-            selected_idle_image = selected_idle,
-            selected_hover_image = selected_hover,
-            selected_insensitive_image = selected_insensitive,
-            selected_activate_image = selected_activate_image,
-            **properties)
+        idle,
+        hover,
+        insensitive_image=insensitive,
+        activate_image=activate_image,
+        selected_idle_image=selected_idle,
+        selected_hover_image=selected_hover,
+        selected_insensitive_image=selected_insensitive,
+        selected_activate_image=selected_activate_image,
+        **properties)
 
 imagebutton = Wrapper(_imagebutton, style="image_button")
 
+
 def _textbutton(label, clicked=None, style=None, text_style=None, substitute=True, scope=None, **kwargs):
 
     text_kwargs, button_kwargs = renpy.easy.split_properties(kwargs, "text_", "")
@@ -914,7 +943,7 @@ def _textbutton(label, clicked=None, style=None, text_style=None, substitute=Tru
         style = prefixed_style("button")
 
     if text_style is None:
-        text_style = renpy.style.get_text_style(style, prefixed_style('button_text')) # @UndefinedVariable
+        text_style = renpy.style.get_text_style(style, prefixed_style('button_text'))  # @UndefinedVariable
 
     rv = renpy.display.behavior.Button(style=style, clicked=clicked, **button_kwargs)
     text = renpy.text.text.Text(label, style=text_style, substitute=substitute, scope=scope, **text_kwargs)
@@ -925,6 +954,7 @@ def _textbutton(label, clicked=None, style=None, text_style=None, substitute=Tru
 
 textbutton = Wrapper(_textbutton)
 
+
 def _label(label, style=None, text_style=None, substitute=True, scope=None, **kwargs):
 
     text_kwargs, label_kwargs = renpy.easy.split_properties(kwargs, "text_", "")
@@ -933,7 +963,7 @@ def _label(label, style=None, text_style=None, substitute=True, scope=None, **kw
         style = prefixed_style('label')
 
     if text_style is None:
-        text_style = renpy.style.get_text_style(style, prefixed_style('label_text')) # @UndefinedVariable
+        text_style = renpy.style.get_text_style(style, prefixed_style('label_text'))  # @UndefinedVariable
 
     rv = renpy.display.layout.Window(None, style=style, **label_kwargs)
     text = renpy.text.text.Text(label, style=text_style, substitute=substitute, scope=scope, **text_kwargs)
@@ -946,16 +976,17 @@ label = Wrapper(_label)
 
 adjustment = renpy.display.behavior.Adjustment
 
+
 def _bar(*args, **properties):
 
     if len(args) == 4:
-        width, height, range, value = args #@ReservedAssignment
+        width, height, range, value = args  # @ReservedAssignment
     if len(args) == 2:
-        range, value = args #@ReservedAssignment
+        range, value = args  # @ReservedAssignment
         width = None
         height = None
     else:
-        range = 1 #@ReservedAssignment
+        range = 1  # @ReservedAssignment
         value = 0
         width = None
         height = None
@@ -967,7 +998,7 @@ def _bar(*args, **properties):
         height  = properties.pop("height")
 
     if "range" in properties:
-        range = properties.pop("range") #@ReservedAssignment
+        range = properties.pop("range")  # @ReservedAssignment
 
     if "value" in properties:
         value = properties.pop("value")
@@ -993,7 +1024,8 @@ vslider = Wrapper(_bar, style='vslider', replaces=True)
 scrollbar = Wrapper(_bar, style='scrollbar', replaces=True)
 vscrollbar = Wrapper(_bar, style='vscrollbar', replaces=True)
 
-def _autobar_interpolate(range, start, end, time, st, at, **properties): #@ReservedAssignment
+
+def _autobar_interpolate(range, start, end, time, st, at, **properties):  # @ReservedAssignment
 
     if st > time:
         t = 1.0
@@ -1007,7 +1039,8 @@ def _autobar_interpolate(range, start, end, time, st, at, **properties): #@Reser
 
 autobar_interpolate = renpy.curry.curry(_autobar_interpolate)
 
-def _autobar(range, start, end, time, **properties): #@ReservedAssignment
+
+def _autobar(range, start, end, time, **properties):  # @ReservedAssignment
     return renpy.display.layout.DynamicDisplayable(autobar_interpolate(range, start, end, time, **properties))
 
 autobar = Wrapper(_autobar)
@@ -1016,6 +1049,7 @@ transform = Wrapper(renpy.display.motion.Transform, one=True, style='transform')
 _viewport = Wrapper(renpy.display.viewport.Viewport, one=True, replaces=True, style='viewport')
 _vpgrid = Wrapper(renpy.display.viewport.VPGrid, many=True, replaces=True, style='vpgrid')
 
+
 def viewport_common(vpfunc, scrollbars=None, **properties):
 
     if scrollbars is None:
@@ -1073,9 +1107,11 @@ def viewport_common(vpfunc, scrollbars=None, **properties):
 
         return rv
 
+
 def viewport(**properties):
     return viewport_common(_viewport, **properties)
 
+
 def vpgrid(**properties):
     return viewport_common(_vpgrid, **properties)
 
@@ -1130,7 +1166,6 @@ def _imagemap(ground=None, hover=None, insensitive=None, idle=None, selected_hov
 
         raise Exception("Could not find a %s image for imagemap." % name)
 
-
     ground = pick(ground, "ground", None)
     idle = pick(idle, "idle", ground)
     selected_idle = pick(selected_idle, "selected_idle", idle)
@@ -1170,6 +1205,7 @@ def _imagemap(ground=None, hover=None, insensitive=None, idle=None, selected_hov
 
 imagemap = Wrapper(_imagemap, imagemap=True, style='imagemap')
 
+
 def _hotspot(spot, style='hotspot', **properties):
 
     if not imagemap_stack:
@@ -1222,11 +1258,13 @@ def _hotspot(spot, style='hotspot', **properties):
 
 hotspot_with_child = Wrapper(_hotspot, style="hotspot", one=True)
 
+
 def hotspot(*args, **kwargs):
     hotspot_with_child(*args, **kwargs)
     null()
 
-def _hotbar(spot, adjustment=None, range=None, value=None, **properties): #@ReservedAssignment
+
+def _hotbar(spot, adjustment=None, range=None, value=None, **properties):  # @ReservedAssignment
 
     if (adjustment is None) and (range is None) and (value is None):
         raise Exception("hotbar requires either an adjustment or a range and value.")
@@ -1256,22 +1294,22 @@ def _hotbar(spot, adjustment=None, range=None, value=None, **properties): #@Rese
         hover_fore_bar, hover_aft_bar = hover_aft_bar, hover_fore_bar
 
     return renpy.display.behavior.Bar(
-            adjustment=adjustment,
-            range=range,
-            value=value,
-            fore_bar=fore_bar,
-            aft_bar=aft_bar,
-            hover_fore_bar=hover_fore_bar,
-            hover_aft_bar=hover_aft_bar,
-            fore_gutter=0,
-            aft_gutter=0,
-            bar_resizing=False,
-            thumb=None,
-            thumb_shadow=None,
-            thumb_offset=0,
-            xmaximum=w,
-            ymaximum=h,
-            **properties)
+        adjustment=adjustment,
+        range=range,
+        value=value,
+        fore_bar=fore_bar,
+        aft_bar=aft_bar,
+        hover_fore_bar=hover_fore_bar,
+        hover_aft_bar=hover_aft_bar,
+        fore_gutter=0,
+        aft_gutter=0,
+        bar_resizing=False,
+        thumb=None,
+        thumb_shadow=None,
+        thumb_offset=0,
+        xmaximum=w,
+        ymaximum=h,
+        **properties)
 
 hotbar = Wrapper(_hotbar, style="hotbar", replaces=True)
 
@@ -1285,6 +1323,7 @@ def _returns(v):
 
 returns = renpy.curry.curry(_returns)
 
+
 def _jumps(label, transition=None):
 
     if isinstance(transition, basestring):
@@ -1297,18 +1336,22 @@ def _jumps(label, transition=None):
 
 jumps = renpy.curry.curry(_jumps)
 
+
 def _jumpsoutofcontext(label):
 
     raise renpy.game.JumpOutException(label)
 
 jumpsoutofcontext = renpy.curry.curry(_jumpsoutofcontext)
 
+
 def callsinnewcontext(*args, **kwargs):
     return renpy.exports.curried_call_in_new_context(*args, **kwargs)
 
+
 def invokesinnewcontext(*args, **kwargs):
     return renpy.exports.curried_invoke_in_new_context(*args, **kwargs)
 
+
 def gamemenus(*args):
     return callsinnewcontext("_game_menu", *args)
 
@@ -1319,6 +1362,8 @@ on = Wrapper(renpy.display.behavior.OnEvent)
 
 ##############################################################################
 # A utility function so CDD components can be given an id.
+
+
 def screen_id(id_, d):
     """
     :doc: ui
diff --git a/renpy/vc_version.py b/renpy/vc_version.py
index 63c2b90..bbb7e4c 100644
--- a/renpy/vc_version.py
+++ b/renpy/vc_version.py
@@ -1 +1 @@
-vc_version = 1749
\ No newline at end of file
+vc_version = 2003
\ No newline at end of file
diff --git a/renpy/warp.py b/renpy/warp.py
index 9516ca8..f3552e6 100644
--- a/renpy/warp.py
+++ b/renpy/warp.py
@@ -28,6 +28,7 @@ import sets
 
 warp_spec = None
 
+
 def warp():
     """
     Given a filename and line number, this attempts to warp the user
@@ -60,7 +61,7 @@ def warp():
     seenset = sets.Set(workset)
 
     # This is called to indicate that next can be executed following node.
-    def add(node, next): #@ReservedAssignment
+    def add(node, next):  # @ReservedAssignment
         if next not in seenset:
             seenset.add(next)
             workset.add(next)
diff --git a/templates/japanese/project.json b/templates/japanese/project.json
index 65f5a15..71ed072 100644
--- a/templates/japanese/project.json
+++ b/templates/japanese/project.json
@@ -1 +1 @@
-{ "type" : "template" }
+{ "type" : "template", "font" : "MTLc3m.ttf" }
diff --git a/templates/korean/project.json b/templates/korean/project.json
index 65f5a15..a988d31 100644
--- a/templates/korean/project.json
+++ b/templates/korean/project.json
@@ -1 +1 @@
-{ "type" : "template" }
+{ "type" : "template", "font" : "NanumGothic.ttf" }
diff --git a/templates/simplified_chinese/project.json b/templates/simplified_chinese/project.json
index 65f5a15..ef87c5e 100644
--- a/templates/simplified_chinese/project.json
+++ b/templates/simplified_chinese/project.json
@@ -1 +1 @@
-{ "type" : "template" }
+{ "type" : "template", "font" : "DroidSansFallback.ttf" }
diff --git a/templates/traditional_chinese/project.json b/templates/traditional_chinese/project.json
index 65f5a15..ef87c5e 100644
--- a/templates/traditional_chinese/project.json
+++ b/templates/traditional_chinese/project.json
@@ -1 +1 @@
-{ "type" : "template" }
+{ "type" : "template", "font" : "DroidSansFallback.ttf" }
diff --git a/tutorial/dialogue.tab b/tutorial/dialogue.tab
new file mode 100644
index 0000000..2619a83
--- /dev/null
+++ b/tutorial/dialogue.tab
@@ -0,0 +1,617 @@
+Identifier	Character	Dialogue	Filename	Line Number
+		Eileen	game/demo_character.rpy	6
+demo_character_16897d85	e	The Character object is used to declare characters, and it can also be used to customize the way in which a character speaks.	game/demo_character.rpy	45
+demo_character_7ad48073	e	By supplying it with the appropriate arguments, we can really change around the feel of the game.	game/demo_character.rpy	47
+demo_character_6fc5bef5	e	In this section, we'll demonstrate some of what can be accomplished by customizing character objects.	game/demo_character.rpy	49
+demo_character_2edcd1df	equote	By supplying what_prefix and what_suffix arguments to a Character object, we can automatically add things before each line of text.	game/demo_character.rpy	51
+demo_character_3ba649df	equote	This is a lot easier than having to put those quotes in by hand.	game/demo_character.rpy	53
+demo_character_48dc5333	equote	We can also use who_prefix and who_suffix to add text to the name of the speaker.	game/demo_character.rpy	55
+demo_character_77ce5256	e	We can also supply arguments to the Character object that customize the look of the character name, the text that is being said, and the window itself.	game/demo_character.rpy	57
+demo_character_fceb39fb	eweird	These can really change the look of the game.	game/demo_character.rpy	59
+demo_character_92ae524c	eside	A more practical use of that is in conjunction with show_side_image, which lets us position an image next to the text.	game/demo_character.rpy	61
+demo_character_ba09ee13	etwo	There's also show_two_window, which puts the character's name in its own window.	game/demo_character.rpy	63
+demo_character_91f8f1cc	ectc	Finally, we demonstrate a click to continue indicator. In this example, it's nestled in with the text.	game/demo_character.rpy	65
+demo_character_90e5383f	ectcf	A click to continue image can also be placed at a fixed location on the screen.	game/demo_character.rpy	67
+demo_character_4a210bad	e	There's a lot more you can do with Character, as it lets you set style properties on all of the displayed text.	game/demo_character.rpy	69
+demo_character_0393756f	e	Finally, let me point out a couple of special characters we pre-define.	game/demo_character.rpy	71
+demo_character_29688b7c	centered	The \"centered\" character shows text at the center of the screen, without a window.	game/demo_character.rpy	76
+demo_character_496243d7	centered	It's just a highly customized normal character, that's useful for dates and titles.	game/demo_character.rpy	78
+demo_character_e79e9042	e	The \"extend\" character is very special.	game/demo_character.rpy	83
+demo_character_0b55b872	e	It lets you	game/demo_character.rpy	85
+demo_character_7c80c8fc	extend	 extend the previous dialogue	game/demo_character.rpy	89
+demo_character_645bb443	extend	 with additional text.	game/demo_character.rpy	93
+demo_character_170d938b	e	That lets you have things happen in the middle of text. If you didn't notice, I was changing my expression.	game/demo_character.rpy	95
+demo_character_4adb20a9	e	Hopefully, these characters, along with the ones you define, will lead to a very expressive game.	game/demo_character.rpy	97
+		Start Game	game/screens.rpy	194
+		Load Game	game/screens.rpy	195
+		Preferences	game/screens.rpy	196
+		Help	game/screens.rpy	197
+		Save Game	game/screens.rpy	230
+		Main Menu	game/screens.rpy	232
+		Previous	game/screens.rpy	266
+		Auto	game/screens.rpy	269
+		Quick	game/screens.rpy	272
+		Next	game/screens.rpy	279
+		Empty Slot.	game/screens.rpy	305
+		Display	game/screens.rpy	361
+		Window	game/screens.rpy	362
+		Transitions	game/screens.rpy	369
+		All	game/screens.rpy	370
+		None	game/screens.rpy	371
+		Text Speed	game/screens.rpy	377
+		Joystick...	game/screens.rpy	384
+		Language	game/screens.rpy	391
+		Skip	game/screens.rpy	406
+		Seen Messages	game/screens.rpy	407
+		All Messages	game/screens.rpy	408
+		Begin Skipping	game/screens.rpy	414
+		After Choices	game/screens.rpy	420
+		Stop Skipping	game/screens.rpy	421
+		Keep Skipping	game/screens.rpy	422
+		Auto-Forward Time	game/screens.rpy	428
+		Wait for Voice	game/screens.rpy	432
+		Music Volume	game/screens.rpy	439
+		Sound Volume	game/screens.rpy	446
+		Test	game/screens.rpy	450
+		Voice Volume	game/screens.rpy	459
+		Voice Sustain	game/screens.rpy	462
+		Yes	game/screens.rpy	523
+		No	game/screens.rpy	524
+		Back	game/screens.rpy	552
+		Save	game/screens.rpy	553
+		Q.Save	game/screens.rpy	554
+		Q.Load	game/screens.rpy	555
+		F.Skip	game/screens.rpy	557
+		Prefs	game/screens.rpy	559
+demo_text_ff47a1f2	e	Ren'Py gives you quite a bit of control over how text appears.	game/demo_text.rpy	65
+demo_text_ab9b2f08	e	Text tags let us control the appearance of text that is shown to the user.	game/demo_text.rpy	67
+demo_text_12663c84	e	Text tags can make text bold, italic, struckthrough, or underlined.	game/demo_text.rpy	69
+demo_text_bdfcba5a	e	They can make the font size bigger or smaller.	game/demo_text.rpy	71
+demo_text_4230bb93	e	They let you pause the display of the text, optionally withline breaks.	game/demo_text.rpy	73
+demo_text_e8aec30a	e	They let you include images inside text Neat	game/demo_text.rpy	75
+demo_text_b647b4d4	e	We can pause the text for a short time, and have it auto-advance. Just like that.	game/demo_text.rpy	77
+demo_text_90c83bb6	eslow	We can even have the text auto-advance,	game/demo_text.rpy	79
+demo_text_a134abb3	extend	 when we reach the end of a block of text, in slow text mode.	game/demo_text.rpy	82
+demo_text_d2b1ebbe	e	They can change the color of the text.	game/demo_text.rpy	84
+demo_text_6d050f89	e	The kerning tag lets you adjust the spacing between characters.\nThe spacing between characters can be increased.\nThe spacing between characters can be decreased.	game/demo_text.rpy	88
+demo_text_e8835287	eruby	You are able to write ruby text, which can help clarify how to pronounce words, like Ren'Pyren-pie.	game/demo_text.rpy	90
+demo_text_6e1b95f0	e	Hyperlinks let buttons be defined using text tags.	game/demo_text.rpy	92
+demo_text_245e745a	e	The space and vspace tags add  horizontal and vertical space, respectively.	game/demo_text.rpy	94
+demo_text_362f67bb	e	You can define your own text tags, that use a style you define.	game/demo_text.rpy	96
+demo_text_9225af3b	e	If you find yourself using text tags on every line, you should probably look at style properties instead.	game/demo_text.rpy	98
+demo_text_3b409933	e	Used with care, text tags can enhance your game.	game/demo_text.rpy	100
+demo_text_fcb34ec8	e	Used with abandon, they can make your game hard to read.	game/demo_text.rpy	102
+demo_text_3154619a	e	With great power comes great responsibility, after all.	game/demo_text.rpy	104
+demo_text_12873855	e	And we want to give you all the power you need.	game/demo_text.rpy	106
+demo_text_63b9c010	e	There are a couple of text adjustments that don't correspond to text tags.	game/demo_text.rpy	108
+demo_text_1a6f274c	eoutline	The outlines setting lets you put outlines around the text.	game/demo_text.rpy	110
+demo_text_c130dcd4	eoutline	You can have more than one outline, and each has its own color and offset.	game/demo_text.rpy	112
+demo_text_9eb0448e	esubtitle	Here, we have two outlines around the white text.	game/demo_text.rpy	116
+demo_text_eb22992d	esubtitle	The bottom one is a translucent black that's offset a little, while the top one is green.	game/demo_text.rpy	118
+demo_text_7067acb5	esubtitle	By hiding the window and adjusting the layout method, we are able to create reasonable subtitles.	game/demo_text.rpy	120
+demo_text_123ff836	esubtitle	This might be an interesting look for a game.	game/demo_text.rpy	122
+demo_text_d742e133	esfont	For even more control, Ren'Py supports SFonts, image files containing font information.	game/demo_text.rpy	126
+demo_text_2a8833c0	esfont	SFonts let you use fonts you otherwise couldn't, and apply special effects to fonts using your favorite image editor.	game/demo_text.rpy	128
+demo_text_418ffc27	e	Well, that's it for fonts and text tags.	game/demo_text.rpy	130
+define_hyperlink_8863ed04	definition	A hyperlink is a button that is defined inside text, using text tags. They're ideal for including definitions of words used in the script, but they shouldn't be used in place of menus.	game/demo_text.rpy	138
+demo_transitions_5bbc72fe	e	Ren'Py ships with a large number of built-in transitions, and also includes classes that let you define your own.	game/demo_transitions.rpy	44
+demo_transitions_menu_3caf78d3	e	What kind of transitions would you like demonstrated?	game/demo_transitions.rpy	46
+		Simple Transitions	game/demo_transitions.rpy	46
+		ImageDissolve Transitions	game/demo_transitions.rpy	46
+		MoveTransition Transitions	game/demo_transitions.rpy	46
+		CropMove Transitions	game/demo_transitions.rpy	46
+		PushMove Transitions	game/demo_transitions.rpy	46
+		AlphaDissolve Transitions	game/demo_transitions.rpy	46
+			game/demo_transitions.rpy	46
+		How about something else?	game/demo_transitions.rpy	46
+demo_simple_transitions_2b4fbae3	e	Okay, I can tell you about simple transitions. We call them simple because they don't take much in the way of configuration.	game/demo_transitions.rpy	85
+demo_simple_transitions_4b235ac2	e	But don't let that get you down, since they're the transitions you'll probably use the most in a game.	game/demo_transitions.rpy	87
+demo_simple_transitions_af0431ac	e	The 'dissolve' transition is probably the most useful, blending one scene into another.	game/demo_transitions.rpy	92
+demo_simple_transitions_5b9f711f	e	The 'Dissolve' function lets you create your own dissolves, taking a different amount of time.	game/demo_transitions.rpy	97
+demo_simple_transitions_79816523	e	The 'fade' transition fades to black, and then fades back in to the new scene.	game/demo_transitions.rpy	102
+demo_simple_transitions_141bb95d	e	If you're going to stay at a black screen, you'll probably want to use 'dissolve' rather than 'fade'.	game/demo_transitions.rpy	104
+demo_simple_transitions_f059f4ae	e	You can use 'Fade' to define your own fades. By changing the timing and the color faded to, you can use this for special effects, like flashbulbs.	game/demo_transitions.rpy	108
+demo_simple_transitions_e948905b	e	The 'pixellate' transition pixellates out the old scene, switches to the new scene, and then unpixellates that.	game/demo_transitions.rpy	113
+demo_simple_transitions_6a1ae05f	e	It's probably not appropriate for most games, but we think it's kind of neat.	game/demo_transitions.rpy	115
+demo_simple_transitions_bdfcd85a	e	You can use 'Pixellate' to change the details of the pixellation.	game/demo_transitions.rpy	118
+demo_simple_transitions_432f7224	e	Motions can also be used as transitions.	game/demo_transitions.rpy	120
+demo_simple_transitions_a20cefa7		...	game/demo_transitions.rpy	122
+demo_simple_transitions_0fd4d656		......	game/demo_transitions.rpy	124
+demo_simple_transitions_fbf11906	e	Hey! Pay attention.	game/demo_transitions.rpy	129
+demo_simple_transitions_51c1c5b8	e	I was about to demonstrate 'vpunch'... well, I guess I just did.	game/demo_transitions.rpy	131
+demo_simple_transitions_57f19473	e	We can also shake the screen horizontally, with 'hpunch'. These were defined using the 'Move' function.	game/demo_transitions.rpy	136
+demo_simple_transitions_fce83e12	e	There's also the 'move' transition, which is confusingly enough defined using the 'MoveTransition' function.	game/demo_transitions.rpy	138
+demo_simple_transitions_1050b6a4	e	The 'move' transition finds images that have changed placement, and slides them to their new place. It's an easy way to get motion in your game.	game/demo_transitions.rpy	145
+demo_simple_transitions_fbb1838e	e	Finally, there's 'Pause', which lets you define a transition that just waits for a given amount of time.	game/demo_transitions.rpy	147
+demo_simple_transitions_654a7a87	e	Why would you want to do that?	game/demo_transitions.rpy	149
+demo_simple_transitions_3b8c0bce	e	It's because clicking during a sequence of transitions will skip all of the remaining transitions.	game/demo_transitions.rpy	151
+demo_simple_transitions_6cad71a4	e	Try clicking during the following transitions:	game/demo_transitions.rpy	153
+demo_simple_transitions_c75a0d2d	e	Having 'Pause' makes it easy to implement skippable cut-scenes in terms of transitions.	game/demo_transitions.rpy	161
+demo_simple_transitions_4632f134	e	Anyway, that's it for the simple transitions.	game/demo_transitions.rpy	163
+demo_imagedissolve_transitions_2db67018	e	Perhaps the most flexible kind of transition is the ImageDissolve, which lets you use an image to control a dissolve.	game/demo_transitions.rpy	170
+demo_imagedissolve_transitions_429f8d03	e	This lets us specify very complex transitions, fairly simply. Let's try some, and then I'll show you how they work.	game/demo_transitions.rpy	172
+demo_imagedissolve_transitions_1ce501b0	e	There are two ImageDissolve transitions built into Ren'Py.	game/demo_transitions.rpy	174
+demo_imagedissolve_transitions_ea0413be	e	The 'blinds' transition opens and closes what looks like vertical blinds.	game/demo_transitions.rpy	185
+demo_imagedissolve_transitions_12e2e0d0	e	The 'squares' transition uses these squares to show things.	game/demo_transitions.rpy	194
+demo_imagedissolve_transitions_bbf73d1c	e	I'm not sure why anyone would want to use it, but it was used in some translated games, so we added it.	game/demo_transitions.rpy	196
+demo_imagedissolve_transitions_0ab2902d	e	The most interesting transitions aren't in the standard library.	game/demo_transitions.rpy	198
+demo_imagedissolve_transitions_54aa9bf9	e	These ones require an image the size of the screen, and so we couldn't include them as the size of the screen can change from game to game.	game/demo_transitions.rpy	200
+demo_imagedissolve_transitions_70cfd5ed	e	You can click the button above to see how they are defined in the demo script.	game/demo_transitions.rpy	202
+demo_imagedissolve_transitions_ca316184	e	We can hide things with a 'circleirisin'...	game/demo_transitions.rpy	207
+demo_imagedissolve_transitions_b8fdf2b6	e	... and show them again with a 'circleirisout'.	game/demo_transitions.rpy	212
+demo_imagedissolve_transitions_ee427486	e	The 'circlewipe' transitions changes screens using a circular wipe effect.	game/demo_transitions.rpy	217
+demo_imagedissolve_transitions_6f089276	e	The 'dream' transition does this weird wavy dissolve, and does it relatively slowly.	game/demo_transitions.rpy	222
+demo_imagedissolve_transitions_c0b9d74d	e	The 'teleport' transition reveals the new scene one line at a time.	game/demo_transitions.rpy	227
+demo_imagedissolve_transitions_72ba11d4	e	This is the background picture used with the circleirisout transition.	game/demo_transitions.rpy	232
+demo_imagedissolve_transitions_fc3b3339	e	When we use an ImageDissolve, the white will dissolve in first, followed by progressively darker colors. Let's try it.	game/demo_transitions.rpy	234
+demo_imagedissolve_transitions_4327dca2	e	If we give ImageDissolve the 'reverse' parameter, black areas will dissolve in first.	game/demo_transitions.rpy	239
+demo_imagedissolve_transitions_3a401ee7	e	This lets circleirisin and circleirisout use the same image.	game/demo_transitions.rpy	244
+demo_imagedissolve_transitions_20d9cf6c	e	The teleport transition uses a different image, one that dissolves things in one line at a time.	game/demo_transitions.rpy	249
+demo_imagedissolve_transitions_906f7800	e	A dissolve only seems to affect parts of the scene that have changed...	game/demo_transitions.rpy	254
+demo_imagedissolve_transitions_4b557a29	e	... which is how we apply the teleport effect to a single character.	game/demo_transitions.rpy	259
+demo_imagedissolve_transitions_e16f8d3a	e	For more examples of ImageDissolve, check out the Utsukushii Effects demo.	game/demo_transitions.rpy	261
+demo_imagedissolve_transitions_b6dbf68b	e	It shows how a clever game-maker can use ImageDissolve to create all sorts of effects.	game/demo_transitions.rpy	263
+demo_cropmove_transitions_1711a91e	e	The CropMove transition class provides a wide range of transition effects. It's not used very much in practice, though.	game/demo_transitions.rpy	269
+demo_cropmove_transitions_6d82cfd7	e	I'll stand offscreen, so you can see some of its modes. I'll read out the mode name after each transition.	game/demo_transitions.rpy	274
+demo_cropmove_transitions_4427c78c	e	We first have wiperight...	game/demo_transitions.rpy	279
+demo_cropmove_transitions_6d1810a1	e	...followed by wipeleft... 	game/demo_transitions.rpy	284
+demo_cropmove_transitions_1dd1c6a1	e	...wipeup...	game/demo_transitions.rpy	289
+demo_cropmove_transitions_0ea0fa83	e	...and wipedown.	game/demo_transitions.rpy	294
+demo_cropmove_transitions_c7cb4c16	e	Next, the slides.	game/demo_transitions.rpy	296
+demo_cropmove_transitions_462a442f	e	Slideright...	game/demo_transitions.rpy	301
+demo_cropmove_transitions_f9a2e523	e	...slideleft...	game/demo_transitions.rpy	306
+demo_cropmove_transitions_20ce3e9c	e	...slideup...	game/demo_transitions.rpy	311
+demo_cropmove_transitions_9e00a7a6	e	and slidedown.	game/demo_transitions.rpy	316
+demo_cropmove_transitions_b8a710c1	e	While the slide transitions slide in the new scene, the slideaways slide out the old scene.	game/demo_transitions.rpy	318
+demo_cropmove_transitions_1efb4cd0	e	Slideawayright...	game/demo_transitions.rpy	324
+demo_cropmove_transitions_bfb5dfd7	e	...slideawayleft...	game/demo_transitions.rpy	329
+demo_cropmove_transitions_6c1a4a6f	e	...slideawayup...	game/demo_transitions.rpy	334
+demo_cropmove_transitions_1f994a7b	e	and slideawaydown.	game/demo_transitions.rpy	339
+demo_cropmove_transitions_025ef723	e	We also have a couple of transitions that use a rectangular iris.	game/demo_transitions.rpy	341
+demo_cropmove_transitions_d00d505e	e	There's irisout...	game/demo_transitions.rpy	347
+demo_cropmove_transitions_016a1e0a	e	... and irisin.	game/demo_transitions.rpy	353
+demo_cropmove_transitions_08d753ed	e	It's enough to make you feel a bit dizzy.	game/demo_transitions.rpy	355
+demo_pushmove_transitions_003e506d	e	The PushMove transitions use the new scene to push the old one out. Let's take a look.	game/demo_transitions.rpy	361
+demo_pushmove_transitions_124f375d		There's pushright...	game/demo_transitions.rpy	367
+demo_pushmove_transitions_ce380ccb		...pushleft...	game/demo_transitions.rpy	372
+demo_pushmove_transitions_77629638		...pushdown...	game/demo_transitions.rpy	377
+demo_pushmove_transitions_b7f33c95		... and pushup. And that's it the for the PushMove-based transitions.	game/demo_transitions.rpy	383
+demo_movetransition_14df0e34	e	The most common MoveTransition is move, which slides around images that have changed position on the screen.	game/demo_transitions.rpy	389
+demo_movetransition_84e40422	e	Just like that.	game/demo_transitions.rpy	394
+demo_movetransition_098ee9f1	e	There are also the moveout and movein transitions.	game/demo_transitions.rpy	396
+demo_movetransition_09748f81	e	The moveout transitions (moveoutleft, moveoutright, moveouttop, and moveoutbottom) slide hidden images off the appropriate side of the screen.	game/demo_transitions.rpy	398
+demo_movetransition_5edf6007	e	The movein transitions (moveinleft, moveinright, moveintop, and moveinbottom) slide in new images.	game/demo_transitions.rpy	400
+demo_movetransition_20946d36	e	Let's see them all in action.	game/demo_transitions.rpy	402
+demo_movetransition_569952e3	e	That's it for the moveins and moveouts.	game/demo_transitions.rpy	428
+demo_movetransition_af4c53cf	e	Finally, there are the zoomin and zoomout transtions, which show and hide things using a zoom.	game/demo_transitions.rpy	430
+demo_movetransition_dc5ccd54	e	And that's all there is.	game/demo_transitions.rpy	438
+demo_alphadissolve_3efbde9f	e	The AlphaDissolve transition lets you use one displayable to combine two others. For example...	game/demo_transitions.rpy	444
+demo_alphadissolve_7c08cf8b	e	The AlphaDissolve displayable takes a control displayable, usually an ATL transform.	game/demo_transitions.rpy	452
+demo_alphadissolve_068e3e98	e	To be useful, the control displayable should be partially transparent.	game/demo_transitions.rpy	457
+demo_alphadissolve_6a1b6203	e	During an AlphaDissolve, the old screen is used to fill the transparent areas of the image, while the new screen fills the opaque areas.	game/demo_transitions.rpy	459
+demo_alphadissolve_80a728b6	e	For our spotlight example, the old screen is this all-black image.	game/demo_transitions.rpy	463
+demo_alphadissolve_ce4380eb	e	The new screen is me just standing here.	game/demo_transitions.rpy	468
+demo_alphadissolve_2e95917b	e	By combining them using AlphaDissolve, we can build a complicated effect out of simpler parts.	game/demo_transitions.rpy	476
+tutorial_video_f34a17f5	e	Ren'Py supports playing movies. There are two ways of doing this.	../tutorial_video.rpyc	11
+tutorial_video_4aefd413	e	The first way allows you to show a movie as an image, along with every other image that's displayed on the screen.	../tutorial_video.rpyc	13
+tutorial_video_b927d009	e	To do this, we first have to define an image to be a Movie displayable. Movie displayables require a size argument, and also use properties to position themselves on the screen.	../tutorial_video.rpyc	17
+tutorial_video_fbaa71e4	e	Then, we can show the movie displayable, which starts the movie playing.	../tutorial_video.rpyc	27
+tutorial_video_bbbb242d	e	When we no longer want to play the movie, we can hide it.	../tutorial_video.rpyc	35
+tutorial_video_a66b154c	e	The other way to show a movie is with the renpy.movie_cutscene python function. This shows the movie fullscreen, either until it ends or until the user clicks.	../tutorial_video.rpyc	39
+tutorial_video_7b2dc95f	e	And that's all there is when it comes to movie playback in Ren'Py.	../tutorial_video.rpyc	47
+tutorial_positions_a09a3fd1	e	In this tutorial, I'll teach you how Ren'Py positions things on the screen. But before that, let's learn a little bit about how Python handles numbers.	../tutorial_atl.rpyc	187
+tutorial_positions_ba39aabc	e	There are two main kinds of numbers in Python: integers and floating point numbers. An integer consists entirely of digits, while a floating point number has a decimal point.	../tutorial_atl.rpyc	189
+tutorial_positions_a60b775d	e	For example, 100 is an integer, while 0.5 is a floating point number, or float for short. In this system, there are two zeros: 0 is an integer, and 0.0 is a float.	../tutorial_atl.rpyc	191
+tutorial_positions_7f1a560c	e	Ren'Py uses integers to represent absolute coordinates, and floats to represent fractions of an area with known size.	../tutorial_atl.rpyc	193
+tutorial_positions_8e7d3e52	e	When we're positioning something, the area is usually the entire screen.	../tutorial_atl.rpyc	195
+tutorial_positions_fdcf9d8b	e	Let me get out of the way, and I'll show you where some positions are.	../tutorial_atl.rpyc	197
+tutorial_positions_76d7a5bf	e	The origin is the upper-left corner of the screen. That's where the x position (xpos) and the y position (ypos) are both zero.	../tutorial_atl.rpyc	211
+tutorial_positions_be14c7c3	e	When we increase xpos, we move to the right. So here's an xpos of .5, meaning half the width across the screen.	../tutorial_atl.rpyc	217
+tutorial_positions_9b91be6c	e	Increasing xpos to 1.0 moves us to the right-hand border of the screen.	../tutorial_atl.rpyc	222
+tutorial_positions_80be064f	e	We can also use an absolute xpos, which is given in an absolute number of pixels from the left side of the screen. For example, since this window is 800 pixels across, using an xpos of 400 will return the target to the center of the top row.	../tutorial_atl.rpyc	228
+tutorial_positions_c4d18c0a	e	The y-axis position, or ypos works the same way. Right now, we have a ypos of 0.0.	../tutorial_atl.rpyc	230
+tutorial_positions_16933a61	e	Here's a ypos of 0.5.	../tutorial_atl.rpyc	236
+tutorial_positions_6eb36777	e	A ypos of 1.0 specifies a position at the bottom of the screen. If you look carefully, you can see the position indicator spinning below the text window.	../tutorial_atl.rpyc	241
+tutorial_positions_a423050f	e	Like xpos, ypos can also be an integer. In this case, ypos would give the total number of pixels from the top of the screen.	../tutorial_atl.rpyc	243
+tutorial_positions_bc7a809a	e	Can you guess where this position is, relative to the screen?	../tutorial_atl.rpyc	249
+		xpos 1.0 ypos .5	game/tutorial_atl.rpy	249
+		xpos .75 ypos .25	game/tutorial_atl.rpy	249
+		xpos .25 ypos .33	game/tutorial_atl.rpy	249
+tutorial_positions_6f926e18	e	Sorry, that's wrong. The xpos is .75, and the ypos is .25.	../tutorial_atl.rpyc	255
+tutorial_positions_5d5feb98	e	In other words, it's 75%% of the way from the left side, and 25%% of the way from the top.	../tutorial_atl.rpyc	257
+tutorial_positions_77b45218	e	Good job! You got that position right.	../tutorial_atl.rpyc	261
+tutorial_positions_6f926e18_1	e	Sorry, that's wrong. The xpos is .75, and the ypos is .25.	../tutorial_atl.rpyc	265
+tutorial_positions_5d5feb98_1	e	In other words, it's 75%% of the way from the left side, and 25%% of the way from the top.	../tutorial_atl.rpyc	267
+tutorial_positions_e4380a83	e	The second position we care about is the anchor. The anchor is a spot on the thing being positioned.	../tutorial_atl.rpyc	281
+tutorial_positions_d1db1246	e	For example, here we have an xanchor of 0.0 and a yanchor of 0.0. It's in the upper-left corner of the logo image.	../tutorial_atl.rpyc	283
+tutorial_positions_6056873f	e	When we increase the xanchor to 1.0, the anchor moves to the right corner of the image.	../tutorial_atl.rpyc	288
+tutorial_positions_7cdb8dcc	e	Similarly, when both xanchor and yanchor are 1.0, the anchor is the bottom-right corner.	../tutorial_atl.rpyc	293
+tutorial_positions_03a07da8	e	To place an image on the screen, we need both the position and the anchor.	../tutorial_atl.rpyc	301
+tutorial_positions_8945054f	e	We then line them up, so that both the position and anchor are at the same point on the screen.	../tutorial_atl.rpyc	309
+tutorial_positions_2b184a93	e	When we place both in the upper-left corner, the image moves to the upper-left corner of the screen.	../tutorial_atl.rpyc	319
+tutorial_positions_5aac4f3f	e	With the right combination of position and anchor, any place on the screen can be specified, without even knowing the size of the image.	../tutorial_atl.rpyc	328
+tutorial_positions_3b59b797	e	It's often useful to set xpos and xanchor to the same value. We call that xalign, and it gives a fractional position on the screen.	../tutorial_atl.rpyc	340
+tutorial_positions_b8ebf9fe	e	For example, when we set xalign to 0.0, things are aligned to the left side of the screen.	../tutorial_atl.rpyc	345
+tutorial_positions_8ce35d52	e	When we set it to 1.0, then we're aligned to the right side of the screen.	../tutorial_atl.rpyc	350
+tutorial_positions_6745825f	e	And when we set it to 0.5, we're back to the center of the screen.	../tutorial_atl.rpyc	355
+tutorial_positions_64428a07	e	Setting yalign is similar, except along the y-axis.	../tutorial_atl.rpyc	357
+tutorial_positions_cfb77d42	e	Remember that xalign is just setting xpos and xanchor to the same value, and yalign is just setting ypos and yanchor to the same value.	../tutorial_atl.rpyc	359
+tutorial_positions_0f4ca2b6	e	Once you understand positions, you can use transformations to move things around the Ren'Py screen.	../tutorial_atl.rpyc	366
+tutorial_atl_a1cc1bff	e	While showing static images is often enough for most games, occasionally we'll want to change images, or move them around the screen.	../tutorial_atl.rpyc	373
+tutorial_atl_81dbb8f2	e	We call this a Transform, and it's what ATL, Ren'Py's Animation and Transformation Language, is for.	../tutorial_atl.rpyc	375
+tutorial_atl_65badef3	e	But first, let's have... a Gratuitous Rock Concert!	../tutorial_atl.rpyc	383
+tutorial_atl_3ccfe2ac	e	That was a lot of work, and before you can do that, we'll need to start with the basics of using ATL.	../tutorial_atl.rpyc	391
+tutorial_atl_1f22f875	e	There are currently three places where ATL can be used in Ren'Py.	../tutorial_atl.rpyc	393
+tutorial_atl_fd036bdf	e	The first place ATL can be used is as part of an image statement. Instead of a displayable, an image may be defined as a block of ATL code.	../tutorial_atl.rpyc	397
+tutorial_atl_7cad2ab9	e	When used in this way, we have to be sure that ATL includes one or more displayables to actually show.	../tutorial_atl.rpyc	399
+tutorial_atl_c78b2a1e	e	The second way is through the use of the transform statement. This assigns the ATL block to a python variable, allowing it to be used in at clauses and inside other transforms.	../tutorial_atl.rpyc	403
+tutorial_atl_da7a7759	e	Finally, an ATL block can be used as part of a show statement, instead of the at clause.	../tutorial_atl.rpyc	407
+tutorial_atl_c21bc1d1	e	The key to ATL is what we call composeability. ATL is made up of relatively simple commands, which can be combined together to create complicated transforms.	../tutorial_atl.rpyc	411
+tutorial_atl_ed82983f	e	Before I explain how ATL works, let me explain what animation and transformation are.	../tutorial_atl.rpyc	413
+tutorial_atl_2807adff	e	Animation is when the displayable being shown changes. For example, right now I am changing my expression.	../tutorial_atl.rpyc	418
+tutorial_atl_3eec202b	e	Transformation involves moving or distorting an image. This includes placing it on the screen, zooming it in and out, rotating it, and changing its opacity.	../tutorial_atl.rpyc	445
+tutorial_atl_fbc9bf83	e	To introduce ATL, let's start by looking at at a simple animation. Here's one that consists of five lines of ATL code, contained within an image statement.	../tutorial_atl.rpyc	453
+tutorial_atl_12c839ee	e	In ATL, to change a displayable, simply mention it on a line of ATL code. Here, we're switching back and forth between two images.	../tutorial_atl.rpyc	455
+tutorial_atl_c671ed7d	e	Since we're defining an image, the first line of ATL has to name a displayable. Otherwise, there would be nothing to show.	../tutorial_atl.rpyc	457
+tutorial_atl_99386181	e	The second and fourth lines are pause statements, which cause ATL to wait half of a second each before continuing. That's how we give the delay between images.	../tutorial_atl.rpyc	459
+tutorial_atl_60f2a5e8	e	The final line is a repeat statement. This causes the current block of ATL to be restarted. You can only have one repeat statement per block.	../tutorial_atl.rpyc	461
+tutorial_atl_146cf4c4	e	If we were to write repeat 2 instead, the animation would loop twice, then stop.	../tutorial_atl.rpyc	466
+tutorial_atl_d90b1838	e	Omitting the repeat statement means that the animation stops once we reach the end of the block of ATL code.	../tutorial_atl.rpyc	471
+tutorial_atl_e5872360	e	By default, displayables are replaced instantaneously. We can also use a with clause to give a transition between displayables.	../tutorial_atl.rpyc	476
+tutorial_atl_a7f8ed01	e	Now, let's move on to see how we can use ATL to transform an image. We'll start off by seeing what we can do to position images on the screen.	../tutorial_atl.rpyc	483
+tutorial_atl_24501213	e	Perhaps the simplest thing we can do is to position the images on the screen. This can be done by simply giving the names of the transform properties, each followed by the value.	../tutorial_atl.rpyc	492
+tutorial_atl_43516492	e	With a few more statements, we can move things around on the screen.	../tutorial_atl.rpyc	497
+tutorial_atl_8b053b5a	e	This code starts the image off at the top-right of the screen, and waits a second.	../tutorial_atl.rpyc	499
+tutorial_atl_d7fc5372	e	It then moves it to the left side, waits another second, and repeats.	../tutorial_atl.rpyc	501
+tutorial_atl_7650ec09	e	The pause and repeat statements are the same statements we used in our animations. They work throughout ATL code.	../tutorial_atl.rpyc	503
+tutorial_atl_d3416d4f	e	Having the image jump around on the screen isn't all that useful. That's why ATL has the interpolation statement.	../tutorial_atl.rpyc	508
+tutorial_atl_4e7512ec	e	The interpolation statement allows you to smoothly vary the value of a transform property, from an old to a new value.	../tutorial_atl.rpyc	510
+tutorial_atl_685eeeaa	e	Here, we have an interpolation statement on the second ATL line. It starts off with the name of a time function, in this case linear.	../tutorial_atl.rpyc	512
+tutorial_atl_c5cb49de	e	That's followed by an amount of time, in this case three seconds. It ends with a list of properties, each followed by its new value.	../tutorial_atl.rpyc	514
+tutorial_atl_72d47fb6	e	The old value is the value of the transform property at the start of the statement. By interpolating the property over time, we can change things on the screen.	../tutorial_atl.rpyc	516
+tutorial_atl_2958f397	e	ATL supports more complicated move types, like circle and spline motion. But I won't be showing those here.	../tutorial_atl.rpyc	526
+tutorial_atl_4a02c8d8	e	Next, let's take a look at some of the transform properties that we can change using ATL.	../tutorial_atl.rpyc	528
+tutorial_atl_821fcb91	e	We've already seen the position properties. Along with xalign and yalign, we support the xpos, ypos, xanchor, and yanchor properties.	../tutorial_atl.rpyc	543
+tutorial_atl_cca5082b	e	We can perform a pan by using xpos and ypos to position images off of the screen.	../tutorial_atl.rpyc	558
+tutorial_atl_0394dd50	e	This usually means giving them negative positions.	../tutorial_atl.rpyc	560
+tutorial_atl_2624662e	e	The zoom property lets us scale the displayable by a factor, making it bigger and smaller. For best results, zoom should always be greater than 0.5.	../tutorial_atl.rpyc	577
+tutorial_atl_b6527546	e	The xzoom and yzoom properties allow the displayable to be scaled in the X and Y directions independently.	../tutorial_atl.rpyc	591
+tutorial_atl_9fe238de	e	The size property can be used to set a size, in pixels, that the displayable is scaled to.	../tutorial_atl.rpyc	602
+tutorial_atl_6b982a23	e	The alpha property allows us to vary the opacity of a displayable. This can make it appear and disappear.	../tutorial_atl.rpyc	617
+tutorial_atl_60d6d9f3	e	The rotate property lets us rotate a displayable.	../tutorial_atl.rpyc	631
+tutorial_atl_898a138a	e	Since rotation can change the size, usually you'll want to set xanchor and yanchor to 0.5 when positioning a rotated displayable.	../tutorial_atl.rpyc	633
+tutorial_atl_207b7fc8	e	The crop property crops a rectangle out of a displayable, showing only part of it.	../tutorial_atl.rpyc	644
+tutorial_atl_ebb84988	e	When used together, they can be used to focus in on specific parts of an image.	../tutorial_atl.rpyc	658
+tutorial_atl_d08fe8d9	e	Apart from displayables, pause, interpolation, and repeat, there are a few other statements we can use as part of ATL.	../tutorial_atl.rpyc	664
+tutorial_atl_db6302bd	e	When we create an ATL transform using the transform statement, we can use that transform as an ATL statement.	../tutorial_atl.rpyc	678
+tutorial_atl_785911cf	e	Since the default positions are also transforms, this means that we can use left, right, and center inside of an ATL block.	../tutorial_atl.rpyc	680
+tutorial_atl_331126c1	e	Here, we have two new statements. The block statement allows you to include a block of ATL code. Since the repeat statement applies to blocks, this lets you repeat only part of an ATL transform.	../tutorial_atl.rpyc	698
+tutorial_atl_24f67b67	e	We also have the time statement, which runs after the given number of seconds have elapsed from the start of the block. It will run even if another statement is running, stopping the other statement.	../tutorial_atl.rpyc	700
+tutorial_atl_30dc0008	e	So this code will bounce the image back and forth for eleven and a half seconds, and then move back to the right side of the screen.	../tutorial_atl.rpyc	702
+tutorial_atl_f903bc3b	e	The parallel statement lets us run two blocks of ATL code at the same time.	../tutorial_atl.rpyc	718
+tutorial_atl_5d0f8f9d	e	Here, the top block move the image in the horizontal direction, and the bottom block moves it in the vertical direction. Since they're moving at different speeds, it looks like the image is bouncing on the screen.	../tutorial_atl.rpyc	720
+tutorial_atl_28a7d27e	e	Finally, the choice statement makes Ren'Py randomly pick a block of ATL code. This allows you to add some variation as to what Ren'Py shows.	../tutorial_atl.rpyc	737
+tutorial_atl_5fc8c0df	e	This tutorial game has only scratched the surface of what you can do with ATL. For example, we haven't even covered the on and event statements. For more information, you might want to check out the ATL chapter in the reference manual.	../tutorial_atl.rpyc	743
+tutorial_atl_1358c6b4	e	But for now, just remember that when it comes to animating and transforming, ATL is the hot new thing.	../tutorial_atl.rpyc	747
+		Dismiss	game/demo_ui.rpy	21
+		Morning	game/demo_ui.rpy	60
+		Afternoon	game/demo_ui.rpy	60
+		Evening	game/demo_ui.rpy	60
+		morning	game/demo_ui.rpy	61
+		afternoon	game/demo_ui.rpy	61
+		evening	game/demo_ui.rpy	61
+		Study	game/demo_ui.rpy	62
+		Exercise	game/demo_ui.rpy	62
+		Eat	game/demo_ui.rpy	62
+		Drink	game/demo_ui.rpy	62
+		Be Merry	game/demo_ui.rpy	62
+		March 25th	game/demo_ui.rpy	69
+		Strength	game/demo_ui.rpy	71
+		Intelligence	game/demo_ui.rpy	71
+		Moxie	game/demo_ui.rpy	71
+		Chutzpah	game/demo_ui.rpy	71
+		Statistics	game/demo_ui.rpy	104
+		Continue	game/demo_ui.rpy	135
+		What will you do in the [periods_small_selected!t]?	game/demo_ui.rpy	155
+		To get to the next screen, click the 'Continue' button.	game/demo_ui.rpy	169
+demo_ui_e1d49b5e	e	Ren'Py gives a number of ways of interacting with the user.	game/demo_ui.rpy	220
+demo_ui_313b38c2	e	You've already seen say statements and menus.	game/demo_ui.rpy	222
+demo_ui_fdeef56f	e	But were you aware that you can have dialogue and menus onscreen at the same time?	game/demo_ui.rpy	224
+		Yes.	game/demo_ui.rpy	224
+		No.	game/demo_ui.rpy	224
+demo_ui_d4d568aa	e	Good!	game/demo_ui.rpy	232
+demo_ui_f34995a5	e	Well, now you know.	game/demo_ui.rpy	238
+demo_ui_7cfaf270	e	We can also prompt the user to enter some text.	game/demo_ui.rpy	242
+		What is your name?	game/demo_ui.rpy	244
+		Guy Shy	game/demo_ui.rpy	244
+demo_ui_d77a671d	pov	My name is [povname!t].	game/demo_ui.rpy	246
+demo_ui_b50edd86	e	Imagemaps let the user click on an image to make a choice. For example, the following screen lets you pick what to do after school:	game/demo_ui.rpy	249
+demo_ui_405542a5	e	You chose swimming.	game/demo_ui.rpy	262
+demo_ui_264b5873	e	Swimming seems like a lot of fun, but I didn't bring my bathing suit with me.	game/demo_ui.rpy	264
+demo_ui_83e5c0cc	e	You chose science.	game/demo_ui.rpy	268
+demo_ui_319cdf4b	e	I've heard that some schools have a competitive science team, but to me research is something that can't be rushed.	game/demo_ui.rpy	270
+demo_ui_d2a94440	e	You chose art.	game/demo_ui.rpy	274
+demo_ui_e6af6f1d	e	Really good background art is hard to make, which is why so many games use filtered photographs. Maybe you can change that.	game/demo_ui.rpy	276
+demo_ui_373ea9a5	e	You chose to go home.	game/demo_ui.rpy	280
+demo_ui_48eca0a4	e	Anyway...	game/demo_ui.rpy	282
+demo_ui_aa9bd954	e	We also support viewports, that allow us to display things that are bigger than the screen.	game/demo_ui.rpy	284
+demo_ui_a9db7181	e	This viewport can be adjusted by dragging, by the mouse wheel, and by the scrollbars.	game/demo_ui.rpy	286
+demo_ui_7d821fb9	e	Viewports also support edge scrolling, which is automatic scrolling when the mouse reaches their edge.	game/demo_ui.rpy	299
+demo_ui_42b93520	e	While these constructs are probably enough for most visual novels, dating simulations may be more complicated.	game/demo_ui.rpy	307
+demo_ui_8300d819	e	The ui functions allow you to create quite complicated interfaces.	game/demo_ui.rpy	309
+demo_ui_a070bc2d	e	For example, try the following scheduling and stats screen, which could be used by a stat-based dating simulation.	game/demo_ui.rpy	311
+demo_ui_0d8b1a1c	e	For a better implementation of this, take a look at the dating sim engine (DSE) that ships with Ren'Py.	game/demo_ui.rpy	321
+_call_fight_1_cf0ffdb0	e	The ui functions can be also be used to show the sorts of stats you'd need if your game involves combat.	game/demo_ui.rpy	325
+_call_fight_2_7890ebb9	e	Hopefully, the ui functions will let you write whatever visual novel or dating sim you want.	game/demo_ui.rpy	329
+demo_dynamic_b72548ea	e	The DynamicDisplayable function lets you change what's displayed over the course of an interaction.	game/demo_dynamic.rpy	27
+demo_dynamic_0276dbb9	e	This makes it possible to display things like countdown timers and progress bars.	game/demo_dynamic.rpy	31
+demo_dynamic_4cabf539	e	Remember, people read at different speeds, so it's probably better to use this for flavor, rather then to make games time-sensitive.	game/demo_dynamic.rpy	33
+demo_imageops_0e0e59e0	e	Image operations allow us to manipulate images as they are loaded in.	game/demo_imageops.rpy	69
+demo_imageops_2dfc0c2e	e	They're efficient, as they are only evaluated when an image is first loaded.	game/demo_imageops.rpy	71
+demo_imageops_9ee5a075	e	This way, there's no extra work that needs to be done when each frame is drawn to the screen.	game/demo_imageops.rpy	73
+demo_imageops_3f73f4c2	e	Let me show you a test image, the Ren'Py logo.	game/demo_imageops.rpy	80
+demo_imageops_e3887927	e	We'll be applying some image operations to it, to see how they can be used.	game/demo_imageops.rpy	82
+demo_imageops_d05ba9d9	e	The im.Crop operation can take the image, and chop it up into a smaller image.	game/demo_imageops.rpy	87
+demo_imageops_f57f6496	e	The im.Composite operation lets us take multiple images, and draw them into a single image.	game/demo_imageops.rpy	92
+demo_imageops_634bc9da	e	While you can do this by showing multiple images, this is often more efficient.	game/demo_imageops.rpy	94
+demo_imageops_3a9392e4	e	There's also LiveComposite, which is less efficent, but allows for animation.	game/demo_imageops.rpy	99
+demo_imageops_aab0c08f	e	It isn't really an image operation, but we don't know where else to put it.	game/demo_imageops.rpy	101
+demo_imageops_23cd24da	e	The im.Scale operation lets us scale an image to a particular size.	game/demo_imageops.rpy	106
+demo_imageops_dcaf5d6b	e	im.FactorScale lets us do the same thing, except to a factor of the original size.	game/demo_imageops.rpy	111
+demo_imageops_eeaec24a	e	The im.Map operation lets us mess with the red, green, blue, and alpha channels of an image.	game/demo_imageops.rpy	116
+demo_imageops_a2ed064d	e	In this case, we removed all the red from the image, leaving only the blue and green channels.	game/demo_imageops.rpy	118
+demo_imageops_77b0a263	e	The im.Recolor operation can do the same thing, but is more efficient when we're linearly mapping colors.	game/demo_imageops.rpy	125
+demo_imageops_360723bc	e	The im.Twocolor operation lets you take a black and white image, like this one...	game/demo_imageops.rpy	130
+demo_imageops_0948998c	e	... and assign colors to replace black and white.	game/demo_imageops.rpy	135
+demo_imageops_75522403	e	The im.MatrixColor operation lets you use a matrix to alter the colors. With the right matrix, you can desaturate colors...	game/demo_imageops.rpy	140
+demo_imageops_6fe260b9	e	... tint the image blue...	game/demo_imageops.rpy	145
+demo_imageops_85c10beb	e	... rotate the hue... 	game/demo_imageops.rpy	150
+demo_imageops_09d2d97f	e	... or invert the colors, for a kinda scary look.	game/demo_imageops.rpy	155
+demo_imageops_6dd8f586	e	It can even adjust brightness and contrast.	game/demo_imageops.rpy	160
+demo_imageops_ba8ddf3e	e	We've made some of the most common matrices into image operators.	game/demo_imageops.rpy	162
+demo_imageops_4c62de6f	e	im.Grayscale can make an image grayscale...	game/demo_imageops.rpy	167
+demo_imageops_7d471e4b	e	... while im.Sepia can sepia-tone an image.	game/demo_imageops.rpy	172
+demo_imageops_59ca3a66	e	The im.Alpha operation can adjust the alpha channel on an image, making things partially transparent.	game/demo_imageops.rpy	179
+demo_imageops_514a55db	e	It's useful if a character just happens to be ghost.	game/demo_imageops.rpy	184
+demo_imageops_05fc1200	e	But that isn't the case with me.	game/demo_imageops.rpy	190
+demo_imageops_cf7fbb57	e	Finally, there's im.Flip, which can flip an image horizontally or vertically.	game/demo_imageops.rpy	197
+demo_imageops_49161c26	e	I think the less I say about this, the better.	game/demo_imageops.rpy	199
+demo_layers_c4715eb5	e	Ren'Py lets you define layers, and show images on specific layers.	game/demo_layers.rpy	15
+demo_layers_c385f69e	e	The \"onlayer\" clause of the scene, show, and hide statements lets us pick which layers the commands affect.	game/demo_layers.rpy	26
+demo_layers_89a87205	e	As you can see, layers do not have to take up the entire screen. When a layer doesn't, images are clipped to the layer.	game/demo_layers.rpy	28
+demo_layers_72b6169a	e	The \"as\" clause lets you change the tag of an image.	game/demo_layers.rpy	34
+demo_layers_31adea8e	e	This is useful when you want to show two copies of the same image.	game/demo_layers.rpy	43
+demo_layers_2659ae91	e	Or if a character has a twin.	game/demo_layers.rpy	45
+		This is text.	game/demo_layers.rpy	53
+demo_layers_fa599d50	e	You can use \"show expression\" to show things that aren't just images, like text.	game/demo_layers.rpy	56
+demo_layers_91559c86	e	The \"behind\" clause lets you place an image behind another.	game/demo_layers.rpy	64
+demo_layers_a983efbd	e	Finally, the \"show layer\" statement allows you to apply a transform to an entire layer.	game/demo_layers.rpy	77
+demo_layers_1185c462	e	And that's it for layers and advanced show.	game/demo_layers.rpy	90
+tutorial_playing_2985ab86	e	As someone who has played more than a few visual novels, there are many features that I expect all games to have.	../tutorial_playing.rpyc	16
+tutorial_playing_ca4769bb	e	Features like saving, loading, changing preferences, and so on.	../tutorial_playing.rpyc	18
+tutorial_playing_f30f1979	e	One of the nice things about Ren'Py is that the engine provides many of these features for you. You can spend your time creating your game, and let us provide these things.	../tutorial_playing.rpyc	20
+tutorial_playing_afa743e7	e	While you're in the game, you can access the game menu by right clicking or hitting the escape key.	../tutorial_playing.rpyc	22
+tutorial_playing_8360224a	e	When you first enter the game menu, you'll see the save screen. Clicking on a numbered slot will save the game.	../tutorial_playing.rpyc	28
+tutorial_playing_6d0ef6c9	e	Unlike other engines, Ren'Py doesn't limit the number of save slots that you can use.	../tutorial_playing.rpyc	30
+tutorial_playing_fea05c6b	e	The load screen looks quite similar to the save screen, and lets you load a game from a save slot.	../tutorial_playing.rpyc	32
+tutorial_playing_8e7e83a8	e	It also lets you load one of the auto-saves that Ren'Py makes for you.	../tutorial_playing.rpyc	34
+tutorial_playing_2bad7992	e	The other screen of the game menu is the preferences screen.	../tutorial_playing.rpyc	39
+tutorial_playing_eaac8ba9	e	This screen lets you decide how Ren'Py displays, pick what Ren'Py skips, control text speed and auto-click speed, and adjust sound, music, and voice volumes.	../tutorial_playing.rpyc	41
+tutorial_playing_b1562a34	e	The game menu also lets you end the game and return to the main menu, or quit Ren'Py entirely.	../tutorial_playing.rpyc	43
+tutorial_playing_790f9dc7	e	While the default game menus look a bit generic, with a little work they can be customized or even entirely replaced, allowing you to create menus as unique as your game.	../tutorial_playing.rpyc	48
+tutorial_playing_bc29822e	e	While inside the game, there are a few more things you can do.	../tutorial_playing.rpyc	54
+tutorial_playing_dc0f9cf7	e	When I'm liking a visual novel, I want to see all the endings. Ren'Py's skip function lets me easily do this, by skipping text that I've already seen.	../tutorial_playing.rpyc	56
+tutorial_playing_6dded697	e	I can skip a few lines by holding down Control, or I can toggle skip mode by pressing tab.	../tutorial_playing.rpyc	58
+tutorial_playing_d3553fbe	e	By default, we only skip read text, so this won't do anything the first time through the game.	../tutorial_playing.rpyc	60
+tutorial_playing_9a605016	e	Pressing the 's' key saves a screenshot to disk, so I can upload pictures of the game to websites like renpy.org.	../tutorial_playing.rpyc	62
+tutorial_playing_a9c70134	e	Finally, there's rollback, which lets you go back in time to previous screens, letting you re-read text.	../tutorial_playing.rpyc	64
+tutorial_playing_ffcaf528	e	Would you like to hear more about rollback?	../tutorial_playing.rpyc	65
+tutorial_rollback_40b09eaf	e	You can invoke a rollback by scrolling the mouse wheel up, or by pushing the page up key. That'll bring you back to the previous screen.	../tutorial_playing.rpyc	80
+tutorial_rollback_041be71b	e	While at a previous screen, you can roll forward by scrolling the mouse wheel down, or pushing the page down key.	../tutorial_playing.rpyc	82
+tutorial_rollback_1d0e55c3	e	Rolling forward through a menu will make the same choice you did last time. But unlike other engines, Ren'Py's rollback system allows you to make a different choice.	../tutorial_playing.rpyc	84
+tutorial_rollback_a4633f53	e	You can try it by rolling back through the last menu, and saying 'No'.	../tutorial_playing.rpyc	86
+tutorial_rollback_a30f8a06	e	Press page up, or scroll up the mouse wheel.	../tutorial_playing.rpyc	88
+tutorial_rollback_de0b6f5a	e	Well, are you going to try it?	../tutorial_playing.rpyc	92
+tutorial_rollback_6bbdedaa	e	Your loss.	../tutorial_playing.rpyc	94
+tutorial_rollback_dce979d4	e	Moving on.	../tutorial_playing.rpyc	96
+tutorial_rollback_done_54d6ee45	e	By allowing Ren'Py to take care of out-of-game issues like loading and saving, you can focus on making your game, while still giving users the experience they've come to expect.	../tutorial_playing.rpyc	102
+tutorial_sprite_d2ca6a0c	e	Ren'Py supports a sprite system, which allows many similar objects to be shown on the screen at once.	../tutorial_sprite.rpyc	63
+tutorial_sprite_40df8d5d	e	The background behind me consists of one hundred and seventy-five stars, being moved at several different speeds, to give a starflight effect.	../tutorial_sprite.rpyc	70
+tutorial_sprite_29c5e523	e	The OpenGL system should be able to animate this smoothly, but you might see a bit of stuttering if your computer is using software.	../tutorial_sprite.rpyc	72
+tutorial_sprite_90927173	e	You'll need to decide which older systems to support.	../tutorial_sprite.rpyc	74
+tutorial_sprite_9afa1448	e	The sprite manager requires you to write a python function to move the sprites around.	../tutorial_sprite.rpyc	80
+tutorial_sprite_2c9a79ad	e	In many cases, all you need is something moving around the screen - like cherry blossoms, or snow.	../tutorial_sprite.rpyc	84
+tutorial_sprite_595d03b3	e	That's what the snowblossom function gives you - a simple way to have things falling from the top of the screen.	../tutorial_sprite.rpyc	86
+tutorial_sprite_4f82c848	e	And that's it for sprites.	../tutorial_sprite.rpyc	91
+demo_nvlmode_a986703b	nvle	NVL-style games are games that cover the full screen with text, rather then placing it in a file at the bottom of the screen.	game/demo_nvlmode.rpy	17
+demo_nvlmode_37fd9ceb	nvle	Ren'Py ships with a file, nvl_mode.rpy, that implements NVL-style games. You're seeing an example of NVL-mode at work.	game/demo_nvlmode.rpy	19
+demo_nvlmode_66cbcf75	nvle	To use NVL-mode, you need to define Characters with a kind=nvl.	game/demo_nvlmode.rpy	23
+demo_nvlmode_ad2b8b67	nvle	You use 'nvl clear' to clear the screen when that becomes necessary.	game/demo_nvlmode.rpy	25
+demo_nvlmode_390a4eb1	nvle	The 'nvl show' and 'nvl hide' statements use transitions to show and hide the NVL window.	game/demo_nvlmode.rpy	30
+demo_nvlmode_74454519	nvle	The nvl_erase function removes a line from the screen.	game/demo_nvlmode.rpy	32
+demo_nvlmode_5e97d841	nvle	Like that.	game/demo_nvlmode.rpy	36
+demo_nvlmode_ea2d8a07	nvle	The nvl_mode also supports showing menus to the user, provided they are the last thing on the screen. Understand?	game/demo_nvlmode.rpy	43
+demo_nvlmode_0f2b7d59	nvle	Good!	game/demo_nvlmode.rpy	51
+demo_nvlmode_b64ad3b1	nvle	Well, it might help if you take a look at the demo code.	game/demo_nvlmode.rpy	59
+demo_nvlmode_edb031ab	eside	You can specify transitions that occur when going from NVL-mode to ADV-mode.	game/demo_nvlmode.rpy	63
+demo_nvlmode_d43b28d1	nvle	As well as when going from ADV-mode to NVL-mode.	game/demo_nvlmode.rpy	65
+demo_nvlmode_f056c7ad	nvle	Text tags like w work in NVL-mode.	game/demo_nvlmode.rpy	67
+demo_nvlmode_750cd9a1	extend	 As does the \"extend\" special character.	game/demo_nvlmode.rpy	69
+demo_nvlmode_146d840b	nvle	And that's it for NVL-mode.	game/demo_nvlmode.rpy	71
+		Player	game/demo_minigame.rpy	16
+		Click to Begin	game/demo_minigame.rpy	18
+demo_minigame_03fc91ef	e	You may want to mix Ren'Py with other forms of gameplay. There are many ways to do this.	game/demo_minigame.rpy	204
+demo_minigame_8c389a44	e	The first is with the UI functions, which can be used to create powerful button and menu based interfaces.	game/demo_minigame.rpy	206
+demo_minigame_0d5698fc	e	These are often enough for many simulation-style games.	game/demo_minigame.rpy	208
+demo_minigame_abc48e39	e	We also have two more ways in which Ren'Py can be extended. Both require experience with Python programming, and so aren't for the faint of heart.	game/demo_minigame.rpy	210
+demo_minigame_4d7b5701	e	Renpygame is a library that allows pygame games to be run inside Ren'Py.	game/demo_minigame.rpy	212
+demo_minigame_bb13a57e	e	When using renpygame, Ren'Py steps out of the way and gives you total control over the user's experience.	game/demo_minigame.rpy	214
+demo_minigame_4f4537ea	e	You can get renpygame from the Frameworks page of the Ren'Py website.	game/demo_minigame.rpy	216
+demo_minigame_b2baab12	e	If you want to integrate your code with Ren'Py, you can write a user-defined displayable.	game/demo_minigame.rpy	218
+demo_minigame_9d67e41d	e	User-defined displayables are somewhat more limited, but integrate better with the rest of Ren'Py.	game/demo_minigame.rpy	220
+demo_minigame_59b3fdfd	e	For example, one could support loading and saving while a user-defined displayable is shown.	game/demo_minigame.rpy	222
+demo_minigame_e02e509d	e	Now, why don't we play some pong?	game/demo_minigame.rpy	224
+demo_minigame_pong_ce00ff63	e	I win!	game/demo_minigame.rpy	246
+demo_minigame_pong_68c82e98	e	You won! Congratulations.	game/demo_minigame.rpy	250
+demo_minigame_pong_dde7e31a	e	Would you like to play again?	game/demo_minigame.rpy	255
+		Sure.	game/demo_minigame.rpy	255
+		No thanks.	game/demo_minigame.rpy	255
+demo_minigame_pong_cd12159e	e	Remember to be careful about putting minigames in a visual novel, since not every visual novel player wants to be good at arcade games.	game/demo_minigame.rpy	264
+		Lucy	game/tutorial_quickstart.rpy	5
+tutorial_dialogue_f6d3ddd3	e	Probably the best way to learn Ren'Py is to see it in action. In this tutorial, I'll be showing you some of the things Ren'Py can do, and also showing you how to do them.	../tutorial_quickstart.rpyc	20
+tutorial_dialogue_49c65906	e	Code examples will show up in a window like the one above. You'll need to click outside of the example window in order to advance the tutorial.	../tutorial_quickstart.rpyc	25
+tutorial_dialogue_5c2cb6f9	e	When an example is bigger than the screen, you can scroll around in it using the mouse wheel or by simply dragging the mouse.	../tutorial_quickstart.rpyc	27
+tutorial_dialogue_3528a1fe	e	To create a new project, you can click New Project in the Ren'Py launcher.	../tutorial_quickstart.rpyc	32
+tutorial_dialogue_3ef9231c	e	If it's your first time making a Ren'Py game, you'll be asked to pick a directory to store your projects in.	../tutorial_quickstart.rpyc	34
+tutorial_dialogue_15734bf9	e	You'll then be asked for the name of the project, and also to choose a theme for the interface.	../tutorial_quickstart.rpyc	36
+tutorial_dialogue_46edb91d	e	Once that's done, Ren'Py will automatically create a directory and fill it with the files needed to make a project.	../tutorial_quickstart.rpyc	38
+tutorial_dialogue_66d639af	e	If you have Java installed, you'll be able to click Edit Script to open your project's script.	../tutorial_quickstart.rpyc	40
+tutorial_dialogue_f0d66410	e	Let's see the simplest possible Ren'Py game.	../tutorial_quickstart.rpyc	42
+tutorial_dialogue_3e6b0068		Wow, It's really really dark in here.	../tutorial_quickstart.rpyc	48
+tutorial_dialogue_5072a404	"Lucy"	Better watch out. You don't want to be eaten by a Grue.	../tutorial_quickstart.rpyc	50
+tutorial_dialogue_871db44f	e	I'll show you the code for that example.	../tutorial_quickstart.rpyc	59
+tutorial_dialogue_6943c36d	e	This code demonstrates two kinds of Ren'Py statements, labels and say statements.	../tutorial_quickstart.rpyc	61
+tutorial_dialogue_bc7ec147	e	The first line is a label statement. The label statement is used to give a name to a place in the program.	../tutorial_quickstart.rpyc	63
+tutorial_dialogue_b20db833	e	In this case, we're naming a place \"start\". The start label is special, as it marks the place a game begins running.	../tutorial_quickstart.rpyc	65
+tutorial_dialogue_b0afbe96	e	The next line is a simple say statement. It consists of a string beginning with a double-quote, and ending at the next double-quote.	../tutorial_quickstart.rpyc	67
+tutorial_dialogue_628c9e4c	e	Special characters in strings can be escaped with a backslash. To include \" in a string, we have to write \\\".	../tutorial_quickstart.rpyc	69
+tutorial_dialogue_3e6b0068_1		Wow, It's really really dark in here.	../tutorial_quickstart.rpyc	74
+tutorial_dialogue_d7f0b5b7	e	When Ren'Py sees a single string on a line by itself, it uses the narrator to say that string. So a single string can be used to express a character's thoughts.	../tutorial_quickstart.rpyc	82
+tutorial_dialogue_5072a404_1	"Lucy"	Better watch out. You don't want to be eaten by a Grue.	../tutorial_quickstart.rpyc	87
+tutorial_dialogue_9dd2d543	e	When we have two strings separated by a space, the first is used as the character's name, and the second is what the character is saying.	../tutorial_quickstart.rpyc	95
+tutorial_dialogue_64ffe685	e	This two-argument form of the say statement is used for dialogue, where a character is speaking out loud.	../tutorial_quickstart.rpyc	97
+tutorial_dialogue_97a33275	e	If you'd like, you can run this game yourself by erasing everything in your project's script.rpy file, and replacing it with the code in the box above.	../tutorial_quickstart.rpyc	99
+tutorial_dialogue_c5e70d7e	e	Be sure to preserve the spacing before lines. That's known as indentation, and it's used to help Ren'Py group lines of script into blocks.	../tutorial_quickstart.rpyc	101
+tutorial_dialogue_90719f73	e	Using a string for a character's name is inconvenient, for two reasons.	../tutorial_quickstart.rpyc	106
+tutorial_dialogue_910f286a	e	The first is that's it's a bit verbose. While typing \"Lucy\" isn't so bad, imagine if you had to type \"Eileen Richardson\" thousands of times.	../tutorial_quickstart.rpyc	108
+tutorial_dialogue_9c9d59c2	e	The second is that it doesn't leave any place to put styling, which can change the look of a character.	../tutorial_quickstart.rpyc	110
+tutorial_dialogue_2a2d1e51	e	To solve these problems, Ren'Py lets you define Characters.	../tutorial_quickstart.rpyc	112
+tutorial_dialogue_16e8c5fd	e	Here's an example Character definition. It begins with the word \"define\". That tells Ren'Py that we are defining something.	../tutorial_quickstart.rpyc	116
+tutorial_dialogue_34fe5aa0	e	Define is followed by a short name for the character, like \"l\". We'll be able to use that short name when writing dialogue.	../tutorial_quickstart.rpyc	118
+tutorial_dialogue_67f90201	e	This is followed by an equals sign, and the thing that we're defining. In this case, it's a Character.	../tutorial_quickstart.rpyc	120
+tutorial_dialogue_4e454a89	e	On the first line, the character's name is given to be \"Lucy\", and her name will be drawn a reddish color.	../tutorial_quickstart.rpyc	122
+tutorial_dialogue_db11f026	e	These short names are case-sensitive. Capital L is a different name from lower-case l, so you'll need to be careful about that.	../tutorial_quickstart.rpyc	124
+tutorial_dialogue_1d161320	e	Now that we have a character defined, we can use it to say dialogue.	../tutorial_quickstart.rpyc	128
+tutorial_dialogue_3710169c	l	Why are you trying to put words into my mouth? And who are you calling \"it\"?	../tutorial_quickstart.rpyc	134
+tutorial_dialogue_6d463776	l	What's more, what are you going to do about the Grue problem? Are you just going to leave me here?	../tutorial_quickstart.rpyc	136
+tutorial_dialogue_023bcd31	e	Here's the full game, including the two new lines of dialogue, both of which use the Character we defined to say dialogue.	../tutorial_quickstart.rpyc	145
+tutorial_dialogue_48bb9547	e	The one-argument form of the say statement is unchanged, but in the two-argument form, instead of the first string we can use a short name.	../tutorial_quickstart.rpyc	147
+tutorial_dialogue_56a9936f	e	When this say statement is run, Ren'Py will look up the short name, which is really a Python variable. It will then use the associated Character to show the dialogue.	../tutorial_quickstart.rpyc	149
+tutorial_dialogue_d5984a21	e	The Character object controls who is speaking, the color of their name, and many other properties of the dialogue.	../tutorial_quickstart.rpyc	151
+tutorial_dialogue_a5bcac8b	e	Since the bulk of a visual novel is dialogue, we've tried to make it as easy to write as possible.	../tutorial_quickstart.rpyc	155
+tutorial_dialogue_6b9a42d0	e	Hopefully, by allowing the use of short names for characters, we've succeeded.	../tutorial_quickstart.rpyc	157
+tutorial_images_e09ac970	e	A visual novel isn't much without images. So let's add some images to our little game.	../tutorial_quickstart.rpyc	163
+tutorial_images_a664a8bc	e	Before we can show images, we must first put the image files into the game directory.	../tutorial_quickstart.rpyc	165
+tutorial_images_1d6236ee	e	The easiest way to open the game directory is to click the Game Directory button in the Ren'Py launcher.	../tutorial_quickstart.rpyc	167
+tutorial_images_e41986f0	e	All of the image files we'll be using here are in the game directory, under the tutorial directory, under the Ren'Py directory.	../tutorial_quickstart.rpyc	169
+tutorial_images_0b9f7257	e	Here are some sample image definitions. They should be placed at the start of the file, without any indentation.	../tutorial_quickstart.rpyc	173
+tutorial_images_5d67054c	e	The image statement begins with the keyword \"image\", which is followed by an image name, a space-separated list of words.	../tutorial_quickstart.rpyc	175
+tutorial_images_4c9a51ec	e	The first word in the image name is the image tag. For the first image the tag is \"bg\", and for the others, it's \"lucy\".	../tutorial_quickstart.rpyc	177
+tutorial_images_bda71aa3	e	This is followed by an equals sign, and a string giving an image name.	../tutorial_quickstart.rpyc	179
+tutorial_images_6d88aaa3	e	A string giving an image name is only one of the dozens of kinds of displayable that Ren'Py supports.	../tutorial_quickstart.rpyc	181
+tutorial_images_76b954de	e	Let's see what those look like in the game.	../tutorial_quickstart.rpyc	185
+tutorial_images_f04e72ea	l	Now that the lights are on, we don't have to worry about Grues anymore.	../tutorial_quickstart.rpyc	192
+tutorial_images_d77ffa1c	l	But what's the deal with me being in a cave? Eileen gets to be out in the sun, and I'm stuck here!	../tutorial_quickstart.rpyc	196
+tutorial_images_6c0c938b	e	Here's the script for that scene. Notice how it includes two new statements, the scene and show statement.	../tutorial_quickstart.rpyc	205
+tutorial_images_1a4660b9	e	The scene statement clears the screen, and then adds a background image.	../tutorial_quickstart.rpyc	207
+tutorial_images_672c8cb8	e	The show statement adds a background image on top of all the other images on the screen.	../tutorial_quickstart.rpyc	209
+tutorial_images_2fc7baee	e	If there was already an image with the same tag, the new image is used to replace the old one.	../tutorial_quickstart.rpyc	211
+tutorial_images_802825f2	e	Changes to the list of shown images take place instantly, so in the example, the user won't see the background by itself.	../tutorial_quickstart.rpyc	213
+tutorial_images_b246dfdd	e	The second show statement has an at clause, which gives a location on the screen. Common locations are left, right, and center, but you can define many more.	../tutorial_quickstart.rpyc	215
+tutorial_images_bc4ae0c7	e	In this example, we show an image named logo base, and we show it at a user-defined position, logopos.	../tutorial_quickstart.rpyc	223
+tutorial_images_9defda43	e	We also specify that it should be shown behind another image, in this case eileen. That's me.	../tutorial_quickstart.rpyc	225
+tutorial_images_73d331f7	e	Finally, there's the hide statement, which hides the image with the given tag.	../tutorial_quickstart.rpyc	233
+tutorial_images_f34f62d5	e	Since the show statement replaces an image, and the scene statement clears the scene, it's pretty rare to hide an image.	../tutorial_quickstart.rpyc	235
+tutorial_images_e06fa53a	e	The main use is for when a character or prop leaves before the scene is over.	../tutorial_quickstart.rpyc	237
+tutorial_transitions_9b8c714c	e	It can be somewhat jarring for the game to jump from place to place.	../tutorial_quickstart.rpyc	246
+tutorial_transitions_3e290ea8	e	To help take some of edge off a change in scene, Ren'Py supports the use of transitions. Let's try that scene change again, but this time we'll use transitions.	../tutorial_quickstart.rpyc	253
+tutorial_transitions_9c0a86c4	e	That's much smoother. Here's some example code showing how we include transitions in our game.	../tutorial_quickstart.rpyc	268
+tutorial_transitions_3e490d40	e	It uses the with statement. The with statement causes the scene to transition from the last things shown to the things currently being shown.	../tutorial_quickstart.rpyc	270
+tutorial_transitions_a43847df	e	It takes a transition as an argument. In this case, we're using the Dissolve transition. This transition takes as an argument the amount of time the dissolve should take.	../tutorial_quickstart.rpyc	272
+tutorial_transitions_6fcee414	e	In this case, each transition takes half a second.	../tutorial_quickstart.rpyc	274
+tutorial_transitions_033042cc	e	We can define a short name for a transition, using the define statement. Here, we're defining slowdissolve to be a dissolve that takes a whole second.	../tutorial_quickstart.rpyc	278
+tutorial_transitions_0ba82f00	e	Once a transition has been given a short name, we can use it in our game.	../tutorial_quickstart.rpyc	292
+tutorial_transitions_51ff9600	e	Ren'Py defines some transitions for you, like dissolve, fade, and move. For more complex or customized transitions, you'll have to define your own.	../tutorial_quickstart.rpyc	296
+tutorial_transitions_a7905e16	e	If you're interested, check out the Transitions Gallery section of the tutorial.	../tutorial_quickstart.rpyc	298
+tutorial_music_8b92efb7	e	Another important part of a visual novel or simulation game is the soundtrack.	../tutorial_quickstart.rpyc	304
+tutorial_music_53910317	e	Ren'Py breaks sound up into channels. The channel a sound is played on determines if the sound loops, and if it is saved and restored with the game.	../tutorial_quickstart.rpyc	306
+tutorial_music_a1e37712	e	When a sound is played on the music channel, it is looped, and it is saved when the game is saved.	../tutorial_quickstart.rpyc	308
+tutorial_music_d9086d22	e	When the channel named sound is used, the sound is played once and then stopped. It isn't saved.	../tutorial_quickstart.rpyc	310
+tutorial_music_45cd30df	e	The sounds themselves are stored in audio files. Ren'Py supports the Ogg Vorbis, mp3, mp2, and wav file formats.	../tutorial_quickstart.rpyc	312
+tutorial_music_a776b6ad	e	Let's check out some of the commands that can effect the music channel.	../tutorial_quickstart.rpyc	314
+tutorial_music_8b606a55	e	The play music command replaces the currently playing music, and replaces it with the named filename.	../tutorial_quickstart.rpyc	324
+tutorial_music_18650fe7	e	If you specify the currently-playing song, it will restart it.	../tutorial_quickstart.rpyc	326
+tutorial_music_413d91fc	e	If the optional fadeout clause is given, it will fade out the currently playing music before starting the new music.	../tutorial_quickstart.rpyc	328
+tutorial_music_a282a0e3	e	The queue statement also adds music to the named channel, but it waits until the currently-playing song is finished before playing the new music.	../tutorial_quickstart.rpyc	330
+tutorial_music_01ca6bad	e	The third statement is the stop statement. It stops the music playing on a channel. It too takes the fadeout clause.	../tutorial_quickstart.rpyc	339
+tutorial_music_384937da	e	Unlike the music channel, playing a sound on the sound channel causes it to play only once.	../tutorial_quickstart.rpyc	348
+tutorial_music_dc707e58	e	You can queue up multiple sounds on the sound channel, but they will only play one at a time.	../tutorial_quickstart.rpyc	359
+tutorial_music_abcc2214	e	Ren'Py has separate mixers for sound, music, and voices, so the player can adjust them as he likes.	../tutorial_quickstart.rpyc	366
+tutorial_menus_0426904b	e	Many visual novels require the player to make choices from in-game menus. These choices can add some challenge to the game, or adjust it to the player's preferences.	../tutorial_quickstart.rpyc	372
+tutorial_menus_9c3b9154	e	Do you think your game will use menus?	../tutorial_quickstart.rpyc	374
+		Yes, I do.	game/tutorial_quickstart.rpy	377
+		No, I don't.	game/tutorial_quickstart.rpy	377
+choice1_yes_f6d95df8	e	While creating a multi-path visual novel can be a bit more work, it can yield a unique experience.	../tutorial_quickstart.rpyc	388
+choice1_no_72958b50	e	Games without menus are called kinetic novels, and there are dozens of them available to play.	../tutorial_quickstart.rpyc	396
+choice1_done_acba9504	e	Here, you can see the code for that menu. If you scroll down, you can see the code we run after the menu.	../tutorial_quickstart.rpyc	408
+choice1_done_d18afbdf	e	Menus are introduced by the menu statement. The menu statement takes an indented block, in which each line must contain a choice in quotes.	../tutorial_quickstart.rpyc	410
+choice1_done_2865a192	e	The choices must end with a colon, as each choice has its own block of Ren'Py code, that is run when that choice is selected.	../tutorial_quickstart.rpyc	412
+choice1_done_59cac95d	e	Here, each block jumps to a label. While you could put small amounts of Ren'Py code inside a menu label, it's probably good practice to usually jump to a bigger block of code.	../tutorial_quickstart.rpyc	414
+choice1_done_2851a313	e	Scrolling down past the menu, you can see the labels that the menu jumps to. There are three labels here, named choice1_yes, choice1_no, and choice1_done.	../tutorial_quickstart.rpyc	416
+choice1_done_ff761b03	e	When the first menu choice is picked, we jump to the choice1_yes, which runs two lines of script before jumping to choice1_done.	../tutorial_quickstart.rpyc	418
+choice1_done_664fe702	e	Similarly, picking the second choice jumps us to choice1_no, which also runs two lines of script.	../tutorial_quickstart.rpyc	420
+choice1_done_31d12b1e	e	The lines beginning with the dollar sign are lines of python code, which are used to set a flag based on the user's choice.	../tutorial_quickstart.rpyc	422
+choice1_done_88398d3e	e	The flag is named menu_flag, and it's set to True or False based on the user's choice. The if statement can be used to test a flag, so the game can remember the user's choices.	../tutorial_quickstart.rpyc	424
+choice1_done_2828dbfc	e	For example, I remember that you plan to use menus in your game.	../tutorial_quickstart.rpyc	432
+choice1_done_503786e4	e	For example, I remember that you're planning to make a kinetic novel, without menus.	../tutorial_quickstart.rpyc	436
+choice1_done_819e234a	e	Here's an example that shows how we can test a flag, and do different things if it is true or not.	../tutorial_quickstart.rpyc	441
+choice1_done_47fa2268	e	Although we won't demonstrate it here, Ren'Py supports making decisions based on a combinations of points, flags, and other factors.	../tutorial_quickstart.rpyc	445
+choice1_done_826a600b	e	One of Ren'Py's big advantages is the flexibility using a scripting language like Python provides us. It lets us easily scale from kinetic novels to complex simulation games.	../tutorial_quickstart.rpyc	447
+choice1_done_c2efd260	e	We look forward to seeing what you make with it.	../tutorial_quickstart.rpyc	449
+		User Experience	game/script.rpy	9
+		Writing Dialogue	game/script.rpy	9
+		Adding Images	game/script.rpy	9
+		Music and Sound Effects	game/script.rpy	9
+		In-Game Menus and Python	game/script.rpy	9
+		Screen Positions	game/script.rpy	9
+		Animation and Transformation	game/script.rpy	9
+		Video Playback	game/script.rpy	9
+		Transition Gallery	game/script.rpy	9
+		Image Operations	game/script.rpy	9
+		User Interaction	game/script.rpy	9
+		Fonts and Text Tags	game/script.rpy	9
+		Character Objects	game/script.rpy	9
+		Layers & Advanced Show	game/script.rpy	9
+		NVL Mode	game/script.rpy	9
+		Dynamic Displayables	game/script.rpy	9
+		Minigames	game/script.rpy	9
+		Persistent Data	game/script.rpy	9
+		Transform	game/script.rpy	9
+		Sprites	game/script.rpy	9
+		That's enough for now.	game/script.rpy	55
+start_0e6a5bb4	e	Hi! My name is Eileen, and I'd like to welcome you to the Ren'Py tutorial.	game/script.rpy	76
+start_d3abb53c	e	In this tutorial, we'll teach you the basics of Ren'Py, so you can make games of your own. We'll also demonstrate many features, so you can see what Ren'Py is capable of.	game/script.rpy	80
+		What would you like to see?	game/script.rpy	91
+		Is there anything else you'd like to see?	game/script.rpy	93
+end_b2482727	e	Thank you for viewing this tutorial.	game/script.rpy	111
+end_38362e36	e	If you'd like to see a full Ren'Py game, select \"The Question\" in the launcher.	game/script.rpy	113
+end_894a9e66	e	You can download new versions of Ren'Py from http://www.renpy.org/. For help and discussion, check out the Lemma Soft Forums.	game/script.rpy	115
+end_a898b369	e	We'd like to thank Piroshki for contributing my sprites, Mugenjohncel for Lucy and the band, and Jake for the magic circle.	game/script.rpy	117
+end_762dc07a	e	The background music is \"Sunflower Slow Drag\", by Scott Joplin and Scott Hayden, performed by the United States Marine Band. The concert music is by Alessio.	game/script.rpy	119
+end_57c21073	e	We look forward to seeing what you can make with Ren'Py. Have fun!	game/script.rpy	123
+demo_transform_f10e08f5	e	The Transform function allows you to rotate, zoom, move, and adjust the alpha of a displayable.	game/demo_transform.rpy	156
+demo_transform_295804e0	e	It does this under the control of a Python function, making it incredibly flexible at the cost of some complexity.	game/demo_transform.rpy	158
+demo_transform_1afd3e7b	e	Here's a simple example, showing how we can change an image as it moves around the screen.	game/demo_transform.rpy	165
+demo_transform_a5427276	e	A nice thing about Transform is that it's \"one price\".	game/demo_transform.rpy	167
+demo_transform_108aec8f	e	If you use it to do a rotation, you can zoom or adjust alpha at no additional cost.	game/demo_transform.rpy	169
+demo_transform_55f784e4	e	As the python functions get more complicated, more advanced behavior is possible.	game/demo_transform.rpy	198
+demo_transform_43798bbe	e	This can include coordinating more than one Transform.	game/demo_transform.rpy	200
+		A Working Button	game/demo_transform.rpy	211
+demo_transform_3f4f14bb	e	Finally, transforms can be applied to buttons, and work even while the button is zoomed.	game/demo_transform.rpy	213
+demo_transform_a439ffaa	e	With a little Python code, transforms let you do a lot of things.	game/demo_transform.rpy	218
+demo_persistent_abef5d83		Ren'Py supports per-game and multi-game persistent data.	game/demo_persistent.rpy	6
+demo_persistent_539955e4		Persistent data can store flags and other per-game information that should be shared between plays of a single game.	game/demo_persistent.rpy	8
+demo_persistent_c8164f03		For example, I can tell you that you've see this line [plays] time(s) since you cleared the per-game persistent data.	game/demo_persistent.rpy	19
+demo_persistent_54bc6648		Multipersistent data is shared between games, which lets one game unlock features in a second.	game/demo_persistent.rpy	21
+demo_persistent_4ff5d824		A sequel might play differently if the player has beaten the first game.	game/demo_persistent.rpy	23
+demo_persistent_634f6d6d		According to the multipersistent data, you've seen this line [plays] times total.	game/demo_persistent.rpy	35
diff --git a/tutorial/dialogue.txt b/tutorial/dialogue.txt
new file mode 100644
index 0000000..5074032
--- /dev/null
+++ b/tutorial/dialogue.txt
@@ -0,0 +1,508 @@
+The Character object is used to declare characters, and it can also be used to customize the way in which a character speaks.
+By supplying it with the appropriate arguments, we can really change around the feel of the game.
+In this section, we'll demonstrate some of what can be accomplished by customizing character objects.
+By supplying what_prefix and what_suffix arguments to a Character object, we can automatically add things before each line of text.
+This is a lot easier than having to put those quotes in by hand.
+We can also use who_prefix and who_suffix to add text to the name of the speaker.
+We can also supply arguments to the Character object that customize the look of the character name, the text that is being said, and the window itself.
+These can really change the look of the game.
+A more practical use of that is in conjunction with show_side_image, which lets us position an image next to the text.
+There's also show_two_window, which puts the character's name in its own window.
+Finally, we demonstrate a click to continue indicator. In this example, it's nestled in with the text.
+A click to continue image can also be placed at a fixed location on the screen.
+There's a lot more you can do with Character, as it lets you set style properties on all of the displayed text.
+Finally, let me point out a couple of special characters we pre-define.
+The "centered" character shows text at the center of the screen, without a window.
+It's just a highly customized normal character, that's useful for dates and titles.
+The "extend" character is very special.
+It lets you
+ extend the previous dialogue
+ with additional text.
+That lets you have things happen in the middle of text. If you didn't notice, I was changing my expression.
+Hopefully, these characters, along with the ones you define, will lead to a very expressive game.
+Ren'Py gives you quite a bit of control over how text appears.
+Text tags let us control the appearance of text that is shown to the user.
+Text tags can make text {b}bold{/b}, {i}italic{/i}, {s}struckthrough{/s}, or {u}underlined{/u}.
+They can make the font size {size=+12}bigger{/size} or {size=-8}smaller{/size}.
+They let you pause{w} the display of the text, optionally with{p}line breaks.
+They let you include images inside text{image=exclamation.png} Neat{image=exclamation.png}
+We can pause the text for a short time, and have it auto-advance.{w=1} Just like that.
+We can even have the text auto-advance,{nw}
+ when we reach the end of a block of text, in slow text mode.
+They can change the {color=#f00}color{/color} {color=#ff0}of{/color} {color=#0f0}the{/color} {color=#0ff}text{/color}.
+The kerning tag lets you adjust the spacing between characters.
+{k=.5}The spacing between characters can be increased.{/k}
+{k=-.5}The spacing between characters can be decreased.{/k}
+You are able to write ruby text, which can help clarify how to pronounce words, like {rb}Ren'Py{/rb}{rt}ren-pie{/rt}.
+{a=define_hyperlink}Hyperlinks{/a} let buttons be defined using text tags.
+The space and vspace tags add {space=30} horizontal and {vspace=20}vertical space, respectively.
+You can define your own text tags, {=pink}that use a style you define.{/=pink}
+If you find yourself using text tags on every line, you should probably look at style properties instead.
+Used with care, text tags can enhance {b}your{/b} game.
+{u}Used{/u} with {i}abandon,{/i} they {b}can{/b} make {b}your{/b} game {color=#333}hard{/color} {color=#888}to{/color} {color=#ccc}read{/color}.
+With great power comes great responsibility, after all.
+And we want to give you all the power you need.
+There are a couple of text adjustments that don't correspond to text tags.
+The outlines setting lets you put outlines around the text.
+You can have more than one outline, and each has its own color and offset.
+Here, we have two outlines around the white text.
+The bottom one is a translucent black that's offset a little, while the top one is green.
+By hiding the window and adjusting the layout method, we are able to create reasonable subtitles.
+This might be an interesting look for a game.
+For even more control, Ren'Py supports SFonts, image files containing font information.
+SFonts let you use fonts you otherwise couldn't, and apply special effects to fonts using your favorite image editor.
+Well, that's it for fonts and text tags.
+A hyperlink is a button that is defined inside text, using text tags. They're ideal for including definitions of words used in the script, but they shouldn't be used in place of menus.
+Ren'Py ships with a large number of built-in transitions, and also includes classes that let you define your own.
+What kind of transitions would you like demonstrated?
+Okay, I can tell you about simple transitions. We call them simple because they don't take much in the way of configuration.
+But don't let that get you down, since they're the transitions you'll probably use the most in a game.
+The 'dissolve' transition is probably the most useful, blending one scene into another.
+The 'Dissolve' function lets you create your own dissolves, taking a different amount of time.
+The 'fade' transition fades to black, and then fades back in to the new scene.
+If you're going to stay at a black screen, you'll probably want to use 'dissolve' rather than 'fade'.
+You can use 'Fade' to define your own fades. By changing the timing and the color faded to, you can use this for special effects, like flashbulbs.
+The 'pixellate' transition pixellates out the old scene, switches to the new scene, and then unpixellates that.
+It's probably not appropriate for most games, but we think it's kind of neat.
+You can use 'Pixellate' to change the details of the pixellation.
+Motions can also be used as transitions.
+...
+......
+Hey! Pay attention.
+I was about to demonstrate 'vpunch'... well, I guess I just did.
+We can also shake the screen horizontally, with 'hpunch'. These were defined using the 'Move' function.
+There's also the 'move' transition, which is confusingly enough defined using the 'MoveTransition' function.
+The 'move' transition finds images that have changed placement, and slides them to their new place. It's an easy way to get motion in your game.
+Finally, there's 'Pause', which lets you define a transition that just waits for a given amount of time.
+Why would you want to do that?
+It's because clicking during a sequence of transitions will skip all of the remaining transitions.
+Try clicking during the following transitions:
+Having 'Pause' makes it easy to implement skippable cut-scenes in terms of transitions.
+Anyway, that's it for the simple transitions.
+Perhaps the most flexible kind of transition is the ImageDissolve, which lets you use an image to control a dissolve.
+This lets us specify very complex transitions, fairly simply. Let's try some, and then I'll show you how they work.
+There are two ImageDissolve transitions built into Ren'Py.
+The 'blinds' transition opens and closes what looks like vertical blinds.
+The 'squares' transition uses these squares to show things.
+I'm not sure why anyone would want to use it, but it was used in some translated games, so we added it.
+The most interesting transitions aren't in the standard library.
+These ones require an image the size of the screen, and so we couldn't include them as the size of the screen can change from game to game.
+You can click the button above to see how they are defined in the demo script.
+We can hide things with a 'circleirisin'...
+... and show them again with a 'circleirisout'.
+The 'circlewipe' transitions changes screens using a circular wipe effect.
+The 'dream' transition does this weird wavy dissolve, and does it relatively slowly.
+The 'teleport' transition reveals the new scene one line at a time.
+This is the background picture used with the circleirisout transition.
+When we use an ImageDissolve, the white will dissolve in first, followed by progressively darker colors. Let's try it.
+If we give ImageDissolve the 'reverse' parameter, black areas will dissolve in first.
+This lets circleirisin and circleirisout use the same image.
+The teleport transition uses a different image, one that dissolves things in one line at a time.
+A dissolve only seems to affect parts of the scene that have changed...
+... which is how we apply the teleport effect to a single character.
+For more examples of ImageDissolve, check out the {i}Utsukushii Effects{/i} demo.
+It shows how a clever game-maker can use ImageDissolve to create all sorts of effects.
+The CropMove transition class provides a wide range of transition effects. It's not used very much in practice, though.
+I'll stand offscreen, so you can see some of its modes. I'll read out the mode name after each transition.
+We first have wiperight...
+...followed by wipeleft... 
+...wipeup...
+...and wipedown.
+Next, the slides.
+Slideright...
+...slideleft...
+...slideup...
+and slidedown.
+While the slide transitions slide in the new scene, the slideaways slide out the old scene.
+Slideawayright...
+...slideawayleft...
+...slideawayup...
+and slideawaydown.
+We also have a couple of transitions that use a rectangular iris.
+There's irisout...
+... and irisin.
+It's enough to make you feel a bit dizzy.
+The PushMove transitions use the new scene to push the old one out. Let's take a look.
+There's pushright...
+...pushleft...
+...pushdown...
+... and pushup. And that's it the for the PushMove-based transitions.
+The most common MoveTransition is move, which slides around images that have changed position on the screen.
+Just like that.
+There are also the moveout and movein transitions.
+The moveout transitions (moveoutleft, moveoutright, moveouttop, and moveoutbottom) slide hidden images off the appropriate side of the screen.
+The movein transitions (moveinleft, moveinright, moveintop, and moveinbottom) slide in new images.
+Let's see them all in action.
+That's it for the moveins and moveouts.
+Finally, there are the zoomin and zoomout transtions, which show and hide things using a zoom.
+And that's all there is.
+The AlphaDissolve transition lets you use one displayable to combine two others. For example...
+The AlphaDissolve displayable takes a control displayable, usually an ATL transform.
+To be useful, the control displayable should be partially transparent.
+During an AlphaDissolve, the old screen is used to fill the transparent areas of the image, while the new screen fills the opaque areas.
+For our spotlight example, the old screen is this all-black image.
+The new screen is me just standing here.
+By combining them using AlphaDissolve, we can build a complicated effect out of simpler parts.
+Ren'Py supports playing movies. There are two ways of doing this.
+The first way allows you to show a movie as an image, along with every other image that's displayed on the screen.
+To do this, we first have to define an image to be a Movie displayable. Movie displayables require a size argument, and also use properties to position themselves on the screen.
+Then, we can show the movie displayable, which starts the movie playing.
+When we no longer want to play the movie, we can hide it.
+The other way to show a movie is with the renpy.movie_cutscene python function. This shows the movie fullscreen, either until it ends or until the user clicks.
+And that's all there is when it comes to movie playback in Ren'Py.
+In this tutorial, I'll teach you how Ren'Py positions things on the screen. But before that, let's learn a little bit about how Python handles numbers.
+There are two main kinds of numbers in Python: integers and floating point numbers. An integer consists entirely of digits, while a floating point number has a decimal point.
+For example, 100 is an integer, while 0.5 is a floating point number, or float for short. In this system, there are two zeros: 0 is an integer, and 0.0 is a float.
+Ren'Py uses integers to represent absolute coordinates, and floats to represent fractions of an area with known size.
+When we're positioning something, the area is usually the entire screen.
+Let me get out of the way, and I'll show you where some positions are.
+The origin is the upper-left corner of the screen. That's where the x position (xpos) and the y position (ypos) are both zero.
+When we increase xpos, we move to the right. So here's an xpos of .5, meaning half the width across the screen.
+Increasing xpos to 1.0 moves us to the right-hand border of the screen.
+We can also use an absolute xpos, which is given in an absolute number of pixels from the left side of the screen. For example, since this window is 800 pixels across, using an xpos of 400 will return the target to the center of the top row.
+The y-axis position, or ypos works the same way. Right now, we have a ypos of 0.0.
+Here's a ypos of 0.5.
+A ypos of 1.0 specifies a position at the bottom of the screen. If you look carefully, you can see the position indicator spinning below the text window.
+Like xpos, ypos can also be an integer. In this case, ypos would give the total number of pixels from the top of the screen.
+Can you guess where this position is, relative to the screen?
+Sorry, that's wrong. The xpos is .75, and the ypos is .25.
+In other words, it's 75%% of the way from the left side, and 25%% of the way from the top.
+Good job! You got that position right.
+Sorry, that's wrong. The xpos is .75, and the ypos is .25.
+In other words, it's 75%% of the way from the left side, and 25%% of the way from the top.
+The second position we care about is the anchor. The anchor is a spot on the thing being positioned.
+For example, here we have an xanchor of 0.0 and a yanchor of 0.0. It's in the upper-left corner of the logo image.
+When we increase the xanchor to 1.0, the anchor moves to the right corner of the image.
+Similarly, when both xanchor and yanchor are 1.0, the anchor is the bottom-right corner.
+To place an image on the screen, we need both the position and the anchor.
+We then line them up, so that both the position and anchor are at the same point on the screen.
+When we place both in the upper-left corner, the image moves to the upper-left corner of the screen.
+With the right combination of position and anchor, any place on the screen can be specified, without even knowing the size of the image.
+It's often useful to set xpos and xanchor to the same value. We call that xalign, and it gives a fractional position on the screen.
+For example, when we set xalign to 0.0, things are aligned to the left side of the screen.
+When we set it to 1.0, then we're aligned to the right side of the screen.
+And when we set it to 0.5, we're back to the center of the screen.
+Setting yalign is similar, except along the y-axis.
+Remember that xalign is just setting xpos and xanchor to the same value, and yalign is just setting ypos and yanchor to the same value.
+Once you understand positions, you can use transformations to move things around the Ren'Py screen.
+While showing static images is often enough for most games, occasionally we'll want to change images, or move them around the screen.
+We call this a Transform, and it's what ATL, Ren'Py's Animation and Transformation Language, is for.
+But first, let's have... a Gratuitous Rock Concert!
+That was a lot of work, and before you can do that, we'll need to start with the basics of using ATL.
+There are currently three places where ATL can be used in Ren'Py.
+The first place ATL can be used is as part of an image statement. Instead of a displayable, an image may be defined as a block of ATL code.
+When used in this way, we have to be sure that ATL includes one or more displayables to actually show.
+The second way is through the use of the transform statement. This assigns the ATL block to a python variable, allowing it to be used in at clauses and inside other transforms.
+Finally, an ATL block can be used as part of a show statement, instead of the at clause.
+The key to ATL is what we call composeability. ATL is made up of relatively simple commands, which can be combined together to create complicated transforms.
+Before I explain how ATL works, let me explain what animation and transformation are.
+Animation is when the displayable being shown changes. For example, right now I am changing my expression.
+Transformation involves moving or distorting an image. This includes placing it on the screen, zooming it in and out, rotating it, and changing its opacity.
+To introduce ATL, let's start by looking at at a simple animation. Here's one that consists of five lines of ATL code, contained within an image statement.
+In ATL, to change a displayable, simply mention it on a line of ATL code. Here, we're switching back and forth between two images.
+Since we're defining an image, the first line of ATL has to name a displayable. Otherwise, there would be nothing to show.
+The second and fourth lines are pause statements, which cause ATL to wait half of a second each before continuing. That's how we give the delay between images.
+The final line is a repeat statement. This causes the current block of ATL to be restarted. You can only have one repeat statement per block.
+If we were to write repeat 2 instead, the animation would loop twice, then stop.
+Omitting the repeat statement means that the animation stops once we reach the end of the block of ATL code.
+By default, displayables are replaced instantaneously. We can also use a with clause to give a transition between displayables.
+Now, let's move on to see how we can use ATL to transform an image. We'll start off by seeing what we can do to position images on the screen.
+Perhaps the simplest thing we can do is to position the images on the screen. This can be done by simply giving the names of the transform properties, each followed by the value.
+With a few more statements, we can move things around on the screen.
+This code starts the image off at the top-right of the screen, and waits a second.
+It then moves it to the left side, waits another second, and repeats.
+The pause and repeat statements are the same statements we used in our animations. They work throughout ATL code.
+Having the image jump around on the screen isn't all that useful. That's why ATL has the interpolation statement.
+The interpolation statement allows you to smoothly vary the value of a transform property, from an old to a new value.
+Here, we have an interpolation statement on the second ATL line. It starts off with the name of a time function, in this case linear.
+That's followed by an amount of time, in this case three seconds. It ends with a list of properties, each followed by its new value.
+The old value is the value of the transform property at the start of the statement. By interpolating the property over time, we can change things on the screen.
+ATL supports more complicated move types, like circle and spline motion. But I won't be showing those here.
+Next, let's take a look at some of the transform properties that we can change using ATL.
+We've already seen the position properties. Along with xalign and yalign, we support the xpos, ypos, xanchor, and yanchor properties.
+We can perform a pan by using xpos and ypos to position images off of the screen.
+This usually means giving them negative positions.
+The zoom property lets us scale the displayable by a factor, making it bigger and smaller. For best results, zoom should always be greater than 0.5.
+The xzoom and yzoom properties allow the displayable to be scaled in the X and Y directions independently.
+The size property can be used to set a size, in pixels, that the displayable is scaled to.
+The alpha property allows us to vary the opacity of a displayable. This can make it appear and disappear.
+The rotate property lets us rotate a displayable.
+Since rotation can change the size, usually you'll want to set xanchor and yanchor to 0.5 when positioning a rotated displayable.
+The crop property crops a rectangle out of a displayable, showing only part of it.
+When used together, they can be used to focus in on specific parts of an image.
+Apart from displayables, pause, interpolation, and repeat, there are a few other statements we can use as part of ATL.
+When we create an ATL transform using the transform statement, we can use that transform as an ATL statement.
+Since the default positions are also transforms, this means that we can use left, right, and center inside of an ATL block.
+Here, we have two new statements. The block statement allows you to include a block of ATL code. Since the repeat statement applies to blocks, this lets you repeat only part of an ATL transform.
+We also have the time statement, which runs after the given number of seconds have elapsed from the start of the block. It will run even if another statement is running, stopping the other statement.
+So this code will bounce the image back and forth for eleven and a half seconds, and then move back to the right side of the screen.
+The parallel statement lets us run two blocks of ATL code at the same time.
+Here, the top block move the image in the horizontal direction, and the bottom block moves it in the vertical direction. Since they're moving at different speeds, it looks like the image is bouncing on the screen.
+Finally, the choice statement makes Ren'Py randomly pick a block of ATL code. This allows you to add some variation as to what Ren'Py shows.
+This tutorial game has only scratched the surface of what you can do with ATL. For example, we haven't even covered the on and event statements. For more information, you might want to check out the ATL chapter in the reference manual.
+But for now, just remember that when it comes to animating and transforming, ATL is the hot new thing.
+Ren'Py gives a number of ways of interacting with the user.
+You've already seen say statements and menus.
+But were you aware that you can have dialogue and menus onscreen at the same time?
+Good!
+Well, now you know.
+We can also prompt the user to enter some text.
+My name is [povname!t].
+Imagemaps let the user click on an image to make a choice. For example, the following screen lets you pick what to do after school:
+You chose swimming.
+Swimming seems like a lot of fun, but I didn't bring my bathing suit with me.
+You chose science.
+I've heard that some schools have a competitive science team, but to me research is something that can't be rushed.
+You chose art.
+Really good background art is hard to make, which is why so many games use filtered photographs. Maybe you can change that.
+You chose to go home.
+Anyway...
+We also support viewports, that allow us to display things that are bigger than the screen.
+This viewport can be adjusted by dragging, by the mouse wheel, and by the scrollbars.
+Viewports also support edge scrolling, which is automatic scrolling when the mouse reaches their edge.
+While these constructs are probably enough for most visual novels, dating simulations may be more complicated.
+The ui functions allow you to create quite complicated interfaces.
+For example, try the following scheduling and stats screen, which could be used by a stat-based dating simulation.
+For a better implementation of this, take a look at the dating sim engine (DSE) that ships with Ren'Py.
+The ui functions can be also be used to show the sorts of stats you'd need if your game involves combat.
+Hopefully, the ui functions will let you write whatever visual novel or dating sim you want.
+The DynamicDisplayable function lets you change what's displayed over the course of an interaction.
+This makes it possible to display things like countdown timers and progress bars.
+Remember, people read at different speeds, so it's probably better to use this for flavor, rather then to make games time-sensitive.
+Image operations allow us to manipulate images as they are loaded in.
+They're efficient, as they are only evaluated when an image is first loaded.
+This way, there's no extra work that needs to be done when each frame is drawn to the screen.
+Let me show you a test image, the Ren'Py logo.
+We'll be applying some image operations to it, to see how they can be used.
+The im.Crop operation can take the image, and chop it up into a smaller image.
+The im.Composite operation lets us take multiple images, and draw them into a single image.
+While you can do this by showing multiple images, this is often more efficient.
+There's also LiveComposite, which is less efficent, but allows for animation.
+It isn't really an image operation, but we don't know where else to put it.
+The im.Scale operation lets us scale an image to a particular size.
+im.FactorScale lets us do the same thing, except to a factor of the original size.
+The im.Map operation lets us mess with the red, green, blue, and alpha channels of an image.
+In this case, we removed all the red from the image, leaving only the blue and green channels.
+The im.Recolor operation can do the same thing, but is more efficient when we're linearly mapping colors.
+The im.Twocolor operation lets you take a black and white image, like this one...
+... and assign colors to replace black and white.
+The im.MatrixColor operation lets you use a matrix to alter the colors. With the right matrix, you can desaturate colors...
+... tint the image blue...
+... rotate the hue... 
+... or invert the colors, for a kinda scary look.
+It can even adjust brightness and contrast.
+We've made some of the most common matrices into image operators.
+im.Grayscale can make an image grayscale...
+... while im.Sepia can sepia-tone an image.
+The im.Alpha operation can adjust the alpha channel on an image, making things partially transparent.
+It's useful if a character just happens to be ghost.
+But that isn't the case with me.
+Finally, there's im.Flip, which can flip an image horizontally or vertically.
+I think the less I say about this, the better.
+Ren'Py lets you define layers, and show images on specific layers.
+The "onlayer" clause of the scene, show, and hide statements lets us pick which layers the commands affect.
+As you can see, layers do not have to take up the entire screen. When a layer doesn't, images are clipped to the layer.
+The "as" clause lets you change the tag of an image.
+This is useful when you want to show two copies of the same image.
+Or if a character has a twin.
+You can use "show expression" to show things that aren't just images, like text.
+The "behind" clause lets you place an image behind another.
+Finally, the "show layer" statement allows you to apply a transform to an entire layer.
+And that's it for layers and advanced show.
+As someone who has played more than a few visual novels, there are many features that I expect all games to have.
+Features like saving, loading, changing preferences, and so on.
+One of the nice things about Ren'Py is that the engine provides many of these features for you. You can spend your time creating your game, and let us provide these things.
+While you're in the game, you can access the game menu by right clicking or hitting the escape key.
+When you first enter the game menu, you'll see the save screen. Clicking on a numbered slot will save the game.
+Unlike other engines, Ren'Py doesn't limit the number of save slots that you can use.
+The load screen looks quite similar to the save screen, and lets you load a game from a save slot.
+It also lets you load one of the auto-saves that Ren'Py makes for you.
+The other screen of the game menu is the preferences screen.
+This screen lets you decide how Ren'Py displays, pick what Ren'Py skips, control text speed and auto-click speed, and adjust sound, music, and voice volumes.
+The game menu also lets you end the game and return to the main menu, or quit Ren'Py entirely.
+While the default game menus look a bit generic, with a little work they can be customized or even entirely replaced, allowing you to create menus as unique as your game.
+While inside the game, there are a few more things you can do.
+When I'm liking a visual novel, I want to see all the endings. Ren'Py's skip function lets me easily do this, by skipping text that I've already seen.
+I can skip a few lines by holding down Control, or I can toggle skip mode by pressing tab.
+By default, we only skip read text, so this won't do anything the first time through the game.
+Pressing the 's' key saves a screenshot to disk, so I can upload pictures of the game to websites like {a=http://www.renpy.org}renpy.org{/a}.
+Finally, there's rollback, which lets you go back in time to previous screens, letting you re-read text.
+Would you like to hear more about rollback?
+You can invoke a rollback by scrolling the mouse wheel up, or by pushing the page up key. That'll bring you back to the previous screen.
+While at a previous screen, you can roll forward by scrolling the mouse wheel down, or pushing the page down key.
+Rolling forward through a menu will make the same choice you did last time. But unlike other engines, Ren'Py's rollback system allows you to make a different choice.
+You can try it by rolling back through the last menu, and saying 'No'.
+Press page up, or scroll up the mouse wheel.
+Well, are you going to try it?
+Your loss.
+Moving on.
+By allowing Ren'Py to take care of out-of-game issues like loading and saving, you can focus on making your game, while still giving users the experience they've come to expect.
+Ren'Py supports a sprite system, which allows many similar objects to be shown on the screen at once.
+The background behind me consists of one hundred and seventy-five stars, being moved at several different speeds, to give a starflight effect.
+The OpenGL system should be able to animate this smoothly, but you might see a bit of stuttering if your computer is using software.
+You'll need to decide which older systems to support.
+The sprite manager requires you to write a python function to move the sprites around.
+In many cases, all you need is something moving around the screen - like cherry blossoms, or snow.
+That's what the snowblossom function gives you - a simple way to have things falling from the top of the screen.
+And that's it for sprites.
+NVL-style games are games that cover the full screen with text, rather then placing it in a file at the bottom of the screen.
+Ren'Py ships with a file, nvl_mode.rpy, that implements NVL-style games. You're seeing an example of NVL-mode at work.
+To use NVL-mode, you need to define Characters with a kind=nvl.
+You use 'nvl clear' to clear the screen when that becomes necessary.
+The 'nvl show' and 'nvl hide' statements use transitions to show and hide the NVL window.
+The nvl_erase function removes a line from the screen.
+Like that.
+The nvl_mode also supports showing menus to the user, provided they are the last thing on the screen. Understand?
+Good!
+Well, it might help if you take a look at the demo code.
+You can specify transitions that occur when going from NVL-mode to ADV-mode.
+As well as when going from ADV-mode to NVL-mode.
+Text tags like {{w}{w} work in NVL-mode.
+ As does the "extend" special character.
+And that's it for NVL-mode.
+You may want to mix Ren'Py with other forms of gameplay. There are many ways to do this.
+The first is with the UI functions, which can be used to create powerful button and menu based interfaces.
+These are often enough for many simulation-style games.
+We also have two more ways in which Ren'Py can be extended. Both require experience with Python programming, and so aren't for the faint of heart.
+Renpygame is a library that allows pygame games to be run inside Ren'Py.
+When using renpygame, Ren'Py steps out of the way and gives you total control over the user's experience.
+You can get renpygame from the Frameworks page of the Ren'Py website.
+If you want to integrate your code with Ren'Py, you can write a user-defined displayable.
+User-defined displayables are somewhat more limited, but integrate better with the rest of Ren'Py.
+For example, one could support loading and saving while a user-defined displayable is shown.
+Now, why don't we play some pong?
+I win!
+You won! Congratulations.
+Would you like to play again?
+Remember to be careful about putting minigames in a visual novel, since not every visual novel player wants to be good at arcade games.
+Probably the best way to learn Ren'Py is to see it in action. In this tutorial, I'll be showing you some of the things Ren'Py can do, and also showing you how to do them.
+Code examples will show up in a window like the one above. You'll need to click outside of the example window in order to advance the tutorial.
+When an example is bigger than the screen, you can scroll around in it using the mouse wheel or by simply dragging the mouse.
+To create a new project, you can click New Project in the Ren'Py launcher.
+If it's your first time making a Ren'Py game, you'll be asked to pick a directory to store your projects in.
+You'll then be asked for the name of the project, and also to choose a theme for the interface.
+Once that's done, Ren'Py will automatically create a directory and fill it with the files needed to make a project.
+If you have Java installed, you'll be able to click Edit Script to open your project's script.
+Let's see the simplest possible Ren'Py game.
+Wow, It's really really dark in here.
+Better watch out. You don't want to be eaten by a Grue.
+I'll show you the code for that example.
+This code demonstrates two kinds of Ren'Py statements, labels and say statements.
+The first line is a label statement. The label statement is used to give a name to a place in the program.
+In this case, we're naming a place "start". The start label is special, as it marks the place a game begins running.
+The next line is a simple say statement. It consists of a string beginning with a double-quote, and ending at the next double-quote.
+Special characters in strings can be escaped with a backslash. To include " in a string, we have to write \".
+Wow, It's really really dark in here.
+When Ren'Py sees a single string on a line by itself, it uses the narrator to say that string. So a single string can be used to express a character's thoughts.
+Better watch out. You don't want to be eaten by a Grue.
+When we have two strings separated by a space, the first is used as the character's name, and the second is what the character is saying.
+This two-argument form of the say statement is used for dialogue, where a character is speaking out loud.
+If you'd like, you can run this game yourself by erasing everything in your project's script.rpy file, and replacing it with the code in the box above.
+Be sure to preserve the spacing before lines. That's known as indentation, and it's used to help Ren'Py group lines of script into blocks.
+Using a string for a character's name is inconvenient, for two reasons.
+The first is that's it's a bit verbose. While typing "Lucy" isn't so bad, imagine if you had to type "Eileen Richardson" thousands of times.
+The second is that it doesn't leave any place to put styling, which can change the look of a character.
+To solve these problems, Ren'Py lets you define Characters.
+Here's an example Character definition. It begins with the word "define". That tells Ren'Py that we are defining something.
+Define is followed by a short name for the character, like "l". We'll be able to use that short name when writing dialogue.
+This is followed by an equals sign, and the thing that we're defining. In this case, it's a Character.
+On the first line, the character's name is given to be "Lucy", and her name will be drawn a reddish color.
+These short names are case-sensitive. Capital L is a different name from lower-case l, so you'll need to be careful about that.
+Now that we have a character defined, we can use it to say dialogue.
+Why are you trying to put words into my mouth? And who are you calling "it"?
+What's more, what are you going to do about the Grue problem? Are you just going to leave me here?
+Here's the full game, including the two new lines of dialogue, both of which use the Character we defined to say dialogue.
+The one-argument form of the say statement is unchanged, but in the two-argument form, instead of the first string we can use a short name.
+When this say statement is run, Ren'Py will look up the short name, which is really a Python variable. It will then use the associated Character to show the dialogue.
+The Character object controls who is speaking, the color of their name, and many other properties of the dialogue.
+Since the bulk of a visual novel is dialogue, we've tried to make it as easy to write as possible.
+Hopefully, by allowing the use of short names for characters, we've succeeded.
+A visual novel isn't much without images. So let's add some images to our little game.
+Before we can show images, we must first put the image files into the game directory.
+The easiest way to open the game directory is to click the Game Directory button in the Ren'Py launcher.
+All of the image files we'll be using here are in the game directory, under the tutorial directory, under the Ren'Py directory.
+Here are some sample image definitions. They should be placed at the start of the file, without any indentation.
+The image statement begins with the keyword "image", which is followed by an image name, a space-separated list of words.
+The first word in the image name is the image tag. For the first image the tag is "bg", and for the others, it's "lucy".
+This is followed by an equals sign, and a string giving an image name.
+A string giving an image name is only one of the dozens of kinds of displayable that Ren'Py supports.
+Let's see what those look like in the game.
+Now that the lights are on, we don't have to worry about Grues anymore.
+But what's the deal with me being in a cave? Eileen gets to be out in the sun, and I'm stuck here!
+Here's the script for that scene. Notice how it includes two new statements, the scene and show statement.
+The scene statement clears the screen, and then adds a background image.
+The show statement adds a background image on top of all the other images on the screen.
+If there was already an image with the same tag, the new image is used to replace the old one.
+Changes to the list of shown images take place instantly, so in the example, the user won't see the background by itself.
+The second show statement has an at clause, which gives a location on the screen. Common locations are left, right, and center, but you can define many more.
+In this example, we show an image named logo base, and we show it at a user-defined position, logopos.
+We also specify that it should be shown behind another image, in this case eileen. That's me.
+Finally, there's the hide statement, which hides the image with the given tag.
+Since the show statement replaces an image, and the scene statement clears the scene, it's pretty rare to hide an image.
+The main use is for when a character or prop leaves before the scene is over.
+It can be somewhat jarring for the game to jump from place to place.
+To help take some of edge off a change in scene, Ren'Py supports the use of transitions. Let's try that scene change again, but this time we'll use transitions.
+That's much smoother. Here's some example code showing how we include transitions in our game.
+It uses the with statement. The with statement causes the scene to transition from the last things shown to the things currently being shown.
+It takes a transition as an argument. In this case, we're using the Dissolve transition. This transition takes as an argument the amount of time the dissolve should take.
+In this case, each transition takes half a second.
+We can define a short name for a transition, using the define statement. Here, we're defining slowdissolve to be a dissolve that takes a whole second.
+Once a transition has been given a short name, we can use it in our game.
+Ren'Py defines some transitions for you, like dissolve, fade, and move. For more complex or customized transitions, you'll have to define your own.
+If you're interested, check out the Transitions Gallery section of the tutorial.
+Another important part of a visual novel or simulation game is the soundtrack.
+Ren'Py breaks sound up into channels. The channel a sound is played on determines if the sound loops, and if it is saved and restored with the game.
+When a sound is played on the music channel, it is looped, and it is saved when the game is saved.
+When the channel named sound is used, the sound is played once and then stopped. It isn't saved.
+The sounds themselves are stored in audio files. Ren'Py supports the Ogg Vorbis, mp3, mp2, and wav file formats.
+Let's check out some of the commands that can effect the music channel.
+The play music command replaces the currently playing music, and replaces it with the named filename.
+If you specify the currently-playing song, it will restart it.
+If the optional fadeout clause is given, it will fade out the currently playing music before starting the new music.
+The queue statement also adds music to the named channel, but it waits until the currently-playing song is finished before playing the new music.
+The third statement is the stop statement. It stops the music playing on a channel. It too takes the fadeout clause.
+Unlike the music channel, playing a sound on the sound channel causes it to play only once.
+You can queue up multiple sounds on the sound channel, but they will only play one at a time.
+Ren'Py has separate mixers for sound, music, and voices, so the player can adjust them as he likes.
+Many visual novels require the player to make choices from in-game menus. These choices can add some challenge to the game, or adjust it to the player's preferences.
+Do you think your game will use menus?
+While creating a multi-path visual novel can be a bit more work, it can yield a unique experience.
+Games without menus are called kinetic novels, and there are dozens of them available to play.
+Here, you can see the code for that menu. If you scroll down, you can see the code we run after the menu.
+Menus are introduced by the menu statement. The menu statement takes an indented block, in which each line must contain a choice in quotes.
+The choices must end with a colon, as each choice has its own block of Ren'Py code, that is run when that choice is selected.
+Here, each block jumps to a label. While you could put small amounts of Ren'Py code inside a menu label, it's probably good practice to usually jump to a bigger block of code.
+Scrolling down past the menu, you can see the labels that the menu jumps to. There are three labels here, named choice1_yes, choice1_no, and choice1_done.
+When the first menu choice is picked, we jump to the choice1_yes, which runs two lines of script before jumping to choice1_done.
+Similarly, picking the second choice jumps us to choice1_no, which also runs two lines of script.
+The lines beginning with the dollar sign are lines of python code, which are used to set a flag based on the user's choice.
+The flag is named menu_flag, and it's set to True or False based on the user's choice. The if statement can be used to test a flag, so the game can remember the user's choices.
+For example, I remember that you plan to use menus in your game.
+For example, I remember that you're planning to make a kinetic novel, without menus.
+Here's an example that shows how we can test a flag, and do different things if it is true or not.
+Although we won't demonstrate it here, Ren'Py supports making decisions based on a combinations of points, flags, and other factors.
+One of Ren'Py's big advantages is the flexibility using a scripting language like Python provides us. It lets us easily scale from kinetic novels to complex simulation games.
+We look forward to seeing what you make with it.
+Hi! My name is Eileen, and I'd like to welcome you to the Ren'Py tutorial.
+In this tutorial, we'll teach you the basics of Ren'Py, so you can make games of your own. We'll also demonstrate many features, so you can see what Ren'Py is capable of.
+Thank you for viewing this tutorial.
+If you'd like to see a full Ren'Py game, select "The Question" in the launcher.
+You can download new versions of Ren'Py from {a=http://www.renpy.org/}http://www.renpy.org/{/a}. For help and discussion, check out the {a=http://lemmasoft.renai.us/forums/}Lemma Soft Forums{/a}.
+We'd like to thank Piroshki for contributing my sprites, Mugenjohncel for Lucy and the band, and Jake for the magic circle.
+The background music is "Sunflower Slow Drag", by Scott Joplin and Scott Hayden, performed by the United States Marine Band. The concert music is by Alessio.
+We look forward to seeing what you can make with Ren'Py. Have fun!
+The Transform function allows you to rotate, zoom, move, and adjust the alpha of a displayable.
+It does this under the control of a Python function, making it incredibly flexible at the cost of some complexity.
+Here's a simple example, showing how we can change an image as it moves around the screen.
+A nice thing about Transform is that it's "one price".
+If you use it to do a rotation, you can zoom or adjust alpha at no additional cost.
+As the python functions get more complicated, more advanced behavior is possible.
+This can include coordinating more than one Transform.
+Finally, transforms can be applied to buttons, and work even while the button is zoomed.
+With a little Python code, transforms let you do a lot of things.
+Ren'Py supports per-game and multi-game persistent data.
+Persistent data can store flags and other per-game information that should be shared between plays of a single game.
+For example, I can tell you that you've see this line [plays] time(s) since you cleared the per-game persistent data.
+Multipersistent data is shared between games, which lets one game unlock features in a second.
+A sequel might play differently if the player has beaten the first game.
+According to the multipersistent data, you've seen this line [plays] times total.
diff --git a/tutorial/game/demo_transitions.rpy b/tutorial/game/demo_transitions.rpy
index 0afbc71..fcfdf19 100644
--- a/tutorial/game/demo_transitions.rpy
+++ b/tutorial/game/demo_transitions.rpy
@@ -69,7 +69,7 @@ label demo_transitions:
 
         "AlphaDissolve Transitions":
 
-            call demo_alphadissolve
+            call demo_alphadissolve from _call_demo_alphadissolve
 
         ""
 
diff --git a/tutorial/game/keywords.py b/tutorial/game/keywords.py
index 0bb150e..aa0068f 100644
--- a/tutorial/game/keywords.py
+++ b/tutorial/game/keywords.py
@@ -1,2 +1,2 @@
 keywords = ['$', 'add', 'and', 'animation', 'as', 'as', 'assert', 'at', 'bar', 'behind', 'block', 'break', 'button', 'call', 'choice', 'circles', 'class', 'clockwise', 'contains', 'continue', 'counterclockwise', 'def', 'define', 'del', 'elif', 'else', 'event', 'except', 'exec', 'expression', 'finally', 'fixed', 'for', 'frame', 'from', 'function', 'global', 'grid', 'has', 'hbox', 'hide', 'hotbar', 'hotspot', 'if', 'if', 'image', 'imagebutton', 'imagemap', 'import', 'in', 'in', 'init', 'in [...]
-properties = ['action', 'activate_additive', 'activate_adjust_spacing', 'activate_align', 'activate_alignaround', 'activate_alpha', 'activate_alt', 'activate_anchor', 'activate_angle', 'activate_antialias', 'activate_area', 'activate_around', 'activate_background', 'activate_bar_invert', 'activate_bar_resizing', 'activate_bar_vertical', 'activate_base_bar', 'activate_black_color', 'activate_bold', 'activate_bottom_bar', 'activate_bottom_gutter', 'activate_bottom_margin', 'activate_bottom [...]
+properties = ['action', 'activate_additive', 'activate_adjust_spacing', 'activate_align', 'activate_alignaround', 'activate_alpha', 'activate_alt', 'activate_anchor', 'activate_angle', 'activate_antialias', 'activate_area', 'activate_around', 'activate_background', 'activate_bar_invert', 'activate_bar_resizing', 'activate_bar_vertical', 'activate_base_bar', 'activate_black_color', 'activate_bold', 'activate_bottom_bar', 'activate_bottom_gutter', 'activate_bottom_margin', 'activate_bottom [...]
diff --git a/tutorial/game/options.rpy b/tutorial/game/options.rpy
index e76fedc..ab4876b 100644
--- a/tutorial/game/options.rpy
+++ b/tutorial/game/options.rpy
@@ -376,3 +376,9 @@ init python:
 
     build.documentation('*.html')
     build.documentation('*.txt')
+
+    # This is tutorial specific code that searches for fonts in
+    # launcher/fonts, reducing the size of the zip file containing
+    # the SDK.
+    config.searchpath.append("../launcher/game/fonts")
+
diff --git a/tutorial/game/screens.rpy b/tutorial/game/screens.rpy
index 4a12711..60b19dd 100644
--- a/tutorial/game/screens.rpy
+++ b/tutorial/game/screens.rpy
@@ -389,12 +389,12 @@ screen preferences():
                 has vbox
 
                 label _("Language")
-                textbutton "English" action Language(None)
-                textbutton "日本語" text_font "tl/japanese/MTLc3m.ttf" action Language("japanese")
-                textbutton "한국어" text_font "tl/korean/NanumGothic.ttf" action Language("korean")
-                textbutton "Русский" action Language("russian")
-                textbutton "Tiếng Việt" action Language("vietnamese")
-                textbutton "Indonesian" action Language("indonesian")
+                textbutton "English" text_font "DejaVuSans.ttf" action Language(None)
+                textbutton "日本語" text_font "MTLc3m.ttf" action Language("japanese")
+                textbutton "한국어" text_font "NanumGothic.ttf" action Language("korean")
+                textbutton "Русский" text_font "DejaVuSans.ttf" action Language("russian")
+                textbutton "Tiếng Việt" text_font "DejaVuSans.ttf" action Language("vietnamese")
+                textbutton "Indonesian" text_font "DejaVuSans.ttf" action Language("indonesian")
 
             # end-tutorial-only
 
diff --git a/tutorial/game/script.rpy b/tutorial/game/script.rpy
index 026c369..3b559ff 100644
--- a/tutorial/game/script.rpy
+++ b/tutorial/game/script.rpy
@@ -102,7 +102,7 @@ label tutorials:
     if _return is False:
         jump end
 
-    call expression _return
+    call expression _return from _call_expression
 
     jump tutorials
 
diff --git a/tutorial/game/testcases.rpy b/tutorial/game/testcases.rpy
index 98a4440..43365fb 100644
--- a/tutorial/game/testcases.rpy
+++ b/tutorial/game/testcases.rpy
@@ -31,7 +31,7 @@ testcase default:
     "That's enough for now."
     click until "Quit"
 
-    pause .6 # Wait out the main menut transition.
+    pause .6 # Wait out the main menu transition.
     "Quit"
 
 testcase quick:
diff --git a/tutorial/game/tl/None/common.rpym b/tutorial/game/tl/None/common.rpym
new file mode 100644
index 0000000..f9c0318
--- /dev/null
+++ b/tutorial/game/tl/None/common.rpym
@@ -0,0 +1,743 @@
+
+translate None strings:
+
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Monday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Tuesday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Wednesday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Thursday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Friday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Saturday"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Sunday"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Mon"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Tue"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Wed"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Thu"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Fri"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Sat"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Sun"
+
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}January"
+
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}February"
+
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}March"
+
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}April"
+
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}May"
+
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}June"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}July"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}August"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}September"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}October"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}November"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}December"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Jan"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Feb"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Mar"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Apr"
+
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}May"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Jun"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Jul"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Aug"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Sep"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Oct"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Nov"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Dec"
+
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%b %d, %H:%M"
+
+    # 00action_file.rpy:569
+    old "Page {}"
+    new "Page {}"
+
+    # 00action_file.rpy:569
+    old "Automatic saves"
+    new "Automatic saves"
+
+    # 00action_file.rpy:569
+    old "Quick saves"
+    new "Quick saves"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Quick save complete."
+
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "Are you sure?"
+
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "Are you sure you want to delete this save?"
+
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "Are you sure you want to overwrite your save?"
+
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "Are you sure you want to quit?"
+
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Are you sure you want to end the replay?"
+
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "Are you sure you want to begin skipping?"
+
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "Are you sure you want to skip to the next choice?"
+
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Are you sure you want to skip unseen dialogue to the next choice?"
+
+    # 00keymap.rpy:251
+    old "Saved screenshot as %s."
+    new "Saved screenshot as %s."
+
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Self-voicing disabled."
+
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Clipboard voicing enabled. "
+
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Self-voicing enabled. "
+
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Skip Mode"
+
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Clipboard voicing enabled. Press 'shift+C' to disable."
+
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Self-voicing enabled. Press 'v' to disable."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Contacting App Store\nPlease Wait..."
+
+    # 00updater.rpy:373
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "The Ren'Py Updater is not supported on mobile devices."
+
+    # 00updater.rpy:492
+    old "An error is being simulated."
+    new "An error is being simulated."
+
+    # 00updater.rpy:668
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Either this project does not support updating, or the update status file was deleted."
+
+    # 00updater.rpy:682
+    old "This account does not have permission to perform an update."
+    new "This account does not have permission to perform an update."
+
+    # 00updater.rpy:685
+    old "This account does not have permission to write the update log."
+    new "This account does not have permission to write the update log."
+
+    # 00updater.rpy:710
+    old "Could not verify update signature."
+    new "Could not verify update signature."
+
+    # 00updater.rpy:981
+    old "The update file was not downloaded."
+    new "The update file was not downloaded."
+
+    # 00updater.rpy:999
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "The update file does not have the correct digest - it may have been corrupted."
+
+    # 00updater.rpy:1055
+    old "While unpacking {}, unknown type {}."
+    new "While unpacking {}, unknown type {}."
+
+    # 00updater.rpy:1399
+    old "Updater"
+    new "Updater"
+
+    # 00updater.rpy:1406
+    old "An error has occured:"
+    new "An error has occured:"
+
+    # 00updater.rpy:1408
+    old "Checking for updates."
+    new "Checking for updates."
+
+    # 00updater.rpy:1410
+    old "This program is up to date."
+    new "This program is up to date."
+
+    # 00updater.rpy:1412
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] is available. Do you want to install it?"
+
+    # 00updater.rpy:1414
+    old "Preparing to download the updates."
+    new "Preparing to download the updates."
+
+    # 00updater.rpy:1416
+    old "Downloading the updates."
+    new "Downloading the updates."
+
+    # 00updater.rpy:1418
+    old "Unpacking the updates."
+    new "Unpacking the updates."
+
+    # 00updater.rpy:1420
+    old "Finishing up."
+    new "Finishing up."
+
+    # 00updater.rpy:1422
+    old "The updates have been installed. The program will restart."
+    new "The updates have been installed. The program will restart."
+
+    # 00updater.rpy:1424
+    old "The updates have been installed."
+    new "The updates have been installed."
+
+    # 00updater.rpy:1426
+    old "The updates were cancelled."
+    new "The updates were cancelled."
+
+    # 00updater.rpy:1441
+    old "Proceed"
+    new "Proceed"
+
+    # 00updater.rpy:1444
+    old "Cancel"
+    new "Cancel"
+
+    # 00compat.rpy:202
+    old "Fullscreen"
+    new "Fullscreen"
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Image [index] of [count] locked."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "prev"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "next"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "slideshow"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "return"
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Graphics Acceleration"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Automatically Choose"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Force Angle/DirectX Renderer"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Force OpenGL Renderer"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Force Software Renderer"
+
+    # 00gltest.rpy:89
+    old "Gamepad"
+    new "Gamepad"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Enable"
+
+    # 00gltest.rpy:97
+    old "Disable"
+    new "Disable"
+
+    # 00gltest.rpy:103
+    old "Calibrate"
+    new "Calibrate"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Changes will take effect the next time this program is run."
+
+    # 00gltest.rpy:114
+    old "Quit"
+    new "Quit"
+
+    # 00gltest.rpy:119
+    old "Return"
+    new "Return"
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Performance Warning"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "This computer is using software rendering."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "This computer is not using shaders."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "This computer is displaying graphics slowly."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "This computer has a problem displaying graphics: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Update DirectX"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Continue, Show this warning again"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Continue, Don't show warning again"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Updating DirectX."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "When setup finishes, please click below to restart this program."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Restart"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Select Gamepad to Calibrate"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "No Gamepads Available"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Calibrating [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Press or move the [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Skip (A)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Back (B)"
+
+    # _errorhandling.rpym:504
+    old "Open Traceback"
+    new "Open Traceback"
+
+    # _errorhandling.rpym:506
+    old "Opens the traceback.txt file in a text editor."
+    new "Opens the traceback.txt file in a text editor."
+
+    # _errorhandling.rpym:508
+    old "Copy to Clipboard"
+    new "Copy to Clipboard"
+
+    # _errorhandling.rpym:510
+    old "Copies the traceback.txt file to the clipboard."
+    new "Copies the traceback.txt file to the clipboard."
+
+    # _errorhandling.rpym:528
+    old "An exception has occurred."
+    new "An exception has occurred."
+
+    # _errorhandling.rpym:547
+    old "Rollback"
+    new "Rollback"
+
+    # _errorhandling.rpym:549
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+
+    # _errorhandling.rpym:552
+    old "Ignore"
+    new "Ignore"
+
+    # _errorhandling.rpym:554
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Ignores the exception, allowing you to continue. This often leads to additional errors."
+
+    # _errorhandling.rpym:557
+    old "Reload"
+    new "Reload"
+
+    # _errorhandling.rpym:559
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Reloads the game from disk, saving and restoring game state if possible."
+
+    # _errorhandling.rpym:569
+    old "Quits the game."
+    new "Quits the game."
+
+    # _errorhandling.rpym:591
+    old "Parsing the script failed."
+    new "Parsing the script failed."
+
+    # _errorhandling.rpym:615
+    old "Open Parse Errors"
+    new "Open Parse Errors"
+
+    # _errorhandling.rpym:617
+    old "Opens the errors.txt file in a text editor."
+    new "Opens the errors.txt file in a text editor."
+
+    # _errorhandling.rpym:621
+    old "Copies the errors.txt file to the clipboard."
+    new "Copies the errors.txt file to the clipboard."
+
+    # _developer/developer.rpym:38
+    old "Developer Menu"
+    new "Developer Menu"
+
+    # _developer/developer.rpym:43
+    old "Reload Game (Shift+R)"
+    new "Reload Game (Shift+R)"
+
+    # _developer/developer.rpym:45
+    old "Console (Shift+O)"
+    new "Console (Shift+O)"
+
+    # _developer/developer.rpym:47
+    old "Variable Viewer"
+    new "Variable Viewer"
+
+    # _developer/developer.rpym:49
+    old "Theme Test"
+    new "Theme Test"
+
+    # _developer/developer.rpym:51
+    old "Image Location Picker"
+    new "Image Location Picker"
+
+    # _developer/developer.rpym:53
+    old "Filename List"
+    new "Filename List"
+
+    # _developer/developer.rpym:57
+    old "Show Image Load Log"
+    new "Show Image Load Log"
+
+    # _developer/developer.rpym:60
+    old "Hide Image Load Log"
+    new "Hide Image Load Log"
+
+    # _developer/developer.rpym:95
+    old "Nothing to inspect."
+    new "Nothing to inspect."
+
+    # _developer/developer.rpym:217
+    old "Return to the developer menu"
+    new "Return to the developer menu"
+
+    # _developer/developer.rpym:373
+    old "Rectangle: %r"
+    new "Rectangle: %r"
+
+    # _developer/developer.rpym:378
+    old "Mouse position: %r"
+    new "Mouse position: %r"
+
+    # _developer/developer.rpym:383
+    old "Right-click or escape to quit."
+    new "Right-click or escape to quit."
+
+    # _developer/developer.rpym:412
+    old "Rectangle copied to clipboard."
+    new "Rectangle copied to clipboard."
+
+    # _developer/developer.rpym:415
+    old "Position copied to clipboard."
+    new "Position copied to clipboard."
+
+    # _developer/developer.rpym:524
+    old "✔ "
+    new "✔ "
+
+    # _developer/developer.rpym:527
+    old "✘ "
+    new "✘ "
+
+    # _developer/developer.rpym:532
+    old "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+    new "\n{color=#cfc}✔ predicted image (good){/color}\n{color=#fcc}✘ unpredicted image (bad){/color}\n{color=#fff}Drag to move.{/color}"
+
+    # _developer/inspector.rpym:38
+    old "Displayable Inspector"
+    new "Displayable Inspector"
+
+    # _developer/inspector.rpym:61
+    old "Size"
+    new "Size"
+
+    # _developer/inspector.rpym:65
+    old "Style"
+    new "Style"
+
+    # _developer/inspector.rpym:71
+    old "Location"
+    new "Location"
+
+    # _developer/inspector.rpym:122
+    old "Inspecting Styles of [displayable_name!q]"
+    new "Inspecting Styles of [displayable_name!q]"
+
+    # _developer/inspector.rpym:139
+    old "displayable:"
+    new "displayable:"
+
+    # _developer/inspector.rpym:145
+    old "        (no properties affect the displayable)"
+    new "        (no properties affect the displayable)"
+
+    # _developer/inspector.rpym:147
+    old "        (default properties omitted)"
+    new "        (default properties omitted)"
+
+    # _developer/inspector.rpym:185
+    old "<repr() failed>"
+    new "<repr() failed>"
+
+    # 00console.rpy:182
+    old "Press <esc> to exit console. Type help for help.\n"
+    new "Press <esc> to exit console. Type help for help.\n"
+
+    # 00console.rpy:186
+    old "Ren'Py script enabled."
+    new "Ren'Py script enabled."
+
+    # 00console.rpy:188
+    old "Ren'Py script disabled."
+    new "Ren'Py script disabled."
+
+    # 00console.rpy:398
+    old "help: show this help"
+    new "help: show this help"
+
+    # 00console.rpy:403
+    old "commands:\n"
+    new "commands:\n"
+
+    # 00console.rpy:413
+    old " <renpy script statement>: run the statement\n"
+    new " <renpy script statement>: run the statement\n"
+
+    # 00console.rpy:415
+    old " <python expression or statement>: run the expression or statement"
+    new " <python expression or statement>: run the expression or statement"
+
+    # 00console.rpy:423
+    old "clear: clear the console history"
+    new "clear: clear the console history"
+
+    # 00console.rpy:427
+    old "exit: exit the console"
+    new "exit: exit the console"
+
+    # 00console.rpy:435
+    old "load <slot>: loads the game from slot"
+    new "load <slot>: loads the game from slot"
+
+    # 00console.rpy:448
+    old "save <slot>: saves the game in slot"
+    new "save <slot>: saves the game in slot"
+
+    # 00console.rpy:459
+    old "reload: reloads the game, refreshing the scripts"
+    new "reload: reloads the game, refreshing the scripts"
+
+    # 00console.rpy:467
+    old "watch <expression>: watch a python expression"
+    new "watch <expression>: watch a python expression"
+
+    # 00console.rpy:493
+    old "unwatch <expression>: stop watching an expression"
+    new "unwatch <expression>: stop watching an expression"
+
+    # 00console.rpy:519
+    old "unwatchall: stop watching all expressions"
+    new "unwatchall: stop watching all expressions"
+
+    # 00console.rpy:536
+    old "jump <label>: jumps to label"
+    new "jump <label>: jumps to label"
+
diff --git a/tutorial/game/tl/piglatin/common.rpy b/tutorial/game/tl/piglatin/common.rpy
new file mode 100644
index 0000000..be148c0
--- /dev/null
+++ b/tutorial/game/tl/piglatin/common.rpy
@@ -0,0 +1,555 @@
+
+translate piglatin strings:
+
+    # 00action_file.rpy:26
+    old "{#weekday}Monday"
+    new "{#weekday}Ondaymay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Tuesday"
+    new "{#weekday}Uesdaytay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Wednesday"
+    new "{#weekday}Ednesdayway"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Thursday"
+    new "{#weekday}Hursdaytay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Friday"
+    new "{#weekday}Ridayfay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Saturday"
+    new "{#weekday}Aturdaysay"
+
+    # 00action_file.rpy:26
+    old "{#weekday}Sunday"
+    new "{#weekday}Undaysay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Mon"
+    new "{#weekday_short}Onmay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Tue"
+    new "{#weekday_short}Uetay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Wed"
+    new "{#weekday_short}Edway"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Thu"
+    new "{#weekday_short}Hutay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Fri"
+    new "{#weekday_short}Rifay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sat"
+    new "{#weekday_short}Atsay"
+
+    # 00action_file.rpy:37
+    old "{#weekday_short}Sun"
+    new "{#weekday_short}Unsay"
+
+    # 00action_file.rpy:47
+    old "{#month}January"
+    new "{#month}Anuaryjay"
+
+    # 00action_file.rpy:47
+    old "{#month}February"
+    new "{#month}Ebruaryfay"
+
+    # 00action_file.rpy:47
+    old "{#month}March"
+    new "{#month}Archmay"
+
+    # 00action_file.rpy:47
+    old "{#month}April"
+    new "{#month}Prilaay"
+
+    # 00action_file.rpy:47
+    old "{#month}May"
+    new "{#month}Aymay"
+
+    # 00action_file.rpy:47
+    old "{#month}June"
+    new "{#month}Unejay"
+
+    # 00action_file.rpy:47
+    old "{#month}July"
+    new "{#month}Ulyjay"
+
+    # 00action_file.rpy:47
+    old "{#month}August"
+    new "{#month}Ugustaay"
+
+    # 00action_file.rpy:47
+    old "{#month}September"
+    new "{#month}Eptembersay"
+
+    # 00action_file.rpy:47
+    old "{#month}October"
+    new "{#month}Ctoberoay"
+
+    # 00action_file.rpy:47
+    old "{#month}November"
+    new "{#month}Ovembernay"
+
+    # 00action_file.rpy:47
+    old "{#month}December"
+    new "{#month}Ecemberday"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jan"
+    new "{#month_short}Anjay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Feb"
+    new "{#month_short}Ebfay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Mar"
+    new "{#month_short}Armay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Apr"
+    new "{#month_short}Praay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}May"
+    new "{#month_short}Aymay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jun"
+    new "{#month_short}Unjay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Jul"
+    new "{#month_short}Uljay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Aug"
+    new "{#month_short}Ugaay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Sep"
+    new "{#month_short}Epsay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Oct"
+    new "{#month_short}Ctoay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Nov"
+    new "{#month_short}Ovnay"
+
+    # 00action_file.rpy:63
+    old "{#month_short}Dec"
+    new "{#month_short}Ecday"
+
+    # 00action_file.rpy:235
+    old "%b %d, %H:%M"
+    new "%bay %day, %Hay:%May"
+
+    # 00action_file.rpy:569
+    old "Page {}"
+    new "Agepay {}"
+
+    # 00action_file.rpy:569
+    old "Automatic saves"
+    new "Utomaticaay avessay"
+
+    # 00action_file.rpy:569
+    old "Quick saves"
+    new "Uickqay avessay"
+
+    # 00action_file.rpy:820
+    old "Quick save complete."
+    new "Uickqay avesay ompletecay."
+
+    # 00gui.rpy:227
+    old "Are you sure?"
+    new "Reaay ouyay uresay?"
+
+    # 00gui.rpy:228
+    old "Are you sure you want to delete this save?"
+    new "Reaay ouyay uresay ouyay antway otay eleteday histay avesay?"
+
+    # 00gui.rpy:229
+    old "Are you sure you want to overwrite your save?"
+    new "Reaay ouyay uresay ouyay antway otay overwriteay ouryay avesay?"
+
+    # 00gui.rpy:230
+    old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
+    new "Oadinglay illway oselay unsaveday rogresspay.\nReaay ouyay uresay ouyay antway otay oday histay?"
+
+    # 00gui.rpy:231
+    old "Are you sure you want to quit?"
+    new "Reaay ouyay uresay ouyay antway otay uitqay?"
+
+    # 00gui.rpy:232
+    old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
+    new "Reaay ouyay uresay ouyay antway otay eturnray otay hetay ainmay enumay?\nHistay illway oselay unsaveday rogresspay."
+
+    # 00gui.rpy:233
+    old "Are you sure you want to end the replay?"
+    new "Reaay ouyay uresay ouyay antway otay enday hetay eplayray?"
+
+    # 00gui.rpy:234
+    old "Are you sure you want to begin skipping?"
+    new "Reaay ouyay uresay ouyay antway otay eginbay kippingsay?"
+
+    # 00gui.rpy:235
+    old "Are you sure you want to skip to the next choice?"
+    new "Reaay ouyay uresay ouyay antway otay kipsay otay hetay extnay oicechay?"
+
+    # 00gui.rpy:236
+    old "Are you sure you want to skip unseen dialogue to the next choice?"
+    new "Reaay ouyay uresay ouyay antway otay kipsay unseenay ialogueday otay hetay extnay oicechay?"
+
+    # 00keymap.rpy:251
+    old "Saved screenshot as %s."
+    new "Avedsay creenshotsay asay %say."
+
+    # 00library.rpy:142
+    old "Self-voicing disabled."
+    new "Elfsay-oicingvay isabledday."
+
+    # 00library.rpy:143
+    old "Clipboard voicing enabled. "
+    new "Lipboardcay oicingvay enableday. "
+
+    # 00library.rpy:144
+    old "Self-voicing enabled. "
+    new "Elfsay-oicingvay enableday. "
+
+    # 00library.rpy:179
+    old "Skip Mode"
+    new "Kipsay Odemay"
+
+    # 00library.rpy:262
+    old "This program contains free software under a number of licenses, including the MIT License and GNU Lesser General Public License. A complete list of software, including links to full source code, can be found {a=https://www.renpy.org/l/license}here{/a}."
+    new "Histay rogrampay ontainscay eefray oftwaresay underay aay umbernay ofay icenseslay, includingay hetay Itmay Icenselay anday Nugay Esserlay Eneralgay Ublicpay Icenselay. Aay ompletecay istlay ofay oftwaresay, includingay inkslay otay ullfay ourcesay odecay, ancay ebay oundfay {a=https://www.renpy.org/l/license}erehay{/a}."
+
+    # 00preferences.rpy:422
+    old "Clipboard voicing enabled. Press 'shift+C' to disable."
+    new "Lipboardcay oicingvay enableday. Resspay 'iftshay+Cay' otay isableday."
+
+    # 00preferences.rpy:424
+    old "Self-voicing would say \"[renpy.display.tts.last]\". Press 'alt+shift+V' to disable."
+    new "Elfsay-oicingvay ouldway aysay \"[renpy.display.tts.last]\". Resspay 'altay+iftshay+Vay' otay isableday."
+
+    # 00preferences.rpy:426
+    old "Self-voicing enabled. Press 'v' to disable."
+    new "Elfsay-oicingvay enableday. Resspay 'vay' otay isableday."
+
+    # 00iap.rpy:217
+    old "Contacting App Store\nPlease Wait..."
+    new "Ontactingcay Ppaay Toresay\nLeasepay Aitway..."
+
+    # 00updater.rpy:373
+    old "The Ren'Py Updater is not supported on mobile devices."
+    new "Hetay Enray'Ypay Pdateruay isay otnay upportedsay onay obilemay evicesday."
+
+    # 00updater.rpy:492
+    old "An error is being simulated."
+    new "Naay erroray isay eingbay imulatedsay."
+
+    # 00updater.rpy:668
+    old "Either this project does not support updating, or the update status file was deleted."
+    new "Ithereay histay rojectpay oesday otnay upportsay updatingay, oray hetay updateay atusstay ilefay asway eletedday."
+
+    # 00updater.rpy:682
+    old "This account does not have permission to perform an update."
+    new "Histay accountay oesday otnay avehay ermissionpay otay erformpay anay updateay."
+
+    # 00updater.rpy:685
+    old "This account does not have permission to write the update log."
+    new "Histay accountay oesday otnay avehay ermissionpay otay riteway hetay updateay oglay."
+
+    # 00updater.rpy:710
+    old "Could not verify update signature."
+    new "Ouldcay otnay erifyvay updateay ignaturesay."
+
+    # 00updater.rpy:981
+    old "The update file was not downloaded."
+    new "Hetay updateay ilefay asway otnay ownloadedday."
+
+    # 00updater.rpy:999
+    old "The update file does not have the correct digest - it may have been corrupted."
+    new "Hetay updateay ilefay oesday otnay avehay hetay orrectcay igestday - itay aymay avehay eenbay orruptedcay."
+
+    # 00updater.rpy:1055
+    old "While unpacking {}, unknown type {}."
+    new "Hileway unpackingay {}, unknownay ypetay {}."
+
+    # 00updater.rpy:1399
+    old "Updater"
+    new "Pdateruay"
+
+    # 00updater.rpy:1406
+    old "An error has occured:"
+    new "Naay erroray ashay occureday:"
+
+    # 00updater.rpy:1408
+    old "Checking for updates."
+    new "Heckingcay orfay updatesay."
+
+    # 00updater.rpy:1410
+    old "This program is up to date."
+    new "Histay rogrampay isay upay otay ateday."
+
+    # 00updater.rpy:1412
+    old "[u.version] is available. Do you want to install it?"
+    new "[u.version] isay availableay. Oday ouyay antway otay installay itay?"
+
+    # 00updater.rpy:1414
+    old "Preparing to download the updates."
+    new "Reparingpay otay ownloadday hetay updatesay."
+
+    # 00updater.rpy:1416
+    old "Downloading the updates."
+    new "Ownloadingday hetay updatesay."
+
+    # 00updater.rpy:1418
+    old "Unpacking the updates."
+    new "Npackinguay hetay updatesay."
+
+    # 00updater.rpy:1420
+    old "Finishing up."
+    new "Inishingfay upay."
+
+    # 00updater.rpy:1422
+    old "The updates have been installed. The program will restart."
+    new "Hetay updatesay avehay eenbay installeday. Hetay rogrampay illway estartray."
+
+    # 00updater.rpy:1424
+    old "The updates have been installed."
+    new "Hetay updatesay avehay eenbay installeday."
+
+    # 00updater.rpy:1426
+    old "The updates were cancelled."
+    new "Hetay updatesay ereway ancelledcay."
+
+    # 00updater.rpy:1441
+    old "Proceed"
+    new "Roceedpay"
+
+    # 00updater.rpy:1444
+    old "Cancel"
+    new "Ancelcay"
+
+    # 00gallery.rpy:563
+    old "Image [index] of [count] locked."
+    new "Mageiay [index] ofay [count] ockedlay."
+
+    # 00gallery.rpy:583
+    old "prev"
+    new "revpay"
+
+    # 00gallery.rpy:584
+    old "next"
+    new "extnay"
+
+    # 00gallery.rpy:585
+    old "slideshow"
+    new "ideshowslay"
+
+    # 00gallery.rpy:586
+    old "return"
+    new "eturnray"
+
+    # 00gltest.rpy:64
+    old "Graphics Acceleration"
+    new "Raphicsgay Ccelerationaay"
+
+    # 00gltest.rpy:70
+    old "Automatically Choose"
+    new "Utomaticallyaay Hoosecay"
+
+    # 00gltest.rpy:75
+    old "Force Angle/DirectX Renderer"
+    new "Orcefay Ngleaay/Irectxday Endererray"
+
+    # 00gltest.rpy:79
+    old "Force OpenGL Renderer"
+    new "Orcefay Pengloay Endererray"
+
+    # 00gltest.rpy:83
+    old "Force Software Renderer"
+    new "Orcefay Oftwaresay Endererray"
+
+    # 00gltest.rpy:89
+    old "Gamepad"
+    new "Amepadgay"
+
+    # 00gltest.rpy:93
+    old "Enable"
+    new "Nableeay"
+
+    # 00gltest.rpy:97
+    old "Disable"
+    new "Isableday"
+
+    # 00gltest.rpy:103
+    old "Calibrate"
+    new "Alibratecay"
+
+    # 00gltest.rpy:109
+    old "Changes will take effect the next time this program is run."
+    new "Hangescay illway aketay effectay hetay extnay imetay histay rogrampay isay unray."
+
+    # 00gltest.rpy:141
+    old "Performance Warning"
+    new "Erformancepay Arningway"
+
+    # 00gltest.rpy:146
+    old "This computer is using software rendering."
+    new "Histay omputercay isay usingay oftwaresay enderingray."
+
+    # 00gltest.rpy:148
+    old "This computer is not using shaders."
+    new "Histay omputercay isay otnay usingay adersshay."
+
+    # 00gltest.rpy:150
+    old "This computer is displaying graphics slowly."
+    new "Histay omputercay isay isplayingday aphicsgray owlyslay."
+
+    # 00gltest.rpy:152
+    old "This computer has a problem displaying graphics: [problem]."
+    new "Histay omputercay ashay aay roblempay isplayingday aphicsgray: [problem]."
+
+    # 00gltest.rpy:157
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
+    new "Tsiay aphicsgray riversday aymay ebay outay ofay ateday oray otnay operatingay orrectlycay. Histay ancay eadlay otay owslay oray incorrectay aphicsgray isplayday. Pdatinguay Irectxday ouldcay ixfay histay roblempay."
+
+    # 00gltest.rpy:159
+    old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
+    new "Tsiay aphicsgray riversday aymay ebay outay ofay ateday oray otnay operatingay orrectlycay. Histay ancay eadlay otay owslay oray incorrectay aphicsgray isplayday."
+
+    # 00gltest.rpy:164
+    old "Update DirectX"
+    new "Pdateuay Irectxday"
+
+    # 00gltest.rpy:170
+    old "Continue, Show this warning again"
+    new "Ontinuecay, Howsay histay arningway againay"
+
+    # 00gltest.rpy:174
+    old "Continue, Don't show warning again"
+    new "Ontinuecay, Onday'tay owshay arningway againay"
+
+    # 00gltest.rpy:192
+    old "Updating DirectX."
+    new "Pdatinguay Irectxday."
+
+    # 00gltest.rpy:196
+    old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
+    new "Irectxday ebway etupsay ashay eenbay artedstay. Tiay aymay artstay inimizedmay inay hetay askbartay. Leasepay ollowfay hetay romptspay otay installay Irectxday."
+
+    # 00gltest.rpy:200
+    old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
+    new "{b}Otenay:{/b} Icrosoftmay'say Irectxday ebway etupsay rogrampay illway, ybay efaultday, installay hetay Ingbay oolbartay. Fiay ouyay oday otnay antway histay oolbartay, uncheckay hetay appropriateay oxbay."
+
+    # 00gltest.rpy:204
+    old "When setup finishes, please click below to restart this program."
+    new "Henway etupsay inishesfay, easeplay ickclay elowbay otay estartray histay rogrampay."
+
+    # 00gltest.rpy:206
+    old "Restart"
+    new "Estartray"
+
+    # 00gamepad.rpy:32
+    old "Select Gamepad to Calibrate"
+    new "Electsay Amepadgay otay Alibratecay"
+
+    # 00gamepad.rpy:35
+    old "No Gamepads Available"
+    new "Onay Amepadsgay Vailableaay"
+
+    # 00gamepad.rpy:54
+    old "Calibrating [name] ([i]/[total])"
+    new "Alibratingcay [name] ([i]/[total])"
+
+    # 00gamepad.rpy:58
+    old "Press or move the [control!r] [kind]."
+    new "Resspay oray ovemay hetay [control!r] [kind]."
+
+    # 00gamepad.rpy:66
+    old "Skip (A)"
+    new "Kipsay (Aay)"
+
+    # 00gamepad.rpy:69
+    old "Back (B)"
+    new "Ackbay (Bay)"
+
+    # _errorhandling.rpym:504
+    old "Open Traceback"
+    new "Penoay Racebacktay"
+
+    # _errorhandling.rpym:506
+    old "Opens the traceback.txt file in a text editor."
+    new "Pensoay hetay acebacktray.xttay ilefay inay aay exttay editoray."
+
+    # _errorhandling.rpym:508
+    old "Copy to Clipboard"
+    new "Opycay otay Lipboardcay"
+
+    # _errorhandling.rpym:510
+    old "Copies the traceback.txt file to the clipboard."
+    new "Opiescay hetay acebacktray.xttay ilefay otay hetay ipboardclay."
+
+    # _errorhandling.rpym:528
+    old "An exception has occurred."
+    new "Naay exceptionay ashay occurreday."
+
+    # _errorhandling.rpym:547
+    old "Rollback"
+    new "Ollbackray"
+
+    # _errorhandling.rpym:549
+    old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
+    new "Ttemptsaay aay ollray ackbay otay aay riorpay imetay, allowingay ouyay otay avesay oray oosechay aay ifferentday oicechay."
+
+    # _errorhandling.rpym:552
+    old "Ignore"
+    new "Gnoreiay"
+
+    # _errorhandling.rpym:554
+    old "Ignores the exception, allowing you to continue. This often leads to additional errors."
+    new "Gnoresiay hetay exceptionay, allowingay ouyay otay ontinuecay. Histay oftenay eadslay otay additionalay errorsay."
+
+    # _errorhandling.rpym:557
+    old "Reload"
+    new "Eloadray"
+
+    # _errorhandling.rpym:559
+    old "Reloads the game from disk, saving and restoring game state if possible."
+    new "Eloadsray hetay amegay omfray iskday, avingsay anday estoringray amegay atestay ifay ossiblepay."
+
+    # _errorhandling.rpym:569
+    old "Quits the game."
+    new "Uitsqay hetay amegay."
+
+    # _errorhandling.rpym:591
+    old "Parsing the script failed."
+    new "Arsingpay hetay criptsay ailedfay."
+
+    # _errorhandling.rpym:615
+    old "Open Parse Errors"
+    new "Penoay Arsepay Rrorseay"
+
+    # _errorhandling.rpym:617
+    old "Opens the errors.txt file in a text editor."
+    new "Pensoay hetay errorsay.xttay ilefay inay aay exttay editoray."
+
+    # _errorhandling.rpym:621
+    old "Copies the errors.txt file to the clipboard."
+    new "Opiescay hetay errorsay.xttay ilefay otay hetay ipboardclay."
+
diff --git a/tutorial/game/tl/piglatin/demo_character.rpy b/tutorial/game/tl/piglatin/demo_character.rpy
new file mode 100644
index 0000000..04b5cfc
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_character.rpy
@@ -0,0 +1,133 @@
+
+# game/demo_character.rpy:45
+translate piglatin demo_character_16897d85:
+
+    # e "The Character object is used to declare characters, and it can also be used to customize the way in which a character speaks."
+    e "Hetay Haractercay objectay isay useday otay eclareday aracterschay, anday itay ancay alsoay ebay useday otay ustomizecay hetay ayway inay hichway aay aracterchay peakssay."
+
+# game/demo_character.rpy:47
+translate piglatin demo_character_7ad48073:
+
+    # e "By supplying it with the appropriate arguments, we can really change around the feel of the game."
+    e "Ybay upplyingsay itay ithway hetay appropriateay argumentsay, eway ancay eallyray angechay arounday hetay eelfay ofay hetay amegay."
+
+# game/demo_character.rpy:49
+translate piglatin demo_character_6fc5bef5:
+
+    # e "In this section, we'll demonstrate some of what can be accomplished by customizing character objects."
+    e "Niay histay ectionsay, eway'llay emonstrateday omesay ofay hatway ancay ebay accomplisheday ybay ustomizingcay aracterchay objectsay."
+
+# game/demo_character.rpy:51
+translate piglatin demo_character_2edcd1df:
+
+    # equote "By supplying what_prefix and what_suffix arguments to a Character object, we can automatically add things before each line of text."
+    equote "Ybay upplyingsay hat_prefixway anday hat_suffixway argumentsay otay aay Haractercay objectay, eway ancay automaticallyay adday hingstay eforebay eachay inelay ofay exttay."
+
+# game/demo_character.rpy:53
+translate piglatin demo_character_3ba649df:
+
+    # equote "This is a lot easier than having to put those quotes in by hand."
+    equote "Histay isay aay otlay easieray hantay avinghay otay utpay hosetay uotesqay inay ybay andhay."
+
+# game/demo_character.rpy:55
+translate piglatin demo_character_48dc5333:
+
+    # equote "We can also use who_prefix and who_suffix to add text to the name of the speaker."
+    equote "Eway ancay alsoay useay ho_prefixway anday ho_suffixway otay adday exttay otay hetay amenay ofay hetay peakersay."
+
+# game/demo_character.rpy:57
+translate piglatin demo_character_77ce5256:
+
+    # e "We can also supply arguments to the Character object that customize the look of the character name, the text that is being said, and the window itself."
+    e "Eway ancay alsoay upplysay argumentsay otay hetay Haractercay objectay hattay ustomizecay hetay ooklay ofay hetay aracterchay amenay, hetay exttay hattay isay eingbay aidsay, anday hetay indowway itselfay."
+
+# game/demo_character.rpy:59
+translate piglatin demo_character_fceb39fb:
+
+    # eweird "These can really change the look of the game."
+    eweird "Hesetay ancay eallyray angechay hetay ooklay ofay hetay amegay."
+
+# game/demo_character.rpy:61
+translate piglatin demo_character_92ae524c:
+
+    # eside "A more practical use of that is in conjunction with show_side_image, which lets us position an image next to the text."
+    eside "Aay oremay racticalpay useay ofay hattay isay inay onjunctioncay ithway ow_side_imageshay, hichway etslay usay ositionpay anay imageay extnay otay hetay exttay."
+
+# game/demo_character.rpy:63
+translate piglatin demo_character_ba09ee13:
+
+    # etwo "There's also show_two_window, which puts the character's name in its own window."
+    etwo "Heretay'say alsoay ow_two_windowshay, hichway utspay hetay aracterchay'say amenay inay itsay ownay indowway."
+
+# game/demo_character.rpy:65
+translate piglatin demo_character_91f8f1cc:
+
+    # ectc "Finally, we demonstrate a click to continue indicator. In this example, it's nestled in with the text."
+    ectc "Inallyfay, eway emonstrateday aay ickclay otay ontinuecay indicatoray. Niay histay exampleay, itay'say estlednay inay ithway hetay exttay."
+
+# game/demo_character.rpy:67
+translate piglatin demo_character_90e5383f:
+
+    # ectcf "A click to continue image can also be placed at a fixed location on the screen."
+    ectcf "Aay ickclay otay ontinuecay imageay ancay alsoay ebay acedplay atay aay ixedfay ocationlay onay hetay creensay."
+
+# game/demo_character.rpy:69
+translate piglatin demo_character_4a210bad:
+
+    # e "There's a lot more you can do with Character, as it lets you set style properties on all of the displayed text."
+    e "Heretay'say aay otlay oremay ouyay ancay oday ithway Haractercay, asay itay etslay ouyay etsay ylestay ropertiespay onay allay ofay hetay isplayedday exttay."
+
+# game/demo_character.rpy:71
+translate piglatin demo_character_0393756f:
+
+    # e "Finally, let me point out a couple of special characters we pre-define."
+    e "Inallyfay, etlay emay ointpay outay aay ouplecay ofay pecialsay aracterschay eway repay-efineday."
+
+# game/demo_character.rpy:76
+translate piglatin demo_character_29688b7c:
+
+    # centered "The \"centered\" character shows text at the center of the screen, without a window."
+    centered "Hetay \"enteredcay\" aracterchay owsshay exttay atay hetay entercay ofay hetay creensay, ithoutway aay indowway."
+
+# game/demo_character.rpy:78
+translate piglatin demo_character_496243d7:
+
+    # centered "It's just a highly customized normal character, that's useful for dates and titles."
+    centered "Tiay'say ustjay aay ighlyhay ustomizedcay ormalnay aracterchay, hattay'say usefulay orfay atesday anday itlestay."
+
+# game/demo_character.rpy:83
+translate piglatin demo_character_e79e9042:
+
+    # e "The \"extend\" character is very special."
+    e "Hetay \"extenday\" aracterchay isay eryvay pecialsay."
+
+# game/demo_character.rpy:85
+translate piglatin demo_character_0b55b872:
+
+    # e "It lets you"
+    e "Tiay etslay ouyay"
+
+# game/demo_character.rpy:89
+translate piglatin demo_character_7c80c8fc:
+
+    # extend " extend the previous dialogue"
+    extend " extenday hetay reviouspay ialogueday"
+
+# game/demo_character.rpy:93
+translate piglatin demo_character_645bb443:
+
+    # extend " with additional text."
+    extend " ithway additionalay exttay."
+
+# game/demo_character.rpy:95
+translate piglatin demo_character_170d938b:
+
+    # e "That lets you have things happen in the middle of text. If you didn't notice, I was changing my expression."
+    e "Hattay etslay ouyay avehay hingstay appenhay inay hetay iddlemay ofay exttay. Fiay ouyay idnday'tay oticenay, Iay asway angingchay ymay expressionay."
+
+# game/demo_character.rpy:97
+translate piglatin demo_character_4adb20a9:
+
+    # e "Hopefully, these characters, along with the ones you define, will lead to a very expressive game."
+    e "Opefullyhay, hesetay aracterschay, alongay ithway hetay onesay ouyay efineday, illway eadlay otay aay eryvay expressiveay amegay."
+
diff --git a/tutorial/game/tl/piglatin/demo_dynamic.rpy b/tutorial/game/tl/piglatin/demo_dynamic.rpy
new file mode 100644
index 0000000..85840f8
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_dynamic.rpy
@@ -0,0 +1,19 @@
+
+# game/demo_dynamic.rpy:27
+translate piglatin demo_dynamic_b72548ea:
+
+    # e "The DynamicDisplayable function lets you change what's displayed over the course of an interaction."
+    e "Hetay Ynamicdisplayableday unctionfay etslay ouyay angechay hatway'say isplayedday overay hetay oursecay ofay anay interactionay."
+
+# game/demo_dynamic.rpy:31
+translate piglatin demo_dynamic_0276dbb9:
+
+    # e "This makes it possible to display things like countdown timers and progress bars."
+    e "Histay akesmay itay ossiblepay otay isplayday hingstay ikelay ountdowncay imerstay anday rogresspay arsbay."
+
+# game/demo_dynamic.rpy:33
+translate piglatin demo_dynamic_4cabf539:
+
+    # e "Remember, people read at different speeds, so it's probably better to use this for flavor, rather then to make games time-sensitive."
+    e "Ememberray, eoplepay eadray atay ifferentday peedssay, osay itay'say robablypay etterbay otay useay histay orfay avorflay, atherray hentay otay akemay amesgay imetay-ensitivesay."
+
diff --git a/tutorial/game/tl/piglatin/demo_imageops.rpy b/tutorial/game/tl/piglatin/demo_imageops.rpy
new file mode 100644
index 0000000..b5591fa
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_imageops.rpy
@@ -0,0 +1,181 @@
+
+# game/demo_imageops.rpy:69
+translate piglatin demo_imageops_0e0e59e0:
+
+    # e "Image operations allow us to manipulate images as they are loaded in."
+    e "Mageiay operationsay alloway usay otay anipulatemay imagesay asay heytay areay oadedlay inay."
+
+# game/demo_imageops.rpy:71
+translate piglatin demo_imageops_2dfc0c2e:
+
+    # e "They're efficient, as they are only evaluated when an image is first loaded."
+    e "Heytay'eray efficientay, asay heytay areay onlyay evaluateday henway anay imageay isay irstfay oadedlay."
+
+# game/demo_imageops.rpy:73
+translate piglatin demo_imageops_9ee5a075:
+
+    # e "This way, there's no extra work that needs to be done when each frame is drawn to the screen."
+    e "Histay ayway, heretay'say onay extraay orkway hattay eedsnay otay ebay oneday henway eachay amefray isay rawnday otay hetay creensay."
+
+# game/demo_imageops.rpy:80
+translate piglatin demo_imageops_3f73f4c2:
+
+    # e "Let me show you a test image, the Ren'Py logo."
+    e "Etlay emay owshay ouyay aay esttay imageay, hetay Enray'Ypay ogolay."
+
+# game/demo_imageops.rpy:82
+translate piglatin demo_imageops_e3887927:
+
+    # e "We'll be applying some image operations to it, to see how they can be used."
+    e "Eway'llay ebay applyingay omesay imageay operationsay otay itay, otay eesay owhay heytay ancay ebay useday."
+
+# game/demo_imageops.rpy:87
+translate piglatin demo_imageops_d05ba9d9:
+
+    # e "The im.Crop operation can take the image, and chop it up into a smaller image."
+    e "Hetay imay.Ropcay operationay ancay aketay hetay imageay, anday opchay itay upay intoay aay mallersay imageay."
+
+# game/demo_imageops.rpy:92
+translate piglatin demo_imageops_f57f6496:
+
+    # e "The im.Composite operation lets us take multiple images, and draw them into a single image."
+    e "Hetay imay.Ompositecay operationay etslay usay aketay ultiplemay imagesay, anday rawday hemtay intoay aay inglesay imageay."
+
+# game/demo_imageops.rpy:94
+translate piglatin demo_imageops_634bc9da:
+
+    # e "While you can do this by showing multiple images, this is often more efficient."
+    e "Hileway ouyay ancay oday histay ybay owingshay ultiplemay imagesay, histay isay oftenay oremay efficientay."
+
+# game/demo_imageops.rpy:99
+translate piglatin demo_imageops_3a9392e4:
+
+    # e "There's also LiveComposite, which is less efficent, but allows for animation."
+    e "Heretay'say alsoay Ivecompositelay, hichway isay esslay efficentay, utbay allowsay orfay animationay."
+
+# game/demo_imageops.rpy:101
+translate piglatin demo_imageops_aab0c08f:
+
+    # e "It isn't really an image operation, but we don't know where else to put it."
+    e "Tiay isnay'tay eallyray anay imageay operationay, utbay eway onday'tay nowkay hereway elseay otay utpay itay."
+
+# game/demo_imageops.rpy:106
+translate piglatin demo_imageops_23cd24da:
+
+    # e "The im.Scale operation lets us scale an image to a particular size."
+    e "Hetay imay.Calesay operationay etslay usay calesay anay imageay otay aay articularpay izesay."
+
+# game/demo_imageops.rpy:111
+translate piglatin demo_imageops_dcaf5d6b:
+
+    # e "im.FactorScale lets us do the same thing, except to a factor of the original size."
+    e "imay.Actorscalefay etslay usay oday hetay amesay hingtay, exceptay otay aay actorfay ofay hetay originalay izesay."
+
+# game/demo_imageops.rpy:116
+translate piglatin demo_imageops_eeaec24a:
+
+    # e "The im.Map operation lets us mess with the red, green, blue, and alpha channels of an image."
+    e "Hetay imay.Apmay operationay etslay usay essmay ithway hetay edray, eengray, ueblay, anday alphaay annelschay ofay anay imageay."
+
+# game/demo_imageops.rpy:118
+translate piglatin demo_imageops_a2ed064d:
+
+    # e "In this case, we removed all the red from the image, leaving only the blue and green channels."
+    e "Niay histay asecay, eway emovedray allay hetay edray omfray hetay imageay, eavinglay onlyay hetay ueblay anday eengray annelschay."
+
+# game/demo_imageops.rpy:125
+translate piglatin demo_imageops_77b0a263:
+
+    # e "The im.Recolor operation can do the same thing, but is more efficient when we're linearly mapping colors."
+    e "Hetay imay.Ecolorray operationay ancay oday hetay amesay hingtay, utbay isay oremay efficientay henway eway'eray inearlylay appingmay olorscay."
+
+# game/demo_imageops.rpy:130
+translate piglatin demo_imageops_360723bc:
+
+    # e "The im.Twocolor operation lets you take a black and white image, like this one..."
+    e "Hetay imay.Wocolortay operationay etslay ouyay aketay aay ackblay anday hiteway imageay, ikelay histay oneay..."
+
+# game/demo_imageops.rpy:135
+translate piglatin demo_imageops_0948998c:
+
+    # e "... and assign colors to replace black and white."
+    e "... anday assignay olorscay otay eplaceray ackblay anday hiteway."
+
+# game/demo_imageops.rpy:140
+translate piglatin demo_imageops_75522403:
+
+    # e "The im.MatrixColor operation lets you use a matrix to alter the colors. With the right matrix, you can desaturate colors..."
+    e "Hetay imay.Atrixcolormay operationay etslay ouyay useay aay atrixmay otay alteray hetay olorscay. Ithway hetay ightray atrixmay, ouyay ancay esaturateday olorscay..."
+
+# game/demo_imageops.rpy:145
+translate piglatin demo_imageops_6fe260b9:
+
+    # e "... tint the image blue..."
+    e "... inttay hetay imageay ueblay..."
+
+# game/demo_imageops.rpy:150
+translate piglatin demo_imageops_85c10beb:
+
+    # e "... rotate the hue... "
+    e "... otateray hetay uehay... "
+
+# game/demo_imageops.rpy:155
+translate piglatin demo_imageops_09d2d97f:
+
+    # e "... or invert the colors, for a kinda scary look."
+    e "... oray invertay hetay olorscay, orfay aay indakay carysay ooklay."
+
+# game/demo_imageops.rpy:160
+translate piglatin demo_imageops_6dd8f586:
+
+    # e "It can even adjust brightness and contrast."
+    e "Tiay ancay evenay adjustay ightnessbray anday ontrastcay."
+
+# game/demo_imageops.rpy:162
+translate piglatin demo_imageops_ba8ddf3e:
+
+    # e "We've made some of the most common matrices into image operators."
+    e "Eway'evay ademay omesay ofay hetay ostmay ommoncay atricesmay intoay imageay operatorsay."
+
+# game/demo_imageops.rpy:167
+translate piglatin demo_imageops_4c62de6f:
+
+    # e "im.Grayscale can make an image grayscale..."
+    e "imay.Rayscalegay ancay akemay anay imageay ayscalegray..."
+
+# game/demo_imageops.rpy:172
+translate piglatin demo_imageops_7d471e4b:
+
+    # e "... while im.Sepia can sepia-tone an image."
+    e "... hileway imay.Epiasay ancay epiasay-onetay anay imageay."
+
+# game/demo_imageops.rpy:179
+translate piglatin demo_imageops_59ca3a66:
+
+    # e "The im.Alpha operation can adjust the alpha channel on an image, making things partially transparent."
+    e "Hetay imay.Lphaaay operationay ancay adjustay hetay alphaay annelchay onay anay imageay, akingmay hingstay artiallypay ansparenttray."
+
+# game/demo_imageops.rpy:184
+translate piglatin demo_imageops_514a55db:
+
+    # e "It's useful if a character just happens to be ghost."
+    e "Tiay'say usefulay ifay aay aracterchay ustjay appenshay otay ebay hostgay."
+
+# game/demo_imageops.rpy:190
+translate piglatin demo_imageops_05fc1200:
+
+    # e "But that isn't the case with me."
+    e "Utbay hattay isnay'tay hetay asecay ithway emay."
+
+# game/demo_imageops.rpy:197
+translate piglatin demo_imageops_cf7fbb57:
+
+    # e "Finally, there's im.Flip, which can flip an image horizontally or vertically."
+    e "Inallyfay, heretay'say imay.Lipfay, hichway ancay ipflay anay imageay orizontallyhay oray erticallyvay."
+
+# game/demo_imageops.rpy:199
+translate piglatin demo_imageops_49161c26:
+
+    # e "I think the less I say about this, the better."
+    e "Iay hinktay hetay esslay Iay aysay aboutay histay, hetay etterbay."
+
diff --git a/tutorial/game/tl/piglatin/demo_layers.rpy b/tutorial/game/tl/piglatin/demo_layers.rpy
new file mode 100644
index 0000000..a804067
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_layers.rpy
@@ -0,0 +1,67 @@
+
+# game/demo_layers.rpy:15
+translate piglatin demo_layers_c4715eb5:
+
+    # e "Ren'Py lets you define layers, and show images on specific layers."
+    e "Enray'Ypay etslay ouyay efineday ayerslay, anday owshay imagesay onay pecificsay ayerslay."
+
+# game/demo_layers.rpy:26
+translate piglatin demo_layers_c385f69e:
+
+    # e "The \"onlayer\" clause of the scene, show, and hide statements lets us pick which layers the commands affect."
+    e "Hetay \"onlayeray\" auseclay ofay hetay cenesay, owshay, anday idehay atementsstay etslay usay ickpay hichway ayerslay hetay ommandscay affectay."
+
+# game/demo_layers.rpy:28
+translate piglatin demo_layers_89a87205:
+
+    # e "As you can see, layers do not have to take up the entire screen. When a layer doesn't, images are clipped to the layer."
+    e "Saay ouyay ancay eesay, ayerslay oday otnay avehay otay aketay upay hetay entireay creensay. Henway aay ayerlay oesnday'tay, imagesay areay ippedclay otay hetay ayerlay."
+
+# game/demo_layers.rpy:34
+translate piglatin demo_layers_72b6169a:
+
+    # e "The \"as\" clause lets you change the tag of an image."
+    e "Hetay \"asay\" auseclay etslay ouyay angechay hetay agtay ofay anay imageay."
+
+# game/demo_layers.rpy:43
+translate piglatin demo_layers_31adea8e:
+
+    # e "This is useful when you want to show two copies of the same image."
+    e "Histay isay usefulay henway ouyay antway otay owshay wotay opiescay ofay hetay amesay imageay."
+
+# game/demo_layers.rpy:45
+translate piglatin demo_layers_2659ae91:
+
+    # e "Or if a character has a twin."
+    e "Roay ifay aay aracterchay ashay aay wintay."
+
+# game/demo_layers.rpy:56
+translate piglatin demo_layers_fa599d50:
+
+    # e "You can use \"show expression\" to show things that aren't just images, like text."
+    e "Ouyay ancay useay \"owshay expressionay\" otay owshay hingstay hattay arenay'tay ustjay imagesay, ikelay exttay."
+
+# game/demo_layers.rpy:64
+translate piglatin demo_layers_91559c86:
+
+    # e "The \"behind\" clause lets you place an image behind another."
+    e "Hetay \"ehindbay\" auseclay etslay ouyay aceplay anay imageay ehindbay anotheray."
+
+# game/demo_layers.rpy:77
+translate piglatin demo_layers_a983efbd:
+
+    # e "Finally, the \"show layer\" statement allows you to apply a transform to an entire layer."
+    e "Inallyfay, hetay \"owshay ayerlay\" atementstay allowsay ouyay otay applyay aay ansformtray otay anay entireay ayerlay."
+
+# game/demo_layers.rpy:90
+translate piglatin demo_layers_1185c462:
+
+    # e "And that's it for layers and advanced show."
+    e "Ndaay hattay'say itay orfay ayerslay anday advanceday owshay."
+
+translate piglatin strings:
+
+    # demo_layers.rpy:53
+    old "This is text."
+    new "Histay isay exttay."
+
diff --git a/tutorial/game/tl/piglatin/demo_minigame.rpy b/tutorial/game/tl/piglatin/demo_minigame.rpy
new file mode 100644
index 0000000..78c79e6
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_minigame.rpy
@@ -0,0 +1,109 @@
+
+# game/demo_minigame.rpy:204
+translate piglatin demo_minigame_03fc91ef:
+
+    # e "You may want to mix Ren'Py with other forms of gameplay. There are many ways to do this."
+    e "Ouyay aymay antway otay ixmay Enray'Ypay ithway otheray ormsfay ofay ameplaygay. Heretay areay anymay aysway otay oday histay."
+
+# game/demo_minigame.rpy:206
+translate piglatin demo_minigame_8c389a44:
+
+    # e "The first is with the UI functions, which can be used to create powerful button and menu based interfaces."
+    e "Hetay irstfay isay ithway hetay Iuay unctionsfay, hichway ancay ebay useday otay reatecay owerfulpay uttonbay anday enumay asedbay interfacesay."
+
+# game/demo_minigame.rpy:208
+translate piglatin demo_minigame_0d5698fc:
+
+    # e "These are often enough for many simulation-style games."
+    e "Hesetay areay oftenay enoughay orfay anymay imulationsay-ylestay amesgay."
+
+# game/demo_minigame.rpy:210
+translate piglatin demo_minigame_abc48e39:
+
+    # e "We also have two more ways in which Ren'Py can be extended. Both require experience with Python programming, and so aren't for the faint of heart."
+    e "Eway alsoay avehay wotay oremay aysway inay hichway Enray'Ypay ancay ebay extendeday. Othbay equireray experienceay ithway Ythonpay rogrammingpay, anday osay arenay'tay orfay hetay aintfay ofay earthay."
+
+# game/demo_minigame.rpy:212
+translate piglatin demo_minigame_4d7b5701:
+
+    # e "Renpygame is a library that allows pygame games to be run inside Ren'Py."
+    e "Enpygameray isay aay ibrarylay hattay allowsay ygamepay amesgay otay ebay unray insideay Enray'Ypay."
+
+# game/demo_minigame.rpy:214
+translate piglatin demo_minigame_bb13a57e:
+
+    # e "When using renpygame, Ren'Py steps out of the way and gives you total control over the user's experience."
+    e "Henway usingay enpygameray, Enray'Ypay epsstay outay ofay hetay ayway anday ivesgay ouyay otaltay ontrolcay overay hetay useray'say experienceay."
+
+# game/demo_minigame.rpy:216
+translate piglatin demo_minigame_4f4537ea:
+
+    # e "You can get renpygame from the Frameworks page of the Ren'Py website."
+    e "Ouyay ancay etgay enpygameray omfray hetay Rameworksfay agepay ofay hetay Enray'Ypay ebsiteway."
+
+# game/demo_minigame.rpy:218
+translate piglatin demo_minigame_b2baab12:
+
+    # e "If you want to integrate your code with Ren'Py, you can write a user-defined displayable."
+    e "Fiay ouyay antway otay integrateay ouryay odecay ithway Enray'Ypay, ouyay ancay riteway aay useray-efinedday isplayableday."
+
+# game/demo_minigame.rpy:220
+translate piglatin demo_minigame_9d67e41d:
+
+    # e "User-defined displayables are somewhat more limited, but integrate better with the rest of Ren'Py."
+    e "Seruay-efinedday isplayablesday areay omewhatsay oremay imitedlay, utbay integrateay etterbay ithway hetay estray ofay Enray'Ypay."
+
+# game/demo_minigame.rpy:222
+translate piglatin demo_minigame_59b3fdfd:
+
+    # e "For example, one could support loading and saving while a user-defined displayable is shown."
+    e "Orfay exampleay, oneay ouldcay upportsay oadinglay anday avingsay hileway aay useray-efinedday isplayableday isay ownshay."
+
+# game/demo_minigame.rpy:224
+translate piglatin demo_minigame_e02e509d:
+
+    # e "Now, why don't we play some pong?"
+    e "Ownay, hyway onday'tay eway ayplay omesay ongpay?"
+
+# game/demo_minigame.rpy:246
+translate piglatin demo_minigame_pong_ce00ff63:
+
+    # e "I win!"
+    e "Iay inway!"
+
+# game/demo_minigame.rpy:250
+translate piglatin demo_minigame_pong_68c82e98:
+
+    # e "You won! Congratulations."
+    e "Ouyay onway! Ongratulationscay."
+
+# game/demo_minigame.rpy:255
+translate piglatin demo_minigame_pong_dde7e31a:
+
+    # e "Would you like to play again?" nointeract
+    e "Ouldway ouyay ikelay otay ayplay againay?" nointeract
+
+# game/demo_minigame.rpy:264
+translate piglatin demo_minigame_pong_cd12159e:
+
+    # e "Remember to be careful about putting minigames in a visual novel, since not every visual novel player wants to be good at arcade games."
+    e "Ememberray otay ebay arefulcay aboutay uttingpay inigamesmay inay aay isualvay ovelnay, incesay otnay everyay isualvay ovelnay ayerplay antsway otay ebay oodgay atay arcadeay amesgay."
+
+translate piglatin strings:
+
+    # demo_minigame.rpy:16
+    old "Player"
+    new "Layerpay"
+
+    # demo_minigame.rpy:18
+    old "Click to Begin"
+    new "Lickcay otay Eginbay"
+
+    # demo_minigame.rpy:255
+    old "Sure."
+    new "Uresay."
+
+    # demo_minigame.rpy:255
+    old "No thanks."
+    new "Onay hankstay."
+
diff --git a/tutorial/game/tl/piglatin/demo_nvlmode.rpy b/tutorial/game/tl/piglatin/demo_nvlmode.rpy
new file mode 100644
index 0000000..af5f41c
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_nvlmode.rpy
@@ -0,0 +1,125 @@
+
+# game/demo_nvlmode.rpy:14
+translate piglatin demo_nvlmode_76b2fe88:
+
+    # nvl clear
+    nvl clear
+
+# game/demo_nvlmode.rpy:17
+translate piglatin demo_nvlmode_a986703b:
+
+    # nvle "NVL-style games are games that cover the full screen with text, rather then placing it in a file at the bottom of the screen."
+    nvle "Vlnay-ylestay amesgay areay amesgay hattay overcay hetay ullfay creensay ithway exttay, atherray hentay acingplay itay inay aay ilefay atay hetay ottombay ofay hetay creensay."
+
+# game/demo_nvlmode.rpy:19
+translate piglatin demo_nvlmode_37fd9ceb:
+
+    # nvle "Ren'Py ships with a file, nvl_mode.rpy, that implements NVL-style games. You're seeing an example of NVL-mode at work."
+    nvle "Enray'Ypay ipsshay ithway aay ilefay, vl_modenay.pyray, hattay implementsay Vlnay-ylestay amesgay. Ouyay'eray eeingsay anay exampleay ofay Vlnay-odemay atay orkway."
+
+# game/demo_nvlmode.rpy:21
+translate piglatin demo_nvlmode_66cbcf75:
+
+    # nvl clear
+    # nvle "To use NVL-mode, you need to define Characters with a kind=nvl."
+    nvl clear
+    nvle "Otay useay Vlnay-odemay, ouyay eednay otay efineday Haracterscay ithway aay indkay=vlnay."
+
+# game/demo_nvlmode.rpy:25
+translate piglatin demo_nvlmode_ad2b8b67:
+
+    # nvle "You use 'nvl clear' to clear the screen when that becomes necessary."
+    nvle "Ouyay useay 'vlnay earclay' otay earclay hetay creensay henway hattay ecomesbay ecessarynay."
+
+# game/demo_nvlmode.rpy:30
+translate piglatin demo_nvlmode_390a4eb1:
+
+    # nvle "The 'nvl show' and 'nvl hide' statements use transitions to show and hide the NVL window."
+    nvle "Hetay 'vlnay owshay' anday 'vlnay idehay' atementsstay useay ansitionstray otay owshay anday idehay hetay Vlnay indowway."
+
+# game/demo_nvlmode.rpy:32
+translate piglatin demo_nvlmode_74454519:
+
+    # nvle "The nvl_erase function removes a line from the screen."
+    nvle "Hetay vl_erasenay unctionfay emovesray aay inelay omfray hetay creensay."
+
+# game/demo_nvlmode.rpy:36
+translate piglatin demo_nvlmode_5e97d841:
+
+    # nvle "Like that."
+    nvle "Ikelay hattay."
+
+# game/demo_nvlmode.rpy:43
+translate piglatin demo_nvlmode_ea2d8a07:
+
+    # nvle "The nvl_mode also supports showing menus to the user, provided they are the last thing on the screen. Understand?" nointeract
+    nvle "Hetay vl_modenay alsoay upportssay owingshay enusmay otay hetay useray, rovidedpay heytay areay hetay astlay hingtay onay hetay creensay. Nderstanduay?" nointeract
+
+# game/demo_nvlmode.rpy:49
+translate piglatin demo_nvlmode_0f2b7d59:
+
+    # nvl clear
+    # nvle "Good!"
+    nvl clear
+    nvle "Oodgay!"
+
+# game/demo_nvlmode.rpy:53
+translate piglatin demo_nvlmode_76b2fe88_1:
+
+    # nvl clear
+    nvl clear
+
+# game/demo_nvlmode.rpy:57
+translate piglatin demo_nvlmode_b64ad3b1:
+
+    # nvl clear
+    # nvle "Well, it might help if you take a look at the demo code."
+    nvl clear
+    nvle "Ellway, itay ightmay elphay ifay ouyay aketay aay ooklay atay hetay emoday odecay."
+
+# game/demo_nvlmode.rpy:61
+translate piglatin demo_nvlmode_76b2fe88_2:
+
+    # nvl clear
+    nvl clear
+
+# game/demo_nvlmode.rpy:63
+translate piglatin demo_nvlmode_edb031ab:
+
+    # eside "You can specify transitions that occur when going from NVL-mode to ADV-mode."
+    eside "Ouyay ancay pecifysay ansitionstray hattay occuray henway oinggay omfray Vlnay-odemay otay Dvaay-odemay."
+
+# game/demo_nvlmode.rpy:65
+translate piglatin demo_nvlmode_d43b28d1:
+
+    # nvle "As well as when going from ADV-mode to NVL-mode."
+    nvle "Saay ellway asay henway oinggay omfray Dvaay-odemay otay Vlnay-odemay."
+
+# game/demo_nvlmode.rpy:67
+translate piglatin demo_nvlmode_f056c7ad:
+
+    # nvle "Text tags like {{w}{w} work in NVL-mode."
+    nvle "Exttay agstay ikelay {{}way{w} orkway inay Vlnay-odemay."
+
+# game/demo_nvlmode.rpy:69
+translate piglatin demo_nvlmode_750cd9a1:
+
+    # extend " As does the \"extend\" special character."
+    extend " Saay oesday hetay \"extenday\" pecialsay aracterchay."
+
+# game/demo_nvlmode.rpy:71
+translate piglatin demo_nvlmode_146d840b:
+
+    # nvle "And that's it for NVL-mode."
+    nvle "Ndaay hattay'say itay orfay Vlnay-odemay."
+
+translate piglatin strings:
+
+    # demo_nvlmode.rpy:43
+    old "Yes."
+    new "Esyay."
+
+    # demo_nvlmode.rpy:43
+    old "No."
+    new "Onay."
+
diff --git a/tutorial/game/tl/piglatin/demo_persistent.rpy b/tutorial/game/tl/piglatin/demo_persistent.rpy
new file mode 100644
index 0000000..f0466cb
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_persistent.rpy
@@ -0,0 +1,37 @@
+
+# game/demo_persistent.rpy:6
+translate piglatin demo_persistent_abef5d83:
+
+    # "Ren'Py supports per-game and multi-game persistent data."
+    "Enray'Ypay upportssay erpay-amegay anday ultimay-amegay ersistentpay ataday."
+
+# game/demo_persistent.rpy:8
+translate piglatin demo_persistent_539955e4:
+
+    # "Persistent data can store flags and other per-game information that should be shared between plays of a single game."
+    "Ersistentpay ataday ancay orestay agsflay anday otheray erpay-amegay informationay hattay ouldshay ebay aredshay etweenbay aysplay ofay aay inglesay amegay."
+
+# game/demo_persistent.rpy:19
+translate piglatin demo_persistent_c8164f03:
+
+    # "For example, I can tell you that you've see this line [plays] time(s) since you cleared the per-game persistent data."
+    "Orfay exampleay, Iay ancay elltay ouyay hattay ouyay'evay eesay histay inelay [plays] imetay(say) incesay ouyay earedclay hetay erpay-amegay ersistentpay ataday."
+
+# game/demo_persistent.rpy:21
+translate piglatin demo_persistent_54bc6648:
+
+    # "Multipersistent data is shared between games, which lets one game unlock features in a second."
+    "Ultipersistentmay ataday isay aredshay etweenbay amesgay, hichway etslay oneay amegay unlockay eaturesfay inay aay econdsay."
+
+# game/demo_persistent.rpy:23
+translate piglatin demo_persistent_4ff5d824:
+
+    # "A sequel might play differently if the player has beaten the first game."
+    "Aay equelsay ightmay ayplay ifferentlyday ifay hetay ayerplay ashay eatenbay hetay irstfay amegay."
+
+# game/demo_persistent.rpy:35
+translate piglatin demo_persistent_634f6d6d:
+
+    # "According to the multipersistent data, you've seen this line [plays] times total."
+    "Ccordingaay otay hetay ultipersistentmay ataday, ouyay'evay eensay histay inelay [plays] imestay otaltay."
+
diff --git a/tutorial/game/tl/piglatin/demo_text.rpy b/tutorial/game/tl/piglatin/demo_text.rpy
new file mode 100644
index 0000000..264976b
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_text.rpy
@@ -0,0 +1,187 @@
+
+# game/demo_text.rpy:65
+translate piglatin demo_text_ff47a1f2:
+
+    # e "Ren'Py gives you quite a bit of control over how text appears."
+    e "Enray'Ypay ivesgay ouyay uiteqay aay itbay ofay ontrolcay overay owhay exttay appearsay."
+
+# game/demo_text.rpy:67
+translate piglatin demo_text_ab9b2f08:
+
+    # e "Text tags let us control the appearance of text that is shown to the user."
+    e "Exttay agstay etlay usay ontrolcay hetay appearanceay ofay exttay hattay isay ownshay otay hetay useray."
+
+# game/demo_text.rpy:69
+translate piglatin demo_text_12663c84:
+
+    # e "Text tags can make text {b}bold{/b}, {i}italic{/i}, {s}struckthrough{/s}, or {u}underlined{/u}."
+    e "Exttay agstay ancay akemay exttay {b}oldbay{/b}, {i}italicay{/i}, {s}ruckthroughstay{/s}, oray {u}underlineday{/u}."
+
+# game/demo_text.rpy:71
+translate piglatin demo_text_bdfcba5a:
+
+    # e "They can make the font size {size=+12}bigger{/size} or {size=-8}smaller{/size}."
+    e "Heytay ancay akemay hetay ontfay izesay {size=+12}iggerbay{/size} oray {size=-8}mallersay{/size}."
+
+# game/demo_text.rpy:73
+translate piglatin demo_text_4230bb93:
+
+    # e "They let you pause{w} the display of the text, optionally with{p}line breaks."
+    e "Heytay etlay ouyay ausepay{w} hetay isplayday ofay hetay exttay, optionallyay ithway{p}inelay eaksbray."
+
+# game/demo_text.rpy:75
+translate piglatin demo_text_e8aec30a:
+
+    # e "They let you include images inside text{image=exclamation.png} Neat{image=exclamation.png}"
+    e "Heytay etlay ouyay includeay imagesay insideay exttay{image=exclamation.png} Eatnay{image=exclamation.png}"
+
+# game/demo_text.rpy:77
+translate piglatin demo_text_b647b4d4:
+
+    # e "We can pause the text for a short time, and have it auto-advance.{w=1} Just like that."
+    e "Eway ancay ausepay hetay exttay orfay aay ortshay imetay, anday avehay itay autoay-advanceay.{w=1} Ustjay ikelay hattay."
+
+# game/demo_text.rpy:79
+translate piglatin demo_text_90c83bb6:
+
+    # eslow "We can even have the text auto-advance,{nw}"
+    eslow "Eway ancay evenay avehay hetay exttay autoay-advanceay,{nw}"
+
+# game/demo_text.rpy:82
+translate piglatin demo_text_a134abb3:
+
+    # extend " when we reach the end of a block of text, in slow text mode."
+    extend " henway eway eachray hetay enday ofay aay ockblay ofay exttay, inay owslay exttay odemay."
+
+# game/demo_text.rpy:84
+translate piglatin demo_text_d2b1ebbe:
+
+    # e "They can change the {color=#f00}color{/color} {color=#ff0}of{/color} {color=#0f0}the{/color} {color=#0ff}text{/color}."
+    e "Heytay ancay angechay hetay {color=#f00}olorcay{/color} {color=#ff0}ofay{/color} {color=#0f0}hetay{/color} {color=#0ff}exttay{/color}."
+
+# game/demo_text.rpy:88
+translate piglatin demo_text_6d050f89:
+
+    # e "The kerning tag lets you adjust the spacing between characters.\n{k=.5}The spacing between characters can be increased.{/k}\n{k=-.5}The spacing between characters can be decreased.{/k}"
+    e "Hetay erningkay agtay etslay ouyay adjustay hetay pacingsay etweenbay aracterschay.\n{k=.5}Hetay pacingsay etweenbay aracterschay ancay ebay increaseday.{/k}\n{k=-.5}Hetay pacingsay etweenbay aracterschay ancay ebay ecreasedday.{/k}"
+
+# game/demo_text.rpy:90
+translate piglatin demo_text_e8835287:
+
+    # eruby "You are able to write ruby text, which can help clarify how to pronounce words, like {rb}Ren'Py{/rb}{rt}ren-pie{/rt}."
+    eruby "Ouyay areay ableay otay riteway ubyray exttay, hichway ancay elphay arifyclay owhay otay ronouncepay ordsway, ikelay {rb}Enray'Ypay{/rb}{rt}enray-iepay{/rt}."
+
+# game/demo_text.rpy:92
+translate piglatin demo_text_6e1b95f0:
+
+    # e "{a=define_hyperlink}Hyperlinks{/a} let buttons be defined using text tags."
+    e "{a=define_hyperlink}Yperlinkshay{/a} etlay uttonsbay ebay efinedday usingay exttay agstay."
+
+# game/demo_text.rpy:94
+translate piglatin demo_text_245e745a:
+
+    # e "The space and vspace tags add {space=30} horizontal and {vspace=20}vertical space, respectively."
+    e "Hetay pacesay anday spacevay agstay adday {space=30} orizontalhay anday {vspace=20}erticalvay pacesay, espectivelyray."
+
+# game/demo_text.rpy:96
+translate piglatin demo_text_362f67bb:
+
+    # e "You can define your own text tags, {=pink}that use a style you define.{/=pink}"
+    e "Ouyay ancay efineday ouryay ownay exttay agstay, {=pink}hattay useay aay ylestay ouyay efineday.{/=pink}"
+
+# game/demo_text.rpy:98
+translate piglatin demo_text_9225af3b:
+
+    # e "If you find yourself using text tags on every line, you should probably look at style properties instead."
+    e "Fiay ouyay indfay ourselfyay usingay exttay agstay onay everyay inelay, ouyay ouldshay robablypay ooklay atay ylestay ropertiespay insteaday."
+
+# game/demo_text.rpy:100
+translate piglatin demo_text_3b409933:
+
+    # e "Used with care, text tags can enhance {b}your{/b} game."
+    e "Seduay ithway arecay, exttay agstay ancay enhanceay {b}ouryay{/b} amegay."
+
+# game/demo_text.rpy:102
+translate piglatin demo_text_fcb34ec8:
+
+    # e "{u}Used{/u} with {i}abandon,{/i} they {b}can{/b} make {b}your{/b} game {color=#333}hard{/color} {color=#888}to{/color} {color=#ccc}read{/color}."
+    e "{u}Seduay{/u} ithway {i}abandonay,{/i} heytay {b}ancay{/b} akemay {b}ouryay{/b} amegay {color=#333}ardhay{/color} {color=#888}otay{/color} {color=#ccc}eadray{/color}."
+
+# game/demo_text.rpy:104
+translate piglatin demo_text_3154619a:
+
+    # e "With great power comes great responsibility, after all."
+    e "Ithway eatgray owerpay omescay eatgray esponsibilityray, afteray allay."
+
+# game/demo_text.rpy:106
+translate piglatin demo_text_12873855:
+
+    # e "And we want to give you all the power you need."
+    e "Ndaay eway antway otay ivegay ouyay allay hetay owerpay ouyay eednay."
+
+# game/demo_text.rpy:108
+translate piglatin demo_text_63b9c010:
+
+    # e "There are a couple of text adjustments that don't correspond to text tags."
+    e "Heretay areay aay ouplecay ofay exttay adjustmentsay hattay onday'tay orrespondcay otay exttay agstay."
+
+# game/demo_text.rpy:110
+translate piglatin demo_text_1a6f274c:
+
+    # eoutline "The outlines setting lets you put outlines around the text."
+    eoutline "Hetay outlinesay ettingsay etslay ouyay utpay outlinesay arounday hetay exttay."
+
+# game/demo_text.rpy:112
+translate piglatin demo_text_c130dcd4:
+
+    # eoutline "You can have more than one outline, and each has its own color and offset."
+    eoutline "Ouyay ancay avehay oremay hantay oneay outlineay, anday eachay ashay itsay ownay olorcay anday offsetay."
+
+# game/demo_text.rpy:116
+translate piglatin demo_text_9eb0448e:
+
+    # esubtitle "Here, we have two outlines around the white text."
+    esubtitle "Erehay, eway avehay wotay outlinesay arounday hetay hiteway exttay."
+
+# game/demo_text.rpy:118
+translate piglatin demo_text_eb22992d:
+
+    # esubtitle "The bottom one is a translucent black that's offset a little, while the top one is green."
+    esubtitle "Hetay ottombay oneay isay aay anslucenttray ackblay hattay'say offsetay aay ittlelay, hileway hetay optay oneay isay eengray."
+
+# game/demo_text.rpy:120
+translate piglatin demo_text_7067acb5:
+
+    # esubtitle "By hiding the window and adjusting the layout method, we are able to create reasonable subtitles."
+    esubtitle "Ybay idinghay hetay indowway anday adjustingay hetay ayoutlay ethodmay, eway areay ableay otay reatecay easonableray ubtitlessay."
+
+# game/demo_text.rpy:122
+translate piglatin demo_text_123ff836:
+
+    # esubtitle "This might be an interesting look for a game."
+    esubtitle "Histay ightmay ebay anay interestingay ooklay orfay aay amegay."
+
+# game/demo_text.rpy:126
+translate piglatin demo_text_d742e133:
+
+    # esfont "For even more control, Ren'Py supports SFonts, image files containing font information."
+    esfont "Orfay evenay oremay ontrolcay, Enray'Ypay upportssay Fontssay, imageay ilesfay ontainingcay ontfay informationay."
+
+# game/demo_text.rpy:128
+translate piglatin demo_text_2a8833c0:
+
+    # esfont "SFonts let you use fonts you otherwise couldn't, and apply special effects to fonts using your favorite image editor."
+    esfont "Fontssay etlay ouyay useay ontsfay ouyay otherwiseay ouldncay'tay, anday applyay pecialsay effectsay otay ontsfay usingay ouryay avoritefay imageay editoray."
+
+# game/demo_text.rpy:130
+translate piglatin demo_text_418ffc27:
+
+    # e "Well, that's it for fonts and text tags."
+    e "Ellway, hattay'say itay orfay ontsfay anday exttay agstay."
+
+# game/demo_text.rpy:138
+translate piglatin define_hyperlink_8863ed04:
+
+    # definition "A hyperlink is a button that is defined inside text, using text tags. They're ideal for including definitions of words used in the script, but they shouldn't be used in place of menus."
+    definition "Aay yperlinkhay isay aay uttonbay hattay isay efinedday insideay exttay, usingay exttay agstay. Heytay'eray idealay orfay includingay efinitionsday ofay ordsway useday inay hetay criptsay, utbay heytay ouldnshay'tay ebay useday inay aceplay ofay enusmay."
+
diff --git a/tutorial/game/tl/piglatin/demo_transform.rpy b/tutorial/game/tl/piglatin/demo_transform.rpy
new file mode 100644
index 0000000..917f8d3
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_transform.rpy
@@ -0,0 +1,61 @@
+
+# game/demo_transform.rpy:156
+translate piglatin demo_transform_f10e08f5:
+
+    # e "The Transform function allows you to rotate, zoom, move, and adjust the alpha of a displayable."
+    e "Hetay Ransformtay unctionfay allowsay ouyay otay otateray, oomzay, ovemay, anday adjustay hetay alphaay ofay aay isplayableday."
+
+# game/demo_transform.rpy:158
+translate piglatin demo_transform_295804e0:
+
+    # e "It does this under the control of a Python function, making it incredibly flexible at the cost of some complexity."
+    e "Tiay oesday histay underay hetay ontrolcay ofay aay Ythonpay unctionfay, akingmay itay incrediblyay exibleflay atay hetay ostcay ofay omesay omplexitycay."
+
+# game/demo_transform.rpy:165
+translate piglatin demo_transform_1afd3e7b:
+
+    # e "Here's a simple example, showing how we can change an image as it moves around the screen."
+    e "Erehay'say aay implesay exampleay, owingshay owhay eway ancay angechay anay imageay asay itay ovesmay arounday hetay creensay."
+
+# game/demo_transform.rpy:167
+translate piglatin demo_transform_a5427276:
+
+    # e "A nice thing about Transform is that it's \"one price\"."
+    e "Aay icenay hingtay aboutay Ransformtay isay hattay itay'say \"oneay ricepay\"."
+
+# game/demo_transform.rpy:169
+translate piglatin demo_transform_108aec8f:
+
+    # e "If you use it to do a rotation, you can zoom or adjust alpha at no additional cost."
+    e "Fiay ouyay useay itay otay oday aay otationray, ouyay ancay oomzay oray adjustay alphaay atay onay additionalay ostcay."
+
+# game/demo_transform.rpy:198
+translate piglatin demo_transform_55f784e4:
+
+    # e "As the python functions get more complicated, more advanced behavior is possible."
+    e "Saay hetay ythonpay unctionsfay etgay oremay omplicatedcay, oremay advanceday ehaviorbay isay ossiblepay."
+
+# game/demo_transform.rpy:200
+translate piglatin demo_transform_43798bbe:
+
+    # e "This can include coordinating more than one Transform."
+    e "Histay ancay includeay oordinatingcay oremay hantay oneay Ransformtay."
+
+# game/demo_transform.rpy:213
+translate piglatin demo_transform_3f4f14bb:
+
+    # e "Finally, transforms can be applied to buttons, and work even while the button is zoomed."
+    e "Inallyfay, ansformstray ancay ebay applieday otay uttonsbay, anday orkway evenay hileway hetay uttonbay isay oomedzay."
+
+# game/demo_transform.rpy:218
+translate piglatin demo_transform_a439ffaa:
+
+    # e "With a little Python code, transforms let you do a lot of things."
+    e "Ithway aay ittlelay Ythonpay odecay, ansformstray etlay ouyay oday aay otlay ofay hingstay."
+
+translate piglatin strings:
+
+    # demo_transform.rpy:211
+    old "A Working Button"
+    new "Aay Orkingway Uttonbay"
+
diff --git a/tutorial/game/tl/piglatin/demo_transitions.rpy b/tutorial/game/tl/piglatin/demo_transitions.rpy
new file mode 100644
index 0000000..dc5aeb4
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_transitions.rpy
@@ -0,0 +1,575 @@
+
+# game/demo_transitions.rpy:44
+translate piglatin demo_transitions_5bbc72fe:
+
+    # e "Ren'Py ships with a large number of built-in transitions, and also includes classes that let you define your own."
+    e "Enray'Ypay ipsshay ithway aay argelay umbernay ofay uiltbay-inay ansitionstray, anday alsoay includesay assesclay hattay etlay ouyay efineday ouryay ownay."
+
+# game/demo_transitions.rpy:46
+translate piglatin demo_transitions_menu_3caf78d3:
+
+    # e "What kind of transitions would you like demonstrated?" nointeract
+    e "Hatway indkay ofay ansitionstray ouldway ouyay ikelay emonstratedday?" nointeract
+
+# game/demo_transitions.rpy:85
+translate piglatin demo_simple_transitions_2b4fbae3:
+
+    # e "Okay, I can tell you about simple transitions. We call them simple because they don't take much in the way of configuration."
+    e "Kayoay, Iay ancay elltay ouyay aboutay implesay ansitionstray. Eway allcay hemtay implesay ecausebay heytay onday'tay aketay uchmay inay hetay ayway ofay onfigurationcay."
+
+# game/demo_transitions.rpy:87
+translate piglatin demo_simple_transitions_4b235ac2:
+
+    # e "But don't let that get you down, since they're the transitions you'll probably use the most in a game."
+    e "Utbay onday'tay etlay hattay etgay ouyay ownday, incesay heytay'eray hetay ansitionstray ouyay'llay robablypay useay hetay ostmay inay aay amegay."
+
+# game/demo_transitions.rpy:92
+translate piglatin demo_simple_transitions_af0431ac:
+
+    # e "The 'dissolve' transition is probably the most useful, blending one scene into another."
+    e "Hetay 'issolveday' ansitiontray isay robablypay hetay ostmay usefulay, endingblay oneay cenesay intoay anotheray."
+
+# game/demo_transitions.rpy:97
+translate piglatin demo_simple_transitions_5b9f711f:
+
+    # e "The 'Dissolve' function lets you create your own dissolves, taking a different amount of time."
+    e "Hetay 'Issolveday' unctionfay etslay ouyay reatecay ouryay ownay issolvesday, akingtay aay ifferentday amountay ofay imetay."
+
+# game/demo_transitions.rpy:102
+translate piglatin demo_simple_transitions_79816523:
+
+    # e "The 'fade' transition fades to black, and then fades back in to the new scene."
+    e "Hetay 'adefay' ansitiontray adesfay otay ackblay, anday hentay adesfay ackbay inay otay hetay ewnay cenesay."
+
+# game/demo_transitions.rpy:104
+translate piglatin demo_simple_transitions_141bb95d:
+
+    # e "If you're going to stay at a black screen, you'll probably want to use 'dissolve' rather than 'fade'."
+    e "Fiay ouyay'eray oinggay otay aystay atay aay ackblay creensay, ouyay'llay robablypay antway otay useay 'issolveday' atherray hantay 'adefay'."
+
+# game/demo_transitions.rpy:108
+translate piglatin demo_simple_transitions_f059f4ae:
+
+    # e "You can use 'Fade' to define your own fades. By changing the timing and the color faded to, you can use this for special effects, like flashbulbs."
+    e "Ouyay ancay useay 'Adefay' otay efineday ouryay ownay adesfay. Ybay angingchay hetay imingtay anday hetay olorcay adedfay otay, ouyay ancay useay histay orfay pecialsay effectsay, ikelay ashbulbsflay."
+
+# game/demo_transitions.rpy:113
+translate piglatin demo_simple_transitions_e948905b:
+
+    # e "The 'pixellate' transition pixellates out the old scene, switches to the new scene, and then unpixellates that."
+    e "Hetay 'ixellatepay' ansitiontray ixellatespay outay hetay olday cenesay, witchessay otay hetay ewnay cenesay, anday hentay unpixellatesay hattay."
+
+# game/demo_transitions.rpy:115
+translate piglatin demo_simple_transitions_6a1ae05f:
+
+    # e "It's probably not appropriate for most games, but we think it's kind of neat."
+    e "Tiay'say robablypay otnay appropriateay orfay ostmay amesgay, utbay eway hinktay itay'say indkay ofay eatnay."
+
+# game/demo_transitions.rpy:118
+translate piglatin demo_simple_transitions_bdfcd85a:
+
+    # e "You can use 'Pixellate' to change the details of the pixellation."
+    e "Ouyay ancay useay 'Ixellatepay' otay angechay hetay etailsday ofay hetay ixellationpay."
+
+# game/demo_transitions.rpy:120
+translate piglatin demo_simple_transitions_432f7224:
+
+    # e "Motions can also be used as transitions."
+    e "Otionsmay ancay alsoay ebay useday asay ansitionstray."
+
+# game/demo_transitions.rpy:122
+translate piglatin demo_simple_transitions_a20cefa7:
+
+    # "..."
+    "..."
+
+# game/demo_transitions.rpy:124
+translate piglatin demo_simple_transitions_0fd4d656:
+
+    # "......"
+    "......"
+
+# game/demo_transitions.rpy:129
+translate piglatin demo_simple_transitions_fbf11906:
+
+    # e "Hey! Pay attention."
+    e "Eyhay! Aypay attentionay."
+
+# game/demo_transitions.rpy:131
+translate piglatin demo_simple_transitions_51c1c5b8:
+
+    # e "I was about to demonstrate 'vpunch'... well, I guess I just did."
+    e "Iay asway aboutay otay emonstrateday 'punchvay'... ellway, Iay uessgay Iay ustjay idday."
+
+# game/demo_transitions.rpy:136
+translate piglatin demo_simple_transitions_57f19473:
+
+    # e "We can also shake the screen horizontally, with 'hpunch'. These were defined using the 'Move' function."
+    e "Eway ancay alsoay akeshay hetay creensay orizontallyhay, ithway 'punchhay'. Hesetay ereway efinedday usingay hetay 'Ovemay' unctionfay."
+
+# game/demo_transitions.rpy:138
+translate piglatin demo_simple_transitions_fce83e12:
+
+    # e "There's also the 'move' transition, which is confusingly enough defined using the 'MoveTransition' function."
+    e "Heretay'say alsoay hetay 'ovemay' ansitiontray, hichway isay onfusinglycay enoughay efinedday usingay hetay 'Ovetransitionmay' unctionfay."
+
+# game/demo_transitions.rpy:145
+translate piglatin demo_simple_transitions_1050b6a4:
+
+    # e "The 'move' transition finds images that have changed placement, and slides them to their new place. It's an easy way to get motion in your game."
+    e "Hetay 'ovemay' ansitiontray indsfay imagesay hattay avehay angedchay acementplay, anday idesslay hemtay otay heirtay ewnay aceplay. Tiay'say anay easyay ayway otay etgay otionmay inay ouryay amegay."
+
+# game/demo_transitions.rpy:147
+translate piglatin demo_simple_transitions_fbb1838e:
+
+    # e "Finally, there's 'Pause', which lets you define a transition that just waits for a given amount of time."
+    e "Inallyfay, heretay'say 'Ausepay', hichway etslay ouyay efineday aay ansitiontray hattay ustjay aitsway orfay aay ivengay amountay ofay imetay."
+
+# game/demo_transitions.rpy:149
+translate piglatin demo_simple_transitions_654a7a87:
+
+    # e "Why would you want to do that?"
+    e "Hyway ouldway ouyay antway otay oday hattay?"
+
+# game/demo_transitions.rpy:151
+translate piglatin demo_simple_transitions_3b8c0bce:
+
+    # e "It's because clicking during a sequence of transitions will skip all of the remaining transitions."
+    e "Tiay'say ecausebay ickingclay uringday aay equencesay ofay ansitionstray illway kipsay allay ofay hetay emainingray ansitionstray."
+
+# game/demo_transitions.rpy:153
+translate piglatin demo_simple_transitions_6cad71a4:
+
+    # e "Try clicking during the following transitions:"
+    e "Rytay ickingclay uringday hetay ollowingfay ansitionstray:"
+
+# game/demo_transitions.rpy:161
+translate piglatin demo_simple_transitions_c75a0d2d:
+
+    # e "Having 'Pause' makes it easy to implement skippable cut-scenes in terms of transitions."
+    e "Avinghay 'Ausepay' akesmay itay easyay otay implementay kippablesay utcay-cenessay inay ermstay ofay ansitionstray."
+
+# game/demo_transitions.rpy:163
+translate piglatin demo_simple_transitions_4632f134:
+
+    # e "Anyway, that's it for the simple transitions."
+    e "Nywayaay, hattay'say itay orfay hetay implesay ansitionstray."
+
+# game/demo_transitions.rpy:170
+translate piglatin demo_imagedissolve_transitions_2db67018:
+
+    # e "Perhaps the most flexible kind of transition is the ImageDissolve, which lets you use an image to control a dissolve."
+    e "Erhapspay hetay ostmay exibleflay indkay ofay ansitiontray isay hetay Magedissolveiay, hichway etslay ouyay useay anay imageay otay ontrolcay aay issolveday."
+
+# game/demo_transitions.rpy:172
+translate piglatin demo_imagedissolve_transitions_429f8d03:
+
+    # e "This lets us specify very complex transitions, fairly simply. Let's try some, and then I'll show you how they work."
+    e "Histay etslay usay pecifysay eryvay omplexcay ansitionstray, airlyfay implysay. Etlay'say ytray omesay, anday hentay Iay'llay owshay ouyay owhay heytay orkway."
+
+# game/demo_transitions.rpy:174
+translate piglatin demo_imagedissolve_transitions_1ce501b0:
+
+    # e "There are two ImageDissolve transitions built into Ren'Py."
+    e "Heretay areay wotay Magedissolveiay ansitionstray uiltbay intoay Enray'Ypay."
+
+# game/demo_transitions.rpy:185
+translate piglatin demo_imagedissolve_transitions_ea0413be:
+
+    # e "The 'blinds' transition opens and closes what looks like vertical blinds."
+    e "Hetay 'indsblay' ansitiontray opensay anday osesclay hatway ookslay ikelay erticalvay indsblay."
+
+# game/demo_transitions.rpy:194
+translate piglatin demo_imagedissolve_transitions_12e2e0d0:
+
+    # e "The 'squares' transition uses these squares to show things."
+    e "Hetay 'quaressay' ansitiontray usesay hesetay quaressay otay owshay hingstay."
+
+# game/demo_transitions.rpy:196
+translate piglatin demo_imagedissolve_transitions_bbf73d1c:
+
+    # e "I'm not sure why anyone would want to use it, but it was used in some translated games, so we added it."
+    e "Iay'may otnay uresay hyway anyoneay ouldway antway otay useay itay, utbay itay asway useday inay omesay anslatedtray amesgay, osay eway addeday itay."
+
+# game/demo_transitions.rpy:198
+translate piglatin demo_imagedissolve_transitions_0ab2902d:
+
+    # e "The most interesting transitions aren't in the standard library."
+    e "Hetay ostmay interestingay ansitionstray arenay'tay inay hetay andardstay ibrarylay."
+
+# game/demo_transitions.rpy:200
+translate piglatin demo_imagedissolve_transitions_54aa9bf9:
+
+    # e "These ones require an image the size of the screen, and so we couldn't include them as the size of the screen can change from game to game."
+    e "Hesetay onesay equireray anay imageay hetay izesay ofay hetay creensay, anday osay eway ouldncay'tay includeay hemtay asay hetay izesay ofay hetay creensay ancay angechay omfray amegay otay amegay."
+
+# game/demo_transitions.rpy:202
+translate piglatin demo_imagedissolve_transitions_70cfd5ed:
+
+    # e "You can click the button above to see how they are defined in the demo script."
+    e "Ouyay ancay ickclay hetay uttonbay aboveay otay eesay owhay heytay areay efinedday inay hetay emoday criptsay."
+
+# game/demo_transitions.rpy:207
+translate piglatin demo_imagedissolve_transitions_ca316184:
+
+    # e "We can hide things with a 'circleirisin'..."
+    e "Eway ancay idehay hingstay ithway aay 'ircleirisincay'..."
+
+# game/demo_transitions.rpy:212
+translate piglatin demo_imagedissolve_transitions_b8fdf2b6:
+
+    # e "... and show them again with a 'circleirisout'."
+    e "... anday owshay hemtay againay ithway aay 'ircleirisoutcay'."
+
+# game/demo_transitions.rpy:217
+translate piglatin demo_imagedissolve_transitions_ee427486:
+
+    # e "The 'circlewipe' transitions changes screens using a circular wipe effect."
+    e "Hetay 'irclewipecay' ansitionstray angeschay creenssay usingay aay ircularcay ipeway effectay."
+
+# game/demo_transitions.rpy:222
+translate piglatin demo_imagedissolve_transitions_6f089276:
+
+    # e "The 'dream' transition does this weird wavy dissolve, and does it relatively slowly."
+    e "Hetay 'reamday' ansitiontray oesday histay eirdway avyway issolveday, anday oesday itay elativelyray owlyslay."
+
+# game/demo_transitions.rpy:227
+translate piglatin demo_imagedissolve_transitions_c0b9d74d:
+
+    # e "The 'teleport' transition reveals the new scene one line at a time."
+    e "Hetay 'eleporttay' ansitiontray evealsray hetay ewnay cenesay oneay inelay atay aay imetay."
+
+# game/demo_transitions.rpy:232
+translate piglatin demo_imagedissolve_transitions_72ba11d4:
+
+    # e "This is the background picture used with the circleirisout transition."
+    e "Histay isay hetay ackgroundbay icturepay useday ithway hetay ircleirisoutcay ansitiontray."
+
+# game/demo_transitions.rpy:234
+translate piglatin demo_imagedissolve_transitions_fc3b3339:
+
+    # e "When we use an ImageDissolve, the white will dissolve in first, followed by progressively darker colors. Let's try it."
+    e "Henway eway useay anay Magedissolveiay, hetay hiteway illway issolveday inay irstfay, ollowedfay ybay rogressivelypay arkerday olorscay. Etlay'say ytray itay."
+
+# game/demo_transitions.rpy:239
+translate piglatin demo_imagedissolve_transitions_4327dca2:
+
+    # e "If we give ImageDissolve the 'reverse' parameter, black areas will dissolve in first."
+    e "Fiay eway ivegay Magedissolveiay hetay 'everseray' arameterpay, ackblay areasay illway issolveday inay irstfay."
+
+# game/demo_transitions.rpy:244
+translate piglatin demo_imagedissolve_transitions_3a401ee7:
+
+    # e "This lets circleirisin and circleirisout use the same image."
+    e "Histay etslay ircleirisincay anday ircleirisoutcay useay hetay amesay imageay."
+
+# game/demo_transitions.rpy:249
+translate piglatin demo_imagedissolve_transitions_20d9cf6c:
+
+    # e "The teleport transition uses a different image, one that dissolves things in one line at a time."
+    e "Hetay eleporttay ansitiontray usesay aay ifferentday imageay, oneay hattay issolvesday hingstay inay oneay inelay atay aay imetay."
+
+# game/demo_transitions.rpy:254
+translate piglatin demo_imagedissolve_transitions_906f7800:
+
+    # e "A dissolve only seems to affect parts of the scene that have changed..."
+    e "Aay issolveday onlyay eemssay otay affectay artspay ofay hetay cenesay hattay avehay angedchay..."
+
+# game/demo_transitions.rpy:259
+translate piglatin demo_imagedissolve_transitions_4b557a29:
+
+    # e "... which is how we apply the teleport effect to a single character."
+    e "... hichway isay owhay eway applyay hetay eleporttay effectay otay aay inglesay aracterchay."
+
+# game/demo_transitions.rpy:261
+translate piglatin demo_imagedissolve_transitions_e16f8d3a:
+
+    # e "For more examples of ImageDissolve, check out the {i}Utsukushii Effects{/i} demo."
+    e "Orfay oremay examplesay ofay Magedissolveiay, eckchay outay hetay {i}Tsukushiiuay Ffectseay{/i} emoday."
+
+# game/demo_transitions.rpy:263
+translate piglatin demo_imagedissolve_transitions_b6dbf68b:
+
+    # e "It shows how a clever game-maker can use ImageDissolve to create all sorts of effects."
+    e "Tiay owsshay owhay aay everclay amegay-akermay ancay useay Magedissolveiay otay reatecay allay ortssay ofay effectsay."
+
+# game/demo_transitions.rpy:269
+translate piglatin demo_cropmove_transitions_1711a91e:
+
+    # e "The CropMove transition class provides a wide range of transition effects. It's not used very much in practice, though."
+    e "Hetay Ropmovecay ansitiontray assclay rovidespay aay ideway angeray ofay ansitiontray effectsay. Tiay'say otnay useday eryvay uchmay inay racticepay, houghtay."
+
+# game/demo_transitions.rpy:274
+translate piglatin demo_cropmove_transitions_6d82cfd7:
+
+    # e "I'll stand offscreen, so you can see some of its modes. I'll read out the mode name after each transition."
+    e "Iay'llay andstay offscreenay, osay ouyay ancay eesay omesay ofay itsay odesmay. Iay'llay eadray outay hetay odemay amenay afteray eachay ansitiontray."
+
+# game/demo_transitions.rpy:279
+translate piglatin demo_cropmove_transitions_4427c78c:
+
+    # e "We first have wiperight..."
+    e "Eway irstfay avehay iperightway..."
+
+# game/demo_transitions.rpy:284
+translate piglatin demo_cropmove_transitions_6d1810a1:
+
+    # e "...followed by wipeleft... "
+    e "...ollowedfay ybay ipeleftway... "
+
+# game/demo_transitions.rpy:289
+translate piglatin demo_cropmove_transitions_1dd1c6a1:
+
+    # e "...wipeup..."
+    e "...ipeupway..."
+
+# game/demo_transitions.rpy:294
+translate piglatin demo_cropmove_transitions_0ea0fa83:
+
+    # e "...and wipedown."
+    e "...anday ipedownway."
+
+# game/demo_transitions.rpy:296
+translate piglatin demo_cropmove_transitions_c7cb4c16:
+
+    # e "Next, the slides."
+    e "Extnay, hetay idesslay."
+
+# game/demo_transitions.rpy:301
+translate piglatin demo_cropmove_transitions_462a442f:
+
+    # e "Slideright..."
+    e "Liderightsay..."
+
+# game/demo_transitions.rpy:306
+translate piglatin demo_cropmove_transitions_f9a2e523:
+
+    # e "...slideleft..."
+    e "...ideleftslay..."
+
+# game/demo_transitions.rpy:311
+translate piglatin demo_cropmove_transitions_20ce3e9c:
+
+    # e "...slideup..."
+    e "...ideupslay..."
+
+# game/demo_transitions.rpy:316
+translate piglatin demo_cropmove_transitions_9e00a7a6:
+
+    # e "and slidedown."
+    e "anday idedownslay."
+
+# game/demo_transitions.rpy:318
+translate piglatin demo_cropmove_transitions_b8a710c1:
+
+    # e "While the slide transitions slide in the new scene, the slideaways slide out the old scene."
+    e "Hileway hetay ideslay ansitionstray ideslay inay hetay ewnay cenesay, hetay ideawaysslay ideslay outay hetay olday cenesay."
+
+# game/demo_transitions.rpy:324
+translate piglatin demo_cropmove_transitions_1efb4cd0:
+
+    # e "Slideawayright..."
+    e "Lideawayrightsay..."
+
+# game/demo_transitions.rpy:329
+translate piglatin demo_cropmove_transitions_bfb5dfd7:
+
+    # e "...slideawayleft..."
+    e "...ideawayleftslay..."
+
+# game/demo_transitions.rpy:334
+translate piglatin demo_cropmove_transitions_6c1a4a6f:
+
+    # e "...slideawayup..."
+    e "...ideawayupslay..."
+
+# game/demo_transitions.rpy:339
+translate piglatin demo_cropmove_transitions_1f994a7b:
+
+    # e "and slideawaydown."
+    e "anday ideawaydownslay."
+
+# game/demo_transitions.rpy:341
+translate piglatin demo_cropmove_transitions_025ef723:
+
+    # e "We also have a couple of transitions that use a rectangular iris."
+    e "Eway alsoay avehay aay ouplecay ofay ansitionstray hattay useay aay ectangularray irisay."
+
+# game/demo_transitions.rpy:347
+translate piglatin demo_cropmove_transitions_d00d505e:
+
+    # e "There's irisout..."
+    e "Heretay'say irisoutay..."
+
+# game/demo_transitions.rpy:353
+translate piglatin demo_cropmove_transitions_016a1e0a:
+
+    # e "... and irisin."
+    e "... anday irisinay."
+
+# game/demo_transitions.rpy:355
+translate piglatin demo_cropmove_transitions_08d753ed:
+
+    # e "It's enough to make you feel a bit dizzy."
+    e "Tiay'say enoughay otay akemay ouyay eelfay aay itbay izzyday."
+
+# game/demo_transitions.rpy:361
+translate piglatin demo_pushmove_transitions_003e506d:
+
+    # e "The PushMove transitions use the new scene to push the old one out. Let's take a look."
+    e "Hetay Ushmovepay ansitionstray useay hetay ewnay cenesay otay ushpay hetay olday oneay outay. Etlay'say aketay aay ooklay."
+
+# game/demo_transitions.rpy:367
+translate piglatin demo_pushmove_transitions_124f375d:
+
+    # "There's pushright..."
+    "Heretay'say ushrightpay..."
+
+# game/demo_transitions.rpy:372
+translate piglatin demo_pushmove_transitions_ce380ccb:
+
+    # "...pushleft..."
+    "...ushleftpay..."
+
+# game/demo_transitions.rpy:377
+translate piglatin demo_pushmove_transitions_77629638:
+
+    # "...pushdown..."
+    "...ushdownpay..."
+
+# game/demo_transitions.rpy:383
+translate piglatin demo_pushmove_transitions_b7f33c95:
+
+    # "... and pushup. And that's it the for the PushMove-based transitions."
+    "... anday ushuppay. Ndaay hattay'say itay hetay orfay hetay Ushmovepay-asedbay ansitionstray."
+
+# game/demo_transitions.rpy:389
+translate piglatin demo_movetransition_14df0e34:
+
+    # e "The most common MoveTransition is move, which slides around images that have changed position on the screen."
+    e "Hetay ostmay ommoncay Ovetransitionmay isay ovemay, hichway idesslay arounday imagesay hattay avehay angedchay ositionpay onay hetay creensay."
+
+# game/demo_transitions.rpy:394
+translate piglatin demo_movetransition_84e40422:
+
+    # e "Just like that."
+    e "Ustjay ikelay hattay."
+
+# game/demo_transitions.rpy:396
+translate piglatin demo_movetransition_098ee9f1:
+
+    # e "There are also the moveout and movein transitions."
+    e "Heretay areay alsoay hetay oveoutmay anday oveinmay ansitionstray."
+
+# game/demo_transitions.rpy:398
+translate piglatin demo_movetransition_09748f81:
+
+    # e "The moveout transitions (moveoutleft, moveoutright, moveouttop, and moveoutbottom) slide hidden images off the appropriate side of the screen."
+    e "Hetay oveoutmay ansitionstray (oveoutleftmay, oveoutrightmay, oveouttopmay, anday oveoutbottommay) ideslay iddenhay imagesay offay hetay appropriateay idesay ofay hetay creensay."
+
+# game/demo_transitions.rpy:400
+translate piglatin demo_movetransition_5edf6007:
+
+    # e "The movein transitions (moveinleft, moveinright, moveintop, and moveinbottom) slide in new images."
+    e "Hetay oveinmay ansitionstray (oveinleftmay, oveinrightmay, oveintopmay, anday oveinbottommay) ideslay inay ewnay imagesay."
+
+# game/demo_transitions.rpy:402
+translate piglatin demo_movetransition_20946d36:
+
+    # e "Let's see them all in action."
+    e "Etlay'say eesay hemtay allay inay actionay."
+
+# game/demo_transitions.rpy:428
+translate piglatin demo_movetransition_569952e3:
+
+    # e "That's it for the moveins and moveouts."
+    e "Hattay'say itay orfay hetay oveinsmay anday oveoutsmay."
+
+# game/demo_transitions.rpy:430
+translate piglatin demo_movetransition_af4c53cf:
+
+    # e "Finally, there are the zoomin and zoomout transtions, which show and hide things using a zoom."
+    e "Inallyfay, heretay areay hetay oominzay anday oomoutzay anstionstray, hichway owshay anday idehay hingstay usingay aay oomzay."
+
+# game/demo_transitions.rpy:438
+translate piglatin demo_movetransition_dc5ccd54:
+
+    # e "And that's all there is."
+    e "Ndaay hattay'say allay heretay isay."
+
+# game/demo_transitions.rpy:444
+translate piglatin demo_alphadissolve_3efbde9f:
+
+    # e "The AlphaDissolve transition lets you use one displayable to combine two others. For example..."
+    e "Hetay Lphadissolveaay ansitiontray etslay ouyay useay oneay isplayableday otay ombinecay wotay othersay. Orfay exampleay..."
+
+# game/demo_transitions.rpy:452
+translate piglatin demo_alphadissolve_7c08cf8b:
+
+    # e "The AlphaDissolve displayable takes a control displayable, usually an ATL transform."
+    e "Hetay Lphadissolveaay isplayableday akestay aay ontrolcay isplayableday, usuallyay anay Tlaay ansformtray."
+
+# game/demo_transitions.rpy:457
+translate piglatin demo_alphadissolve_068e3e98:
+
+    # e "To be useful, the control displayable should be partially transparent."
+    e "Otay ebay usefulay, hetay ontrolcay isplayableday ouldshay ebay artiallypay ansparenttray."
+
+# game/demo_transitions.rpy:459
+translate piglatin demo_alphadissolve_6a1b6203:
+
+    # e "During an AlphaDissolve, the old screen is used to fill the transparent areas of the image, while the new screen fills the opaque areas."
+    e "Uringday anay Lphadissolveaay, hetay olday creensay isay useday otay illfay hetay ansparenttray areasay ofay hetay imageay, hileway hetay ewnay creensay illsfay hetay opaqueay areasay."
+
+# game/demo_transitions.rpy:463
+translate piglatin demo_alphadissolve_80a728b6:
+
+    # e "For our spotlight example, the old screen is this all-black image."
+    e "Orfay ouray potlightsay exampleay, hetay olday creensay isay histay allay-ackblay imageay."
+
+# game/demo_transitions.rpy:468
+translate piglatin demo_alphadissolve_ce4380eb:
+
+    # e "The new screen is me just standing here."
+    e "Hetay ewnay creensay isay emay ustjay andingstay erehay."
+
+# game/demo_transitions.rpy:476
+translate piglatin demo_alphadissolve_2e95917b:
+
+    # e "By combining them using AlphaDissolve, we can build a complicated effect out of simpler parts."
+    e "Ybay ombiningcay hemtay usingay Lphadissolveaay, eway ancay uildbay aay omplicatedcay effectay outay ofay implersay artspay."
+
+translate piglatin strings:
+
+    # demo_transitions.rpy:46
+    old "Simple Transitions"
+    new "Implesay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old "ImageDissolve Transitions"
+    new "Magedissolveiay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old "MoveTransition Transitions"
+    new "Ovetransitionmay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old "CropMove Transitions"
+    new "Ropmovecay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old "PushMove Transitions"
+    new "Ushmovepay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old "AlphaDissolve Transitions"
+    new "Lphadissolveaay Ransitionstay"
+
+    # demo_transitions.rpy:46
+    old ""
+    new ""
+
+    # demo_transitions.rpy:46
+    old "How about something else?"
+    new "Owhay aboutay omethingsay elseay?"
+
diff --git a/tutorial/game/tl/piglatin/demo_ui.rpy b/tutorial/game/tl/piglatin/demo_ui.rpy
new file mode 100644
index 0000000..753ce65
--- /dev/null
+++ b/tutorial/game/tl/piglatin/demo_ui.rpy
@@ -0,0 +1,245 @@
+
+# game/demo_ui.rpy:220
+translate piglatin demo_ui_e1d49b5e:
+
+    # e "Ren'Py gives a number of ways of interacting with the user."
+    e "Enray'Ypay ivesgay aay umbernay ofay aysway ofay interactingay ithway hetay useray."
+
+# game/demo_ui.rpy:222
+translate piglatin demo_ui_313b38c2:
+
+    # e "You've already seen say statements and menus."
+    e "Ouyay'evay alreadyay eensay aysay atementsstay anday enusmay."
+
+# game/demo_ui.rpy:224
+translate piglatin demo_ui_fdeef56f:
+
+    # e "But were you aware that you can have dialogue and menus onscreen at the same time?" nointeract
+    e "Utbay ereway ouyay awareay hattay ouyay ancay avehay ialogueday anday enusmay onscreenay atay hetay amesay imetay?" nointeract
+
+# game/demo_ui.rpy:232
+translate piglatin demo_ui_d4d568aa:
+
+    # e "Good!"
+    e "Oodgay!"
+
+# game/demo_ui.rpy:238
+translate piglatin demo_ui_f34995a5:
+
+    # e "Well, now you know."
+    e "Ellway, ownay ouyay nowkay."
+
+# game/demo_ui.rpy:242
+translate piglatin demo_ui_7cfaf270:
+
+    # e "We can also prompt the user to enter some text."
+    e "Eway ancay alsoay romptpay hetay useray otay enteray omesay exttay."
+
+# game/demo_ui.rpy:246
+translate piglatin demo_ui_d77a671d:
+
+    # pov "My name is [povname!t]."
+    pov "Ymay amenay isay [povname!t]."
+
+# game/demo_ui.rpy:249
+translate piglatin demo_ui_b50edd86:
+
+    # e "Imagemaps let the user click on an image to make a choice. For example, the following screen lets you pick what to do after school:"
+    e "Magemapsiay etlay hetay useray ickclay onay anay imageay otay akemay aay oicechay. Orfay exampleay, hetay ollowingfay creensay etslay ouyay ickpay hatway otay oday afteray choolsay:"
+
+# game/demo_ui.rpy:262
+translate piglatin demo_ui_405542a5:
+
+    # e "You chose swimming."
+    e "Ouyay osechay wimmingsay."
+
+# game/demo_ui.rpy:264
+translate piglatin demo_ui_264b5873:
+
+    # e "Swimming seems like a lot of fun, but I didn't bring my bathing suit with me."
+    e "Wimmingsay eemssay ikelay aay otlay ofay unfay, utbay Iay idnday'tay ingbray ymay athingbay uitsay ithway emay."
+
+# game/demo_ui.rpy:268
+translate piglatin demo_ui_83e5c0cc:
+
+    # e "You chose science."
+    e "Ouyay osechay ciencesay."
+
+# game/demo_ui.rpy:270
+translate piglatin demo_ui_319cdf4b:
+
+    # e "I've heard that some schools have a competitive science team, but to me research is something that can't be rushed."
+    e "Iay'evay eardhay hattay omesay choolssay avehay aay ompetitivecay ciencesay eamtay, utbay otay emay esearchray isay omethingsay hattay ancay'tay ebay ushedray."
+
+# game/demo_ui.rpy:274
+translate piglatin demo_ui_d2a94440:
+
+    # e "You chose art."
+    e "Ouyay osechay artay."
+
+# game/demo_ui.rpy:276
+translate piglatin demo_ui_e6af6f1d:
+
+    # e "Really good background art is hard to make, which is why so many games use filtered photographs. Maybe you can change that."
+    e "Eallyray oodgay ackgroundbay artay isay ardhay otay akemay, hichway isay hyway osay anymay amesgay useay ilteredfay otographsphay. Aybemay ouyay ancay angechay hattay."
+
+# game/demo_ui.rpy:280
+translate piglatin demo_ui_373ea9a5:
+
+    # e "You chose to go home."
+    e "Ouyay osechay otay ogay omehay."
+
+# game/demo_ui.rpy:282
+translate piglatin demo_ui_48eca0a4:
+
+    # e "Anyway..."
+    e "Nywayaay..."
+
+# game/demo_ui.rpy:284
+translate piglatin demo_ui_aa9bd954:
+
+    # e "We also support viewports, that allow us to display things that are bigger than the screen."
+    e "Eway alsoay upportsay iewportsvay, hattay alloway usay otay isplayday hingstay hattay areay iggerbay hantay hetay creensay."
+
+# game/demo_ui.rpy:286
+translate piglatin demo_ui_a9db7181:
+
+    # e "This viewport can be adjusted by dragging, by the mouse wheel, and by the scrollbars."
+    e "Histay iewportvay ancay ebay adjusteday ybay raggingday, ybay hetay ousemay heelway, anday ybay hetay crollbarssay."
+
+# game/demo_ui.rpy:299
+translate piglatin demo_ui_7d821fb9:
+
+    # e "Viewports also support edge scrolling, which is automatic scrolling when the mouse reaches their edge."
+    e "Iewportsvay alsoay upportsay edgeay crollingsay, hichway isay automaticay crollingsay henway hetay ousemay eachesray heirtay edgeay."
+
+# game/demo_ui.rpy:307
+translate piglatin demo_ui_42b93520:
+
+    # e "While these constructs are probably enough for most visual novels, dating simulations may be more complicated."
+    e "Hileway hesetay onstructscay areay robablypay enoughay orfay ostmay isualvay ovelsnay, atingday imulationssay aymay ebay oremay omplicatedcay."
+
+# game/demo_ui.rpy:309
+translate piglatin demo_ui_8300d819:
+
+    # e "The ui functions allow you to create quite complicated interfaces."
+    e "Hetay uiay unctionsfay alloway ouyay otay reatecay uiteqay omplicatedcay interfacesay."
+
+# game/demo_ui.rpy:311
+translate piglatin demo_ui_a070bc2d:
+
+    # e "For example, try the following scheduling and stats screen, which could be used by a stat-based dating simulation."
+    e "Orfay exampleay, ytray hetay ollowingfay chedulingsay anday atsstay creensay, hichway ouldcay ebay useday ybay aay atstay-asedbay atingday imulationsay."
+
+# game/demo_ui.rpy:321
+translate piglatin demo_ui_0d8b1a1c:
+
+    # e "For a better implementation of this, take a look at the dating sim engine (DSE) that ships with Ren'Py."
+    e "Orfay aay etterbay implementationay ofay histay, aketay aay ooklay atay hetay atingday imsay engineay (Seday) hattay ipsshay ithway Enray'Ypay."
+
+# game/demo_ui.rpy:325
+translate piglatin _call_fight_1_cf0ffdb0:
+
+    # e "The ui functions can be also be used to show the sorts of stats you'd need if your game involves combat."
+    e "Hetay uiay unctionsfay ancay ebay alsoay ebay useday otay owshay hetay ortssay ofay atsstay ouyay'day eednay ifay ouryay amegay involvesay ombatcay."
+
+# game/demo_ui.rpy:329
+translate piglatin _call_fight_2_7890ebb9:
+
+    # e "Hopefully, the ui functions will let you write whatever visual novel or dating sim you want."
+    e "Opefullyhay, hetay uiay unctionsfay illway etlay ouyay riteway hateverway isualvay ovelnay oray atingday imsay ouyay antway."
+
+translate piglatin strings:
+
+    # demo_ui.rpy:21
+    old "Dismiss"
+    new "Ismissday"
+
+    # demo_ui.rpy:60
+    old "Morning"
+    new "Orningmay"
+
+    # demo_ui.rpy:60
+    old "Afternoon"
+    new "Fternoonaay"
+
+    # demo_ui.rpy:60
+    old "Evening"
+    new "Veningeay"
+
+    # demo_ui.rpy:61
+    old "morning"
+    new "orningmay"
+
+    # demo_ui.rpy:61
+    old "afternoon"
+    new "afternoonay"
+
+    # demo_ui.rpy:61
+    old "evening"
+    new "eveningay"
+
+    # demo_ui.rpy:62
+    old "Study"
+    new "Tudysay"
+
+    # demo_ui.rpy:62
+    old "Exercise"
+    new "Xerciseeay"
+
+    # demo_ui.rpy:62
+    old "Eat"
+    new "Ateay"
+
+    # demo_ui.rpy:62
+    old "Drink"
+    new "Rinkday"
+
+    # demo_ui.rpy:62
+    old "Be Merry"
+    new "Ebay Errymay"
+
+    # demo_ui.rpy:69
+    old "March 25th"
+    new "Archmay 5th2ay"
+
+    # demo_ui.rpy:71
+    old "Strength"
+    new "Trengthsay"
+
+    # demo_ui.rpy:71
+    old "Intelligence"
+    new "Ntelligenceiay"
+
+    # demo_ui.rpy:71
+    old "Moxie"
+    new "Oxiemay"
+
+    # demo_ui.rpy:71
+    old "Chutzpah"
+    new "Hutzpahcay"
+
+    # demo_ui.rpy:104
+    old "Statistics"
+    new "Tatisticssay"
+
+    # demo_ui.rpy:135
+    old "Continue"
+    new "Ontinuecay"
+
+    # demo_ui.rpy:155
+    old "What will you do in the [periods_small_selected!t]?"
+    new "Hatway illway ouyay oday inay hetay [periods_small_selected!t]?"
+
+    # demo_ui.rpy:169
+    old "To get to the next screen, click the 'Continue' button."
+    new "Otay etgay otay hetay extnay creensay, ickclay hetay 'Ontinuecay' uttonbay."
+
+    # demo_ui.rpy:244
+    old "What is your name?"
+    new "Hatway isay ouryay amenay?"
+
+    # demo_ui.rpy:244
+    old "Guy Shy"
+    new "Uygay Hysay"
+
diff --git a/tutorial/game/tl/piglatin/screens.rpy b/tutorial/game/tl/piglatin/screens.rpy
new file mode 100644
index 0000000..e983cc4
--- /dev/null
+++ b/tutorial/game/tl/piglatin/screens.rpy
@@ -0,0 +1,175 @@
+
+translate piglatin strings:
+
+    # screens.rpy:194
+    old "Start Game"
+    new "Tartsay Amegay"
+
+    # screens.rpy:195
+    old "Load Game"
+    new "Oadlay Amegay"
+
+    # screens.rpy:196
+    old "Preferences"
+    new "Referencespay"
+
+    # screens.rpy:197
+    old "Help"
+    new "Elphay"
+
+    # screens.rpy:198
+    old "Quit"
+    new "Uitqay"
+
+    # screens.rpy:228
+    old "Return"
+    new "Eturnray"
+
+    # screens.rpy:230
+    old "Save Game"
+    new "Avesay Amegay"
+
+    # screens.rpy:232
+    old "Main Menu"
+    new "Ainmay Enumay"
+
+    # screens.rpy:266
+    old "Previous"
+    new "Reviouspay"
+
+    # screens.rpy:269
+    old "Auto"
+    new "Utoaay"
+
+    # screens.rpy:272
+    old "Quick"
+    new "Uickqay"
+
+    # screens.rpy:279
+    old "Next"
+    new "Extnay"
+
+    # screens.rpy:305
+    old "Empty Slot."
+    new "Mptyeay Lotsay."
+
+    # screens.rpy:361
+    old "Display"
+    new "Isplayday"
+
+    # screens.rpy:362
+    old "Window"
+    new "Indowway"
+
+    # screens.rpy:363
+    old "Fullscreen"
+    new "Ullscreenfay"
+
+    # screens.rpy:370
+    old "All"
+    new "Llaay"
+
+    # screens.rpy:371
+    old "None"
+    new "Onenay"
+
+    # screens.rpy:377
+    old "Text Speed"
+    new "Exttay Peedsay"
+
+    # screens.rpy:384
+    old "Joystick..."
+    new "Oystickjay..."
+
+    # screens.rpy:391
+    old "Language"
+    new "Anguagelay"
+
+    # screens.rpy:406
+    old "Skip"
+    new "Kipsay"
+
+    # screens.rpy:407
+    old "Seen Messages"
+    new "Eensay Essagesmay"
+
+    # screens.rpy:408
+    old "All Messages"
+    new "Llaay Essagesmay"
+
+    # screens.rpy:414
+    old "Begin Skipping"
+    new "Eginbay Kippingsay"
+
+    # screens.rpy:420
+    old "After Choices"
+    new "Fteraay Hoicescay"
+
+    # screens.rpy:421
+    old "Stop Skipping"
+    new "Topsay Kippingsay"
+
+    # screens.rpy:422
+    old "Keep Skipping"
+    new "Eepkay Kippingsay"
+
+    # screens.rpy:428
+    old "Auto-Forward Time"
+    new "Utoaay-Orwardfay Imetay"
+
+    # screens.rpy:432
+    old "Wait for Voice"
+    new "Aitway orfay Oicevay"
+
+    # screens.rpy:439
+    old "Music Volume"
+    new "Usicmay Olumevay"
+
+    # screens.rpy:446
+    old "Sound Volume"
+    new "Oundsay Olumevay"
+
+    # screens.rpy:450
+    old "Test"
+    new "Esttay"
+
+    # screens.rpy:459
+    old "Voice Volume"
+    new "Oicevay Olumevay"
+
+    # screens.rpy:462
+    old "Voice Sustain"
+    new "Oicevay Ustainsay"
+
+    # screens.rpy:523
+    old "Yes"
+    new "Esyay"
+
+    # screens.rpy:524
+    old "No"
+    new "Onay"
+
+    # screens.rpy:552
+    old "Back"
+    new "Ackbay"
+
+    # screens.rpy:553
+    old "Save"
+    new "Avesay"
+
+    # screens.rpy:554
+    old "Q.Save"
+    new "Qay.Avesay"
+
+    # screens.rpy:555
+    old "Q.Load"
+    new "Qay.Oadlay"
+
+    # screens.rpy:557
+    old "F.Skip"
+    new "Fay.Kipsay"
+
+    # screens.rpy:559
+    old "Prefs"
+    new "Refspay"
+
diff --git a/tutorial/game/tl/piglatin/script.rpy b/tutorial/game/tl/piglatin/script.rpy
new file mode 100644
index 0000000..50d14e7
--- /dev/null
+++ b/tutorial/game/tl/piglatin/script.rpy
@@ -0,0 +1,151 @@
+
+# game/script.rpy:76
+translate piglatin start_0e6a5bb4:
+
+    # e "Hi! My name is Eileen, and I'd like to welcome you to the Ren'Py tutorial."
+    e "Ihay! Ymay amenay isay Ileeneay, anday Iay'day ikelay otay elcomeway ouyay otay hetay Enray'Ypay utorialtay."
+
+# game/script.rpy:80
+translate piglatin start_d3abb53c:
+
+    # e "In this tutorial, we'll teach you the basics of Ren'Py, so you can make games of your own. We'll also demonstrate many features, so you can see what Ren'Py is capable of."
+    e "Niay histay utorialtay, eway'llay eachtay ouyay hetay asicsbay ofay Enray'Ypay, osay ouyay ancay akemay amesgay ofay ouryay ownay. Eway'llay alsoay emonstrateday anymay eaturesfay, osay ouyay ancay eesay hatway Enray'Ypay isay apablecay ofay."
+
+# game/script.rpy:111
+translate piglatin end_b2482727:
+
+    # e "Thank you for viewing this tutorial."
+    e "Hanktay ouyay orfay iewingvay histay utorialtay."
+
+# game/script.rpy:113
+translate piglatin end_38362e36:
+
+    # e "If you'd like to see a full Ren'Py game, select \"The Question\" in the launcher."
+    e "Fiay ouyay'day ikelay otay eesay aay ullfay Enray'Ypay amegay, electsay \"Hetay Uestionqay\" inay hetay auncherlay."
+
+# game/script.rpy:115
+translate piglatin end_894a9e66:
+
+    # e "You can download new versions of Ren'Py from {a=http://www.renpy.org/}http://www.renpy.org/{/a}. For help and discussion, check out the {a=http://lemmasoft.renai.us/forums/}Lemma Soft Forums{/a}."
+    e "Ouyay ancay ownloadday ewnay ersionsvay ofay Enray'Ypay omfray {a=http://www.renpy.org/}ttphay://wwway.enpyray.orgay/{/a}. Orfay elphay anday iscussionday, eckchay outay hetay {a=http://lemmasoft.renai.us/forums/}Emmalay Oftsay Orumsfay{/a}."
+
+# game/script.rpy:117
+translate piglatin end_a898b369:
+
+    # e "We'd like to thank Piroshki for contributing my sprites, Mugenjohncel for Lucy and the band, and Jake for the magic circle."
+    e "Eway'day ikelay otay hanktay Iroshkipay orfay ontributingcay ymay pritessay, Ugenjohncelmay orfay Ucylay anday hetay andbay, anday Akejay orfay hetay agicmay irclecay."
+
+# game/script.rpy:119
+translate piglatin end_762dc07a:
+
+    # e "The background music is \"Sunflower Slow Drag\", by Scott Joplin and Scott Hayden, performed by the United States Marine Band. The concert music is by Alessio."
+    e "Hetay ackgroundbay usicmay isay \"Unflowersay Lowsay Ragday\", ybay Cottsay Oplinjay anday Cottsay Aydenhay, erformedpay ybay hetay Niteduay Tatessay Arinemay Andbay. Hetay oncertcay usicmay isay ybay Lessioaay."
+
+# game/script.rpy:123
+translate piglatin end_57c21073:
+
+    # e "We look forward to seeing what you can make with Ren'Py. Have fun!"
+    e "Eway ooklay orwardfay otay eeingsay hatway ouyay ancay akemay ithway Enray'Ypay. Avehay unfay!"
+
+translate piglatin strings:
+
+    # script.rpy:5
+    old "Eileen"
+    new "Ileeneay"
+
+    # script.rpy:9
+    old "User Experience"
+    new "Seruay Xperienceeay"
+
+    # script.rpy:9
+    old "Writing Dialogue"
+    new "Ritingway Ialogueday"
+
+    # script.rpy:9
+    old "Adding Images"
+    new "Ddingaay Magesiay"
+
+    # script.rpy:9
+    old "Transitions"
+    new "Ransitionstay"
+
+    # script.rpy:9
+    old "Music and Sound Effects"
+    new "Usicmay anday Oundsay Ffectseay"
+
+    # script.rpy:9
+    old "In-Game Menus and Python"
+    new "Niay-Amegay Enusmay anday Ythonpay"
+
+    # script.rpy:9
+    old "Screen Positions"
+    new "Creensay Ositionspay"
+
+    # script.rpy:9
+    old "Animation and Transformation"
+    new "Nimationaay anday Ransformationtay"
+
+    # script.rpy:9
+    old "Video Playback"
+    new "Ideovay Laybackpay"
+
+    # script.rpy:9
+    old "Transition Gallery"
+    new "Ransitiontay Allerygay"
+
+    # script.rpy:9
+    old "Image Operations"
+    new "Mageiay Perationsoay"
+
+    # script.rpy:9
+    old "User Interaction"
+    new "Seruay Nteractioniay"
+
+    # script.rpy:9
+    old "Fonts and Text Tags"
+    new "Ontsfay anday Exttay Agstay"
+
+    # script.rpy:9
+    old "Character Objects"
+    new "Haractercay Bjectsoay"
+
+    # script.rpy:9
+    old "Layers & Advanced Show"
+    new "Ayerslay & Dvancedaay Howsay"
+
+    # script.rpy:9
+    old "NVL Mode"
+    new "Vlnay Odemay"
+
+    # script.rpy:9
+    old "Dynamic Displayables"
+    new "Ynamicday Isplayablesday"
+
+    # script.rpy:9
+    old "Minigames"
+    new "Inigamesmay"
+
+    # script.rpy:9
+    old "Persistent Data"
+    new "Ersistentpay Ataday"
+
+    # script.rpy:9
+    old "Transform"
+    new "Ransformtay"
+
+    # script.rpy:9
+    old "Sprites"
+    new "Pritessay"
+
+    # script.rpy:55
+    old "That's enough for now."
+    new "Hattay'say enoughay orfay ownay."
+
+    # script.rpy:91
+    old "What would you like to see?"
+    new "Hatway ouldway ouyay ikelay otay eesay?"
+
+    # script.rpy:93
+    old "Is there anything else you'd like to see?"
+    new "Siay heretay anythingay elseay ouyay'day ikelay otay eesay?"
+
diff --git a/tutorial/game/tl/piglatin/tutorial_atl.rpy b/tutorial/game/tl/piglatin/tutorial_atl.rpy
new file mode 100644
index 0000000..c1a5b77
--- /dev/null
+++ b/tutorial/game/tl/piglatin/tutorial_atl.rpy
@@ -0,0 +1,561 @@
+
+# ../tutorial_atl.rpyc:187
+translate piglatin tutorial_positions_a09a3fd1:
+
+    # e "In this tutorial, I'll teach you how Ren'Py positions things on the screen. But before that, let's learn a little bit about how Python handles numbers."
+    e "Niay histay utorialtay, Iay'llay eachtay ouyay owhay Enray'Ypay ositionspay hingstay onay hetay creensay. Utbay eforebay hattay, etlay'say earnlay aay ittlelay itbay aboutay owhay Ythonpay andleshay umbersnay."
+
+# ../tutorial_atl.rpyc:189
+translate piglatin tutorial_positions_ba39aabc:
+
+    # e "There are two main kinds of numbers in Python: integers and floating point numbers. An integer consists entirely of digits, while a floating point number has a decimal point."
+    e "Heretay areay wotay ainmay indskay ofay umbersnay inay Ythonpay: integersay anday oatingflay ointpay umbersnay. Naay integeray onsistscay entirelyay ofay igitsday, hileway aay oatingflay ointpay umbernay ashay aay ecimalday ointpay."
+
+# ../tutorial_atl.rpyc:191
+translate piglatin tutorial_positions_a60b775d:
+
+    # e "For example, 100 is an integer, while 0.5 is a floating point number, or float for short. In this system, there are two zeros: 0 is an integer, and 0.0 is a float."
+    e "Orfay exampleay, 001ay isay anay integeray, hileway 0ay.5ay isay aay oatingflay ointpay umbernay, oray oatflay orfay ortshay. Niay histay ystemsay, heretay areay wotay eroszay: 0ay isay anay integeray, anday 0ay.0ay isay aay oatflay."
+
+# ../tutorial_atl.rpyc:193
+translate piglatin tutorial_positions_7f1a560c:
+
+    # e "Ren'Py uses integers to represent absolute coordinates, and floats to represent fractions of an area with known size."
+    e "Enray'Ypay usesay integersay otay epresentray absoluteay oordinatescay, anday oatsflay otay epresentray actionsfray ofay anay areaay ithway nownkay izesay."
+
+# ../tutorial_atl.rpyc:195
+translate piglatin tutorial_positions_8e7d3e52:
+
+    # e "When we're positioning something, the area is usually the entire screen."
+    e "Henway eway'eray ositioningpay omethingsay, hetay areaay isay usuallyay hetay entireay creensay."
+
+# ../tutorial_atl.rpyc:197
+translate piglatin tutorial_positions_fdcf9d8b:
+
+    # e "Let me get out of the way, and I'll show you where some positions are."
+    e "Etlay emay etgay outay ofay hetay ayway, anday Iay'llay owshay ouyay hereway omesay ositionspay areay."
+
+# ../tutorial_atl.rpyc:211
+translate piglatin tutorial_positions_76d7a5bf:
+
+    # e "The origin is the upper-left corner of the screen. That's where the x position (xpos) and the y position (ypos) are both zero."
+    e "Hetay originay isay hetay upperay-eftlay ornercay ofay hetay creensay. Hattay'say hereway hetay xay ositionpay (posxay) anday hetay yay ositionpay (posyay) areay othbay erozay."
+
+# ../tutorial_atl.rpyc:217
+translate piglatin tutorial_positions_be14c7c3:
+
+    # e "When we increase xpos, we move to the right. So here's an xpos of .5, meaning half the width across the screen."
+    e "Henway eway increaseay posxay, eway ovemay otay hetay ightray. Osay erehay'say anay posxay ofay .5ay, eaningmay alfhay hetay idthway acrossay hetay creensay."
+
+# ../tutorial_atl.rpyc:222
+translate piglatin tutorial_positions_9b91be6c:
+
+    # e "Increasing xpos to 1.0 moves us to the right-hand border of the screen."
+    e "Ncreasingiay posxay otay 1ay.0ay ovesmay usay otay hetay ightray-andhay orderbay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:228
+translate piglatin tutorial_positions_80be064f:
+
+    # e "We can also use an absolute xpos, which is given in an absolute number of pixels from the left side of the screen. For example, since this window is 800 pixels across, using an xpos of 400 will return the target to the center of the top row."
+    e "Eway ancay alsoay useay anay absoluteay posxay, hichway isay ivengay inay anay absoluteay umbernay ofay ixelspay omfray hetay eftlay idesay ofay hetay creensay. Orfay exampleay, incesay histay indowway isay 008ay ixelspay acrossay, usingay anay posxay ofay 004ay illway eturnray hetay argettay otay hetay entercay ofay hetay optay owray."
+
+# ../tutorial_atl.rpyc:230
+translate piglatin tutorial_positions_c4d18c0a:
+
+    # e "The y-axis position, or ypos works the same way. Right now, we have a ypos of 0.0."
+    e "Hetay yay-axisay ositionpay, oray posyay orksway hetay amesay ayway. Ightray ownay, eway avehay aay posyay ofay 0ay.0ay."
+
+# ../tutorial_atl.rpyc:236
+translate piglatin tutorial_positions_16933a61:
+
+    # e "Here's a ypos of 0.5."
+    e "Erehay'say aay posyay ofay 0ay.5ay."
+
+# ../tutorial_atl.rpyc:241
+translate piglatin tutorial_positions_6eb36777:
+
+    # e "A ypos of 1.0 specifies a position at the bottom of the screen. If you look carefully, you can see the position indicator spinning below the text window."
+    e "Aay posyay ofay 1ay.0ay pecifiessay aay ositionpay atay hetay ottombay ofay hetay creensay. Fiay ouyay ooklay arefullycay, ouyay ancay eesay hetay ositionpay indicatoray pinningsay elowbay hetay exttay indowway."
+
+# ../tutorial_atl.rpyc:243
+translate piglatin tutorial_positions_a423050f:
+
+    # e "Like xpos, ypos can also be an integer. In this case, ypos would give the total number of pixels from the top of the screen."
+    e "Ikelay posxay, posyay ancay alsoay ebay anay integeray. Niay histay asecay, posyay ouldway ivegay hetay otaltay umbernay ofay ixelspay omfray hetay optay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:249
+translate piglatin tutorial_positions_bc7a809a:
+
+    # e "Can you guess where this position is, relative to the screen?" nointeract
+    e "Ancay ouyay uessgay hereway histay ositionpay isay, elativeray otay hetay creensay?" nointeract
+
+# ../tutorial_atl.rpyc:255
+translate piglatin tutorial_positions_6f926e18:
+
+    # e "Sorry, that's wrong. The xpos is .75, and the ypos is .25."
+    e "Orrysay, hattay'say rongway. Hetay posxay isay .57ay, anday hetay posyay isay .52ay."
+
+# ../tutorial_atl.rpyc:257
+translate piglatin tutorial_positions_5d5feb98:
+
+    # e "In other words, it's 75%% of the way from the left side, and 25%% of the way from the top."
+    e "Niay otheray ordsway, itay'say 57ay%% ofay hetay ayway omfray hetay eftlay idesay, anday 52ay%% ofay hetay ayway omfray hetay optay."
+
+# ../tutorial_atl.rpyc:261
+translate piglatin tutorial_positions_77b45218:
+
+    # e "Good job! You got that position right."
+    e "Oodgay objay! Ouyay otgay hattay ositionpay ightray."
+
+# ../tutorial_atl.rpyc:265
+translate piglatin tutorial_positions_6f926e18_1:
+
+    # e "Sorry, that's wrong. The xpos is .75, and the ypos is .25."
+    e "Orrysay, hattay'say rongway. Hetay posxay isay .57ay, anday hetay posyay isay .52ay."
+
+# ../tutorial_atl.rpyc:267
+translate piglatin tutorial_positions_5d5feb98_1:
+
+    # e "In other words, it's 75%% of the way from the left side, and 25%% of the way from the top."
+    e "Niay otheray ordsway, itay'say 57ay%% ofay hetay ayway omfray hetay eftlay idesay, anday 52ay%% ofay hetay ayway omfray hetay optay."
+
+# ../tutorial_atl.rpyc:281
+translate piglatin tutorial_positions_e4380a83:
+
+    # e "The second position we care about is the anchor. The anchor is a spot on the thing being positioned."
+    e "Hetay econdsay ositionpay eway arecay aboutay isay hetay anchoray. Hetay anchoray isay aay potsay onay hetay hingtay eingbay ositionedpay."
+
+# ../tutorial_atl.rpyc:283
+translate piglatin tutorial_positions_d1db1246:
+
+    # e "For example, here we have an xanchor of 0.0 and a yanchor of 0.0. It's in the upper-left corner of the logo image."
+    e "Orfay exampleay, erehay eway avehay anay anchorxay ofay 0ay.0ay anday aay anchoryay ofay 0ay.0ay. Tiay'say inay hetay upperay-eftlay ornercay ofay hetay ogolay imageay."
+
+# ../tutorial_atl.rpyc:288
+translate piglatin tutorial_positions_6056873f:
+
+    # e "When we increase the xanchor to 1.0, the anchor moves to the right corner of the image."
+    e "Henway eway increaseay hetay anchorxay otay 1ay.0ay, hetay anchoray ovesmay otay hetay ightray ornercay ofay hetay imageay."
+
+# ../tutorial_atl.rpyc:293
+translate piglatin tutorial_positions_7cdb8dcc:
+
+    # e "Similarly, when both xanchor and yanchor are 1.0, the anchor is the bottom-right corner."
+    e "Imilarlysay, henway othbay anchorxay anday anchoryay areay 1ay.0ay, hetay anchoray isay hetay ottombay-ightray ornercay."
+
+# ../tutorial_atl.rpyc:301
+translate piglatin tutorial_positions_03a07da8:
+
+    # e "To place an image on the screen, we need both the position and the anchor."
+    e "Otay aceplay anay imageay onay hetay creensay, eway eednay othbay hetay ositionpay anday hetay anchoray."
+
+# ../tutorial_atl.rpyc:309
+translate piglatin tutorial_positions_8945054f:
+
+    # e "We then line them up, so that both the position and anchor are at the same point on the screen."
+    e "Eway hentay inelay hemtay upay, osay hattay othbay hetay ositionpay anday anchoray areay atay hetay amesay ointpay onay hetay creensay."
+
+# ../tutorial_atl.rpyc:319
+translate piglatin tutorial_positions_2b184a93:
+
+    # e "When we place both in the upper-left corner, the image moves to the upper-left corner of the screen."
+    e "Henway eway aceplay othbay inay hetay upperay-eftlay ornercay, hetay imageay ovesmay otay hetay upperay-eftlay ornercay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:328
+translate piglatin tutorial_positions_5aac4f3f:
+
+    # e "With the right combination of position and anchor, any place on the screen can be specified, without even knowing the size of the image."
+    e "Ithway hetay ightray ombinationcay ofay ositionpay anday anchoray, anyay aceplay onay hetay creensay ancay ebay pecifiedsay, ithoutway evenay nowingkay hetay izesay ofay hetay imageay."
+
+# ../tutorial_atl.rpyc:340
+translate piglatin tutorial_positions_3b59b797:
+
+    # e "It's often useful to set xpos and xanchor to the same value. We call that xalign, and it gives a fractional position on the screen."
+    e "Tiay'say oftenay usefulay otay etsay posxay anday anchorxay otay hetay amesay aluevay. Eway allcay hattay alignxay, anday itay ivesgay aay actionalfray ositionpay onay hetay creensay."
+
+# ../tutorial_atl.rpyc:345
+translate piglatin tutorial_positions_b8ebf9fe:
+
+    # e "For example, when we set xalign to 0.0, things are aligned to the left side of the screen."
+    e "Orfay exampleay, henway eway etsay alignxay otay 0ay.0ay, hingstay areay aligneday otay hetay eftlay idesay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:350
+translate piglatin tutorial_positions_8ce35d52:
+
+    # e "When we set it to 1.0, then we're aligned to the right side of the screen."
+    e "Henway eway etsay itay otay 1ay.0ay, hentay eway'eray aligneday otay hetay ightray idesay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:355
+translate piglatin tutorial_positions_6745825f:
+
+    # e "And when we set it to 0.5, we're back to the center of the screen."
+    e "Ndaay henway eway etsay itay otay 0ay.5ay, eway'eray ackbay otay hetay entercay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:357
+translate piglatin tutorial_positions_64428a07:
+
+    # e "Setting yalign is similar, except along the y-axis."
+    e "Ettingsay alignyay isay imilarsay, exceptay alongay hetay yay-axisay."
+
+# ../tutorial_atl.rpyc:359
+translate piglatin tutorial_positions_cfb77d42:
+
+    # e "Remember that xalign is just setting xpos and xanchor to the same value, and yalign is just setting ypos and yanchor to the same value."
+    e "Ememberray hattay alignxay isay ustjay ettingsay posxay anday anchorxay otay hetay amesay aluevay, anday alignyay isay ustjay ettingsay posyay anday anchoryay otay hetay amesay aluevay."
+
+# ../tutorial_atl.rpyc:366
+translate piglatin tutorial_positions_0f4ca2b6:
+
+    # e "Once you understand positions, you can use transformations to move things around the Ren'Py screen."
+    e "Nceoay ouyay understanday ositionspay, ouyay ancay useay ansformationstray otay ovemay hingstay arounday hetay Enray'Ypay creensay."
+
+# ../tutorial_atl.rpyc:373
+translate piglatin tutorial_atl_a1cc1bff:
+
+    # e "While showing static images is often enough for most games, occasionally we'll want to change images, or move them around the screen."
+    e "Hileway owingshay aticstay imagesay isay oftenay enoughay orfay ostmay amesgay, occasionallyay eway'llay antway otay angechay imagesay, oray ovemay hemtay arounday hetay creensay."
+
+# ../tutorial_atl.rpyc:375
+translate piglatin tutorial_atl_81dbb8f2:
+
+    # e "We call this a Transform, and it's what ATL, Ren'Py's Animation and Transformation Language, is for."
+    e "Eway allcay histay aay Ransformtay, anday itay'say hatway Tlaay, Enray'Ypay'say Nimationaay anday Ransformationtay Anguagelay, isay orfay."
+
+# ../tutorial_atl.rpyc:383
+translate piglatin tutorial_atl_65badef3:
+
+    # e "But first, let's have... a Gratuitous Rock Concert!"
+    e "Utbay irstfay, etlay'say avehay... aay Ratuitousgay Ockray Oncertcay!"
+
+# ../tutorial_atl.rpyc:391
+translate piglatin tutorial_atl_3ccfe2ac:
+
+    # e "That was a lot of work, and before you can do that, we'll need to start with the basics of using ATL."
+    e "Hattay asway aay otlay ofay orkway, anday eforebay ouyay ancay oday hattay, eway'llay eednay otay artstay ithway hetay asicsbay ofay usingay Tlaay."
+
+# ../tutorial_atl.rpyc:393
+translate piglatin tutorial_atl_1f22f875:
+
+    # e "There are currently three places where ATL can be used in Ren'Py."
+    e "Heretay areay urrentlycay hreetay acesplay hereway Tlaay ancay ebay useday inay Enray'Ypay."
+
+# ../tutorial_atl.rpyc:397
+translate piglatin tutorial_atl_fd036bdf:
+
+    # e "The first place ATL can be used is as part of an image statement. Instead of a displayable, an image may be defined as a block of ATL code."
+    e "Hetay irstfay aceplay Tlaay ancay ebay useday isay asay artpay ofay anay imageay atementstay. Nsteadiay ofay aay isplayableday, anay imageay aymay ebay efinedday asay aay ockblay ofay Tlaay odecay."
+
+# ../tutorial_atl.rpyc:399
+translate piglatin tutorial_atl_7cad2ab9:
+
+    # e "When used in this way, we have to be sure that ATL includes one or more displayables to actually show."
+    e "Henway useday inay histay ayway, eway avehay otay ebay uresay hattay Tlaay includesay oneay oray oremay isplayablesday otay actuallyay owshay."
+
+# ../tutorial_atl.rpyc:403
+translate piglatin tutorial_atl_c78b2a1e:
+
+    # e "The second way is through the use of the transform statement. This assigns the ATL block to a python variable, allowing it to be used in at clauses and inside other transforms."
+    e "Hetay econdsay ayway isay hroughtay hetay useay ofay hetay ansformtray atementstay. Histay assignsay hetay Tlaay ockblay otay aay ythonpay ariablevay, allowingay itay otay ebay useday inay atay ausesclay anday insideay otheray ansformstray."
+
+# ../tutorial_atl.rpyc:407
+translate piglatin tutorial_atl_da7a7759:
+
+    # e "Finally, an ATL block can be used as part of a show statement, instead of the at clause."
+    e "Inallyfay, anay Tlaay ockblay ancay ebay useday asay artpay ofay aay owshay atementstay, insteaday ofay hetay atay auseclay."
+
+# ../tutorial_atl.rpyc:411
+translate piglatin tutorial_atl_c21bc1d1:
+
+    # e "The key to ATL is what we call composeability. ATL is made up of relatively simple commands, which can be combined together to create complicated transforms."
+    e "Hetay eykay otay Tlaay isay hatway eway allcay omposeabilitycay. Tlaay isay ademay upay ofay elativelyray implesay ommandscay, hichway ancay ebay ombinedcay ogethertay otay reatecay omplicatedcay ansformstray."
+
+# ../tutorial_atl.rpyc:413
+translate piglatin tutorial_atl_ed82983f:
+
+    # e "Before I explain how ATL works, let me explain what animation and transformation are."
+    e "Eforebay Iay explainay owhay Tlaay orksway, etlay emay explainay hatway animationay anday ansformationtray areay."
+
+# ../tutorial_atl.rpyc:418
+translate piglatin tutorial_atl_2807adff:
+
+    # e "Animation is when the displayable being shown changes. For example, right now I am changing my expression."
+    e "Nimationaay isay henway hetay isplayableday eingbay ownshay angeschay. Orfay exampleay, ightray ownay Iay amay angingchay ymay expressionay."
+
+# ../tutorial_atl.rpyc:445
+translate piglatin tutorial_atl_3eec202b:
+
+    # e "Transformation involves moving or distorting an image. This includes placing it on the screen, zooming it in and out, rotating it, and changing its opacity."
+    e "Ransformationtay involvesay ovingmay oray istortingday anay imageay. Histay includesay acingplay itay onay hetay creensay, oomingzay itay inay anday outay, otatingray itay, anday angingchay itsay opacityay."
+
+# ../tutorial_atl.rpyc:453
+translate piglatin tutorial_atl_fbc9bf83:
+
+    # e "To introduce ATL, let's start by looking at at a simple animation. Here's one that consists of five lines of ATL code, contained within an image statement."
+    e "Otay introduceay Tlaay, etlay'say artstay ybay ookinglay atay atay aay implesay animationay. Erehay'say oneay hattay onsistscay ofay ivefay ineslay ofay Tlaay odecay, ontainedcay ithinway anay imageay atementstay."
+
+# ../tutorial_atl.rpyc:455
+translate piglatin tutorial_atl_12c839ee:
+
+    # e "In ATL, to change a displayable, simply mention it on a line of ATL code. Here, we're switching back and forth between two images."
+    e "Niay Tlaay, otay angechay aay isplayableday, implysay entionmay itay onay aay inelay ofay Tlaay odecay. Erehay, eway'eray witchingsay ackbay anday orthfay etweenbay wotay imagesay."
+
+# ../tutorial_atl.rpyc:457
+translate piglatin tutorial_atl_c671ed7d:
+
+    # e "Since we're defining an image, the first line of ATL has to name a displayable. Otherwise, there would be nothing to show."
+    e "Incesay eway'eray efiningday anay imageay, hetay irstfay inelay ofay Tlaay ashay otay amenay aay isplayableday. Therwiseoay, heretay ouldway ebay othingnay otay owshay."
+
+# ../tutorial_atl.rpyc:459
+translate piglatin tutorial_atl_99386181:
+
+    # e "The second and fourth lines are pause statements, which cause ATL to wait half of a second each before continuing. That's how we give the delay between images."
+    e "Hetay econdsay anday ourthfay ineslay areay ausepay atementsstay, hichway ausecay Tlaay otay aitway alfhay ofay aay econdsay eachay eforebay ontinuingcay. Hattay'say owhay eway ivegay hetay elayday etweenbay imagesay."
+
+# ../tutorial_atl.rpyc:461
+translate piglatin tutorial_atl_60f2a5e8:
+
+    # e "The final line is a repeat statement. This causes the current block of ATL to be restarted. You can only have one repeat statement per block."
+    e "Hetay inalfay inelay isay aay epeatray atementstay. Histay ausescay hetay urrentcay ockblay ofay Tlaay otay ebay estartedray. Ouyay ancay onlyay avehay oneay epeatray atementstay erpay ockblay."
+
+# ../tutorial_atl.rpyc:466
+translate piglatin tutorial_atl_146cf4c4:
+
+    # e "If we were to write repeat 2 instead, the animation would loop twice, then stop."
+    e "Fiay eway ereway otay riteway epeatray 2ay insteaday, hetay animationay ouldway ooplay wicetay, hentay opstay."
+
+# ../tutorial_atl.rpyc:471
+translate piglatin tutorial_atl_d90b1838:
+
+    # e "Omitting the repeat statement means that the animation stops once we reach the end of the block of ATL code."
+    e "Mittingoay hetay epeatray atementstay eansmay hattay hetay animationay opsstay onceay eway eachray hetay enday ofay hetay ockblay ofay Tlaay odecay."
+
+# ../tutorial_atl.rpyc:476
+translate piglatin tutorial_atl_e5872360:
+
+    # e "By default, displayables are replaced instantaneously. We can also use a with clause to give a transition between displayables."
+    e "Ybay efaultday, isplayablesday areay eplacedray instantaneouslyay. Eway ancay alsoay useay aay ithway auseclay otay ivegay aay ansitiontray etweenbay isplayablesday."
+
+# ../tutorial_atl.rpyc:483
+translate piglatin tutorial_atl_a7f8ed01:
+
+    # e "Now, let's move on to see how we can use ATL to transform an image. We'll start off by seeing what we can do to position images on the screen."
+    e "Ownay, etlay'say ovemay onay otay eesay owhay eway ancay useay Tlaay otay ansformtray anay imageay. Eway'llay artstay offay ybay eeingsay hatway eway ancay oday otay ositionpay imagesay onay hetay creensay."
+
+# ../tutorial_atl.rpyc:492
+translate piglatin tutorial_atl_24501213:
+
+    # e "Perhaps the simplest thing we can do is to position the images on the screen. This can be done by simply giving the names of the transform properties, each followed by the value."
+    e "Erhapspay hetay implestsay hingtay eway ancay oday isay otay ositionpay hetay imagesay onay hetay creensay. Histay ancay ebay oneday ybay implysay ivinggay hetay amesnay ofay hetay ansformtray ropertiespay, eachay ollowedfay ybay hetay aluevay."
+
+# ../tutorial_atl.rpyc:497
+translate piglatin tutorial_atl_43516492:
+
+    # e "With a few more statements, we can move things around on the screen."
+    e "Ithway aay ewfay oremay atementsstay, eway ancay ovemay hingstay arounday onay hetay creensay."
+
+# ../tutorial_atl.rpyc:499
+translate piglatin tutorial_atl_8b053b5a:
+
+    # e "This code starts the image off at the top-right of the screen, and waits a second."
+    e "Histay odecay artsstay hetay imageay offay atay hetay optay-ightray ofay hetay creensay, anday aitsway aay econdsay."
+
+# ../tutorial_atl.rpyc:501
+translate piglatin tutorial_atl_d7fc5372:
+
+    # e "It then moves it to the left side, waits another second, and repeats."
+    e "Tiay hentay ovesmay itay otay hetay eftlay idesay, aitsway anotheray econdsay, anday epeatsray."
+
+# ../tutorial_atl.rpyc:503
+translate piglatin tutorial_atl_7650ec09:
+
+    # e "The pause and repeat statements are the same statements we used in our animations. They work throughout ATL code."
+    e "Hetay ausepay anday epeatray atementsstay areay hetay amesay atementsstay eway useday inay ouray animationsay. Heytay orkway hroughouttay Tlaay odecay."
+
+# ../tutorial_atl.rpyc:508
+translate piglatin tutorial_atl_d3416d4f:
+
+    # e "Having the image jump around on the screen isn't all that useful. That's why ATL has the interpolation statement."
+    e "Avinghay hetay imageay umpjay arounday onay hetay creensay isnay'tay allay hattay usefulay. Hattay'say hyway Tlaay ashay hetay interpolationay atementstay."
+
+# ../tutorial_atl.rpyc:510
+translate piglatin tutorial_atl_4e7512ec:
+
+    # e "The interpolation statement allows you to smoothly vary the value of a transform property, from an old to a new value."
+    e "Hetay interpolationay atementstay allowsay ouyay otay moothlysay aryvay hetay aluevay ofay aay ansformtray ropertypay, omfray anay olday otay aay ewnay aluevay."
+
+# ../tutorial_atl.rpyc:512
+translate piglatin tutorial_atl_685eeeaa:
+
+    # e "Here, we have an interpolation statement on the second ATL line. It starts off with the name of a time function, in this case linear."
+    e "Erehay, eway avehay anay interpolationay atementstay onay hetay econdsay Tlaay inelay. Tiay artsstay offay ithway hetay amenay ofay aay imetay unctionfay, inay histay asecay inearlay."
+
+# ../tutorial_atl.rpyc:514
+translate piglatin tutorial_atl_c5cb49de:
+
+    # e "That's followed by an amount of time, in this case three seconds. It ends with a list of properties, each followed by its new value."
+    e "Hattay'say ollowedfay ybay anay amountay ofay imetay, inay histay asecay hreetay econdssay. Tiay endsay ithway aay istlay ofay ropertiespay, eachay ollowedfay ybay itsay ewnay aluevay."
+
+# ../tutorial_atl.rpyc:516
+translate piglatin tutorial_atl_72d47fb6:
+
+    # e "The old value is the value of the transform property at the start of the statement. By interpolating the property over time, we can change things on the screen."
+    e "Hetay olday aluevay isay hetay aluevay ofay hetay ansformtray ropertypay atay hetay artstay ofay hetay atementstay. Ybay interpolatingay hetay ropertypay overay imetay, eway ancay angechay hingstay onay hetay creensay."
+
+# ../tutorial_atl.rpyc:526
+translate piglatin tutorial_atl_2958f397:
+
+    # e "ATL supports more complicated move types, like circle and spline motion. But I won't be showing those here."
+    e "Tlaay upportssay oremay omplicatedcay ovemay ypestay, ikelay irclecay anday plinesay otionmay. Utbay Iay onway'tay ebay owingshay hosetay erehay."
+
+# ../tutorial_atl.rpyc:528
+translate piglatin tutorial_atl_4a02c8d8:
+
+    # e "Next, let's take a look at some of the transform properties that we can change using ATL."
+    e "Extnay, etlay'say aketay aay ooklay atay omesay ofay hetay ansformtray ropertiespay hattay eway ancay angechay usingay Tlaay."
+
+# ../tutorial_atl.rpyc:543
+translate piglatin tutorial_atl_821fcb91:
+
+    # e "We've already seen the position properties. Along with xalign and yalign, we support the xpos, ypos, xanchor, and yanchor properties."
+    e "Eway'evay alreadyay eensay hetay ositionpay ropertiespay. Longaay ithway alignxay anday alignyay, eway upportsay hetay posxay, posyay, anchorxay, anday anchoryay ropertiespay."
+
+# ../tutorial_atl.rpyc:558
+translate piglatin tutorial_atl_cca5082b:
+
+    # e "We can perform a pan by using xpos and ypos to position images off of the screen."
+    e "Eway ancay erformpay aay anpay ybay usingay posxay anday posyay otay ositionpay imagesay offay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:560
+translate piglatin tutorial_atl_0394dd50:
+
+    # e "This usually means giving them negative positions."
+    e "Histay usuallyay eansmay ivinggay hemtay egativenay ositionspay."
+
+# ../tutorial_atl.rpyc:577
+translate piglatin tutorial_atl_2624662e:
+
+    # e "The zoom property lets us scale the displayable by a factor, making it bigger and smaller. For best results, zoom should always be greater than 0.5."
+    e "Hetay oomzay ropertypay etslay usay calesay hetay isplayableday ybay aay actorfay, akingmay itay iggerbay anday mallersay. Orfay estbay esultsray, oomzay ouldshay alwaysay ebay eatergray hantay 0ay.5ay."
+
+# ../tutorial_atl.rpyc:591
+translate piglatin tutorial_atl_b6527546:
+
+    # e "The xzoom and yzoom properties allow the displayable to be scaled in the X and Y directions independently."
+    e "Hetay zoomxay anday zoomyay ropertiespay alloway hetay isplayableday otay ebay caledsay inay hetay Xay anday Yay irectionsday independentlyay."
+
+# ../tutorial_atl.rpyc:602
+translate piglatin tutorial_atl_9fe238de:
+
+    # e "The size property can be used to set a size, in pixels, that the displayable is scaled to."
+    e "Hetay izesay ropertypay ancay ebay useday otay etsay aay izesay, inay ixelspay, hattay hetay isplayableday isay caledsay otay."
+
+# ../tutorial_atl.rpyc:617
+translate piglatin tutorial_atl_6b982a23:
+
+    # e "The alpha property allows us to vary the opacity of a displayable. This can make it appear and disappear."
+    e "Hetay alphaay ropertypay allowsay usay otay aryvay hetay opacityay ofay aay isplayableday. Histay ancay akemay itay appearay anday isappearday."
+
+# ../tutorial_atl.rpyc:631
+translate piglatin tutorial_atl_60d6d9f3:
+
+    # e "The rotate property lets us rotate a displayable."
+    e "Hetay otateray ropertypay etslay usay otateray aay isplayableday."
+
+# ../tutorial_atl.rpyc:633
+translate piglatin tutorial_atl_898a138a:
+
+    # e "Since rotation can change the size, usually you'll want to set xanchor and yanchor to 0.5 when positioning a rotated displayable."
+    e "Incesay otationray ancay angechay hetay izesay, usuallyay ouyay'llay antway otay etsay anchorxay anday anchoryay otay 0ay.5ay henway ositioningpay aay otatedray isplayableday."
+
+# ../tutorial_atl.rpyc:644
+translate piglatin tutorial_atl_207b7fc8:
+
+    # e "The crop property crops a rectangle out of a displayable, showing only part of it."
+    e "Hetay ropcay ropertypay ropscay aay ectangleray outay ofay aay isplayableday, owingshay onlyay artpay ofay itay."
+
+# ../tutorial_atl.rpyc:658
+translate piglatin tutorial_atl_ebb84988:
+
+    # e "When used together, they can be used to focus in on specific parts of an image."
+    e "Henway useday ogethertay, heytay ancay ebay useday otay ocusfay inay onay pecificsay artspay ofay anay imageay."
+
+# ../tutorial_atl.rpyc:664
+translate piglatin tutorial_atl_d08fe8d9:
+
+    # e "Apart from displayables, pause, interpolation, and repeat, there are a few other statements we can use as part of ATL."
+    e "Partaay omfray isplayablesday, ausepay, interpolationay, anday epeatray, heretay areay aay ewfay otheray atementsstay eway ancay useay asay artpay ofay Tlaay."
+
+# ../tutorial_atl.rpyc:678
+translate piglatin tutorial_atl_db6302bd:
+
+    # e "When we create an ATL transform using the transform statement, we can use that transform as an ATL statement."
+    e "Henway eway reatecay anay Tlaay ansformtray usingay hetay ansformtray atementstay, eway ancay useay hattay ansformtray asay anay Tlaay atementstay."
+
+# ../tutorial_atl.rpyc:680
+translate piglatin tutorial_atl_785911cf:
+
+    # e "Since the default positions are also transforms, this means that we can use left, right, and center inside of an ATL block."
+    e "Incesay hetay efaultday ositionspay areay alsoay ansformstray, histay eansmay hattay eway ancay useay eftlay, ightray, anday entercay insideay ofay anay Tlaay ockblay."
+
+# ../tutorial_atl.rpyc:698
+translate piglatin tutorial_atl_331126c1:
+
+    # e "Here, we have two new statements. The block statement allows you to include a block of ATL code. Since the repeat statement applies to blocks, this lets you repeat only part of an ATL transform."
+    e "Erehay, eway avehay wotay ewnay atementsstay. Hetay ockblay atementstay allowsay ouyay otay includeay aay ockblay ofay Tlaay odecay. Incesay hetay epeatray atementstay appliesay otay ocksblay, histay etslay ouyay epeatray onlyay artpay ofay anay Tlaay ansformtray."
+
+# ../tutorial_atl.rpyc:700
+translate piglatin tutorial_atl_24f67b67:
+
+    # e "We also have the time statement, which runs after the given number of seconds have elapsed from the start of the block. It will run even if another statement is running, stopping the other statement."
+    e "Eway alsoay avehay hetay imetay atementstay, hichway unsray afteray hetay ivengay umbernay ofay econdssay avehay elapseday omfray hetay artstay ofay hetay ockblay. Tiay illway unray evenay ifay anotheray atementstay isay unningray, oppingstay hetay otheray atementstay."
+
+# ../tutorial_atl.rpyc:702
+translate piglatin tutorial_atl_30dc0008:
+
+    # e "So this code will bounce the image back and forth for eleven and a half seconds, and then move back to the right side of the screen."
+    e "Osay histay odecay illway ouncebay hetay imageay ackbay anday orthfay orfay elevenay anday aay alfhay econdssay, anday hentay ovemay ackbay otay hetay ightray idesay ofay hetay creensay."
+
+# ../tutorial_atl.rpyc:718
+translate piglatin tutorial_atl_f903bc3b:
+
+    # e "The parallel statement lets us run two blocks of ATL code at the same time."
+    e "Hetay arallelpay atementstay etslay usay unray wotay ocksblay ofay Tlaay odecay atay hetay amesay imetay."
+
+# ../tutorial_atl.rpyc:720
+translate piglatin tutorial_atl_5d0f8f9d:
+
+    # e "Here, the top block move the image in the horizontal direction, and the bottom block moves it in the vertical direction. Since they're moving at different speeds, it looks like the image is bouncing on the screen."
+    e "Erehay, hetay optay ockblay ovemay hetay imageay inay hetay orizontalhay irectionday, anday hetay ottombay ockblay ovesmay itay inay hetay erticalvay irectionday. Incesay heytay'eray ovingmay atay ifferentday peedssay, itay ookslay ikelay hetay imageay isay ouncingbay onay hetay creensay."
+
+# ../tutorial_atl.rpyc:737
+translate piglatin tutorial_atl_28a7d27e:
+
+    # e "Finally, the choice statement makes Ren'Py randomly pick a block of ATL code. This allows you to add some variation as to what Ren'Py shows."
+    e "Inallyfay, hetay oicechay atementstay akesmay Enray'Ypay andomlyray ickpay aay ockblay ofay Tlaay odecay. Histay allowsay ouyay otay adday omesay ariationvay asay otay hatway Enray'Ypay owsshay."
+
+# ../tutorial_atl.rpyc:743
+translate piglatin tutorial_atl_5fc8c0df:
+
+    # e "This tutorial game has only scratched the surface of what you can do with ATL. For example, we haven't even covered the on and event statements. For more information, you might want to check out the ATL chapter in the reference manual."
+    e "Histay utorialtay amegay ashay onlyay cratchedsay hetay urfacesay ofay hatway ouyay ancay oday ithway Tlaay. Orfay exampleay, eway avenhay'tay evenay overedcay hetay onay anday eventay atementsstay. Orfay oremay informationay, ouyay ightmay antway otay eckchay outay hetay Tlaay apterchay inay hetay eferenceray anualmay."
+
+# ../tutorial_atl.rpyc:747
+translate piglatin tutorial_atl_1358c6b4:
+
+    # e "But for now, just remember that when it comes to animating and transforming, ATL is the hot new thing."
+    e "Utbay orfay ownay, ustjay ememberray hattay henway itay omescay otay animatingay anday ansformingtray, Tlaay isay hetay othay ewnay hingtay."
+
+translate piglatin strings:
+
+    # tutorial_atl.rpy:249
+    old "xpos 1.0 ypos .5"
+    new "posxay 1ay.0ay posyay .5ay"
+
+    # tutorial_atl.rpy:249
+    old "xpos .75 ypos .25"
+    new "posxay .57ay posyay .52ay"
+
+    # tutorial_atl.rpy:249
+    old "xpos .25 ypos .33"
+    new "posxay .52ay posyay .33ay"
+
diff --git a/tutorial/game/tl/piglatin/tutorial_playing.rpy b/tutorial/game/tl/piglatin/tutorial_playing.rpy
new file mode 100644
index 0000000..8e64d8c
--- /dev/null
+++ b/tutorial/game/tl/piglatin/tutorial_playing.rpy
@@ -0,0 +1,169 @@
+
+# ../tutorial_playing.rpyc:16
+translate piglatin tutorial_playing_2985ab86:
+
+    # e "As someone who has played more than a few visual novels, there are many features that I expect all games to have."
+    e "Saay omeonesay howay ashay ayedplay oremay hantay aay ewfay isualvay ovelsnay, heretay areay anymay eaturesfay hattay Iay expectay allay amesgay otay avehay."
+
+# ../tutorial_playing.rpyc:18
+translate piglatin tutorial_playing_ca4769bb:
+
+    # e "Features like saving, loading, changing preferences, and so on."
+    e "Eaturesfay ikelay avingsay, oadinglay, angingchay referencespay, anday osay onay."
+
+# ../tutorial_playing.rpyc:20
+translate piglatin tutorial_playing_f30f1979:
+
+    # e "One of the nice things about Ren'Py is that the engine provides many of these features for you. You can spend your time creating your game, and let us provide these things."
+    e "Neoay ofay hetay icenay hingstay aboutay Enray'Ypay isay hattay hetay engineay rovidespay anymay ofay hesetay eaturesfay orfay ouyay. Ouyay ancay pendsay ouryay imetay reatingcay ouryay amegay, anday etlay usay rovidepay hesetay hingstay."
+
+# ../tutorial_playing.rpyc:22
+translate piglatin tutorial_playing_afa743e7:
+
+    # e "While you're in the game, you can access the game menu by right clicking or hitting the escape key."
+    e "Hileway ouyay'eray inay hetay amegay, ouyay ancay accessay hetay amegay enumay ybay ightray ickingclay oray ittinghay hetay escapeay eykay."
+
+# ../tutorial_playing.rpyc:28
+translate piglatin tutorial_playing_8360224a:
+
+    # e "When you first enter the game menu, you'll see the save screen. Clicking on a numbered slot will save the game."
+    e "Henway ouyay irstfay enteray hetay amegay enumay, ouyay'llay eesay hetay avesay creensay. Lickingcay onay aay umberednay otslay illway avesay hetay amegay."
+
+# ../tutorial_playing.rpyc:30
+translate piglatin tutorial_playing_6d0ef6c9:
+
+    # e "Unlike other engines, Ren'Py doesn't limit the number of save slots that you can use."
+    e "Nlikeuay otheray enginesay, Enray'Ypay oesnday'tay imitlay hetay umbernay ofay avesay otsslay hattay ouyay ancay useay."
+
+# ../tutorial_playing.rpyc:32
+translate piglatin tutorial_playing_fea05c6b:
+
+    # e "The load screen looks quite similar to the save screen, and lets you load a game from a save slot."
+    e "Hetay oadlay creensay ookslay uiteqay imilarsay otay hetay avesay creensay, anday etslay ouyay oadlay aay amegay omfray aay avesay otslay."
+
+# ../tutorial_playing.rpyc:34
+translate piglatin tutorial_playing_8e7e83a8:
+
+    # e "It also lets you load one of the auto-saves that Ren'Py makes for you."
+    e "Tiay alsoay etslay ouyay oadlay oneay ofay hetay autoay-avessay hattay Enray'Ypay akesmay orfay ouyay."
+
+# ../tutorial_playing.rpyc:39
+translate piglatin tutorial_playing_2bad7992:
+
+    # e "The other screen of the game menu is the preferences screen."
+    e "Hetay otheray creensay ofay hetay amegay enumay isay hetay referencespay creensay."
+
+# ../tutorial_playing.rpyc:41
+translate piglatin tutorial_playing_eaac8ba9:
+
+    # e "This screen lets you decide how Ren'Py displays, pick what Ren'Py skips, control text speed and auto-click speed, and adjust sound, music, and voice volumes."
+    e "Histay creensay etslay ouyay ecideday owhay Enray'Ypay isplaysday, ickpay hatway Enray'Ypay kipssay, ontrolcay exttay peedsay anday autoay-ickclay peedsay, anday adjustay oundsay, usicmay, anday oicevay olumesvay."
+
+# ../tutorial_playing.rpyc:43
+translate piglatin tutorial_playing_b1562a34:
+
+    # e "The game menu also lets you end the game and return to the main menu, or quit Ren'Py entirely."
+    e "Hetay amegay enumay alsoay etslay ouyay enday hetay amegay anday eturnray otay hetay ainmay enumay, oray uitqay Enray'Ypay entirelyay."
+
+# ../tutorial_playing.rpyc:48
+translate piglatin tutorial_playing_790f9dc7:
+
+    # e "While the default game menus look a bit generic, with a little work they can be customized or even entirely replaced, allowing you to create menus as unique as your game."
+    e "Hileway hetay efaultday amegay enusmay ooklay aay itbay enericgay, ithway aay ittlelay orkway heytay ancay ebay ustomizedcay oray evenay entirelyay eplacedray, allowingay ouyay otay reatecay enusmay asay uniqueay asay ouryay amegay."
+
+# ../tutorial_playing.rpyc:54
+translate piglatin tutorial_playing_bc29822e:
+
+    # e "While inside the game, there are a few more things you can do."
+    e "Hileway insideay hetay amegay, heretay areay aay ewfay oremay hingstay ouyay ancay oday."
+
+# ../tutorial_playing.rpyc:56
+translate piglatin tutorial_playing_dc0f9cf7:
+
+    # e "When I'm liking a visual novel, I want to see all the endings. Ren'Py's skip function lets me easily do this, by skipping text that I've already seen."
+    e "Henway Iay'may ikinglay aay isualvay ovelnay, Iay antway otay eesay allay hetay endingsay. Enray'Ypay'say kipsay unctionfay etslay emay easilyay oday histay, ybay kippingsay exttay hattay Iay'evay alreadyay eensay."
+
+# ../tutorial_playing.rpyc:58
+translate piglatin tutorial_playing_6dded697:
+
+    # e "I can skip a few lines by holding down Control, or I can toggle skip mode by pressing tab."
+    e "Iay ancay kipsay aay ewfay ineslay ybay oldinghay ownday Ontrolcay, oray Iay ancay oggletay kipsay odemay ybay ressingpay abtay."
+
+# ../tutorial_playing.rpyc:60
+translate piglatin tutorial_playing_d3553fbe:
+
+    # e "By default, we only skip read text, so this won't do anything the first time through the game."
+    e "Ybay efaultday, eway onlyay kipsay eadray exttay, osay histay onway'tay oday anythingay hetay irstfay imetay hroughtay hetay amegay."
+
+# ../tutorial_playing.rpyc:62
+translate piglatin tutorial_playing_9a605016:
+
+    # e "Pressing the 's' key saves a screenshot to disk, so I can upload pictures of the game to websites like {a=http://www.renpy.org}renpy.org{/a}."
+    e "Ressingpay hetay 'say' eykay avessay aay creenshotsay otay iskday, osay Iay ancay uploaday icturespay ofay hetay amegay otay ebsitesway ikelay {a=http://www.renpy.org}enpyray.orgay{/a}."
+
+# ../tutorial_playing.rpyc:64
+translate piglatin tutorial_playing_a9c70134:
+
+    # e "Finally, there's rollback, which lets you go back in time to previous screens, letting you re-read text."
+    e "Inallyfay, heretay'say ollbackray, hichway etslay ouyay ogay ackbay inay imetay otay reviouspay creenssay, ettinglay ouyay eray-eadray exttay."
+
+# ../tutorial_playing.rpyc:65
+translate piglatin tutorial_playing_ffcaf528:
+
+    # e "Would you like to hear more about rollback?" nointeract
+    e "Ouldway ouyay ikelay otay earhay oremay aboutay ollbackray?" nointeract
+
+# ../tutorial_playing.rpyc:80
+translate piglatin tutorial_rollback_40b09eaf:
+
+    # e "You can invoke a rollback by scrolling the mouse wheel up, or by pushing the page up key. That'll bring you back to the previous screen."
+    e "Ouyay ancay invokeay aay ollbackray ybay crollingsay hetay ousemay heelway upay, oray ybay ushingpay hetay agepay upay eykay. Hattay'llay ingbray ouyay ackbay otay hetay reviouspay creensay."
+
+# ../tutorial_playing.rpyc:82
+translate piglatin tutorial_rollback_041be71b:
+
+    # e "While at a previous screen, you can roll forward by scrolling the mouse wheel down, or pushing the page down key."
+    e "Hileway atay aay reviouspay creensay, ouyay ancay ollray orwardfay ybay crollingsay hetay ousemay heelway ownday, oray ushingpay hetay agepay ownday eykay."
+
+# ../tutorial_playing.rpyc:84
+translate piglatin tutorial_rollback_1d0e55c3:
+
+    # e "Rolling forward through a menu will make the same choice you did last time. But unlike other engines, Ren'Py's rollback system allows you to make a different choice."
+    e "Ollingray orwardfay hroughtay aay enumay illway akemay hetay amesay oicechay ouyay idday astlay imetay. Utbay unlikeay otheray enginesay, Enray'Ypay'say ollbackray ystemsay allowsay ouyay otay akemay aay ifferentday oicechay."
+
+# ../tutorial_playing.rpyc:86
+translate piglatin tutorial_rollback_a4633f53:
+
+    # e "You can try it by rolling back through the last menu, and saying 'No'."
+    e "Ouyay ancay ytray itay ybay ollingray ackbay hroughtay hetay astlay enumay, anday ayingsay 'Onay'."
+
+# ../tutorial_playing.rpyc:88
+translate piglatin tutorial_rollback_a30f8a06:
+
+    # e "Press page up, or scroll up the mouse wheel."
+    e "Resspay agepay upay, oray crollsay upay hetay ousemay heelway."
+
+# ../tutorial_playing.rpyc:92
+translate piglatin tutorial_rollback_de0b6f5a:
+
+    # e "Well, are you going to try it?"
+    e "Ellway, areay ouyay oinggay otay ytray itay?"
+
+# ../tutorial_playing.rpyc:94
+translate piglatin tutorial_rollback_6bbdedaa:
+
+    # e "Your loss."
+    e "Ouryay osslay."
+
+# ../tutorial_playing.rpyc:96
+translate piglatin tutorial_rollback_dce979d4:
+
+    # e "Moving on."
+    e "Ovingmay onay."
+
+# ../tutorial_playing.rpyc:102
+translate piglatin tutorial_rollback_done_54d6ee45:
+
+    # e "By allowing Ren'Py to take care of out-of-game issues like loading and saving, you can focus on making your game, while still giving users the experience they've come to expect."
+    e "Ybay allowingay Enray'Ypay otay aketay arecay ofay outay-ofay-amegay issuesay ikelay oadinglay anday avingsay, ouyay ancay ocusfay onay akingmay ouryay amegay, hileway illstay ivinggay usersay hetay experienceay heytay'evay omecay otay expectay."
+
diff --git a/tutorial/game/tl/piglatin/tutorial_quickstart.rpy b/tutorial/game/tl/piglatin/tutorial_quickstart.rpy
new file mode 100644
index 0000000..5877636
--- /dev/null
+++ b/tutorial/game/tl/piglatin/tutorial_quickstart.rpy
@@ -0,0 +1,663 @@
+
+# ../tutorial_quickstart.rpyc:20
+translate piglatin tutorial_dialogue_f6d3ddd3:
+
+    # e "Probably the best way to learn Ren'Py is to see it in action. In this tutorial, I'll be showing you some of the things Ren'Py can do, and also showing you how to do them."
+    e "Robablypay hetay estbay ayway otay earnlay Enray'Ypay isay otay eesay itay inay actionay. Niay histay utorialtay, Iay'llay ebay owingshay ouyay omesay ofay hetay hingstay Enray'Ypay ancay oday, anday alsoay owingshay ouyay owhay otay oday hemtay."
+
+# ../tutorial_quickstart.rpyc:25
+translate piglatin tutorial_dialogue_49c65906:
+
+    # e "Code examples will show up in a window like the one above. You'll need to click outside of the example window in order to advance the tutorial."
+    e "Odecay examplesay illway owshay upay inay aay indowway ikelay hetay oneay aboveay. Ouyay'llay eednay otay ickclay outsideay ofay hetay exampleay indowway inay orderay otay advanceay hetay utorialtay."
+
+# ../tutorial_quickstart.rpyc:27
+translate piglatin tutorial_dialogue_5c2cb6f9:
+
+    # e "When an example is bigger than the screen, you can scroll around in it using the mouse wheel or by simply dragging the mouse."
+    e "Henway anay exampleay isay iggerbay hantay hetay creensay, ouyay ancay crollsay arounday inay itay usingay hetay ousemay heelway oray ybay implysay raggingday hetay ousemay."
+
+# ../tutorial_quickstart.rpyc:32
+translate piglatin tutorial_dialogue_3528a1fe:
+
+    # e "To create a new project, you can click New Project in the Ren'Py launcher."
+    e "Otay reatecay aay ewnay rojectpay, ouyay ancay ickclay Ewnay Rojectpay inay hetay Enray'Ypay auncherlay."
+
+# ../tutorial_quickstart.rpyc:34
+translate piglatin tutorial_dialogue_3ef9231c:
+
+    # e "If it's your first time making a Ren'Py game, you'll be asked to pick a directory to store your projects in."
+    e "Fiay itay'say ouryay irstfay imetay akingmay aay Enray'Ypay amegay, ouyay'llay ebay askeday otay ickpay aay irectoryday otay orestay ouryay rojectspay inay."
+
+# ../tutorial_quickstart.rpyc:36
+translate piglatin tutorial_dialogue_15734bf9:
+
+    # e "You'll then be asked for the name of the project, and also to choose a theme for the interface."
+    e "Ouyay'llay hentay ebay askeday orfay hetay amenay ofay hetay rojectpay, anday alsoay otay oosechay aay hemetay orfay hetay interfaceay."
+
+# ../tutorial_quickstart.rpyc:38
+translate piglatin tutorial_dialogue_46edb91d:
+
+    # e "Once that's done, Ren'Py will automatically create a directory and fill it with the files needed to make a project."
+    e "Nceoay hattay'say oneday, Enray'Ypay illway automaticallyay reatecay aay irectoryday anday illfay itay ithway hetay ilesfay eedednay otay akemay aay rojectpay."
+
+# ../tutorial_quickstart.rpyc:40
+translate piglatin tutorial_dialogue_66d639af:
+
+    # e "If you have Java installed, you'll be able to click Edit Script to open your project's script."
+    e "Fiay ouyay avehay Avajay installeday, ouyay'llay ebay ableay otay ickclay Diteay Criptsay otay openay ouryay rojectpay'say criptsay."
+
+# ../tutorial_quickstart.rpyc:42
+translate piglatin tutorial_dialogue_f0d66410:
+
+    # e "Let's see the simplest possible Ren'Py game."
+    e "Etlay'say eesay hetay implestsay ossiblepay Enray'Ypay amegay."
+
+# ../tutorial_quickstart.rpyc:48
+translate piglatin tutorial_dialogue_3e6b0068:
+
+    # "Wow, It's really really dark in here."
+    "Owway, Tiay'say eallyray eallyray arkday inay erehay."
+
+# ../tutorial_quickstart.rpyc:50
+translate piglatin tutorial_dialogue_5072a404:
+
+    # "Lucy" "Better watch out. You don't want to be eaten by a Grue."
+    "Lucy" "Etterbay atchway outay. Ouyay onday'tay antway otay ebay eatenay ybay aay Ruegay."
+
+# ../tutorial_quickstart.rpyc:59
+translate piglatin tutorial_dialogue_871db44f:
+
+    # e "I'll show you the code for that example."
+    e "Iay'llay owshay ouyay hetay odecay orfay hattay exampleay."
+
+# ../tutorial_quickstart.rpyc:61
+translate piglatin tutorial_dialogue_6943c36d:
+
+    # e "This code demonstrates two kinds of Ren'Py statements, labels and say statements."
+    e "Histay odecay emonstratesday wotay indskay ofay Enray'Ypay atementsstay, abelslay anday aysay atementsstay."
+
+# ../tutorial_quickstart.rpyc:63
+translate piglatin tutorial_dialogue_bc7ec147:
+
+    # e "The first line is a label statement. The label statement is used to give a name to a place in the program."
+    e "Hetay irstfay inelay isay aay abellay atementstay. Hetay abellay atementstay isay useday otay ivegay aay amenay otay aay aceplay inay hetay rogrampay."
+
+# ../tutorial_quickstart.rpyc:65
+translate piglatin tutorial_dialogue_b20db833:
+
+    # e "In this case, we're naming a place \"start\". The start label is special, as it marks the place a game begins running."
+    e "Niay histay asecay, eway'eray amingnay aay aceplay \"artstay\". Hetay artstay abellay isay pecialsay, asay itay arksmay hetay aceplay aay amegay eginsbay unningray."
+
+# ../tutorial_quickstart.rpyc:67
+translate piglatin tutorial_dialogue_b0afbe96:
+
+    # e "The next line is a simple say statement. It consists of a string beginning with a double-quote, and ending at the next double-quote."
+    e "Hetay extnay inelay isay aay implesay aysay atementstay. Tiay onsistscay ofay aay ringstay eginningbay ithway aay oubleday-uoteqay, anday endingay atay hetay extnay oubleday-uoteqay."
+
+# ../tutorial_quickstart.rpyc:69
+translate piglatin tutorial_dialogue_628c9e4c:
+
+    # e "Special characters in strings can be escaped with a backslash. To include \" in a string, we have to write \\\"."
+    e "Pecialsay aracterschay inay ringsstay ancay ebay escapeday ithway aay ackslashbay. Otay includeay \" inay aay ringstay, eway avehay otay riteway \\\"."
+
+# ../tutorial_quickstart.rpyc:74
+translate piglatin tutorial_dialogue_3e6b0068_1:
+
+    # "Wow, It's really really dark in here."
+    "Owway, Tiay'say eallyray eallyray arkday inay erehay."
+
+# ../tutorial_quickstart.rpyc:82
+translate piglatin tutorial_dialogue_d7f0b5b7:
+
+    # e "When Ren'Py sees a single string on a line by itself, it uses the narrator to say that string. So a single string can be used to express a character's thoughts."
+    e "Henway Enray'Ypay eessay aay inglesay ringstay onay aay inelay ybay itselfay, itay usesay hetay arratornay otay aysay hattay ringstay. Osay aay inglesay ringstay ancay ebay useday otay expressay aay aracterchay'say houghtstay."
+
+# ../tutorial_quickstart.rpyc:87
+translate piglatin tutorial_dialogue_5072a404_1:
+
+    # "Lucy" "Better watch out. You don't want to be eaten by a Grue."
+    "Lucy" "Etterbay atchway outay. Ouyay onday'tay antway otay ebay eatenay ybay aay Ruegay."
+
+# ../tutorial_quickstart.rpyc:95
+translate piglatin tutorial_dialogue_9dd2d543:
+
+    # e "When we have two strings separated by a space, the first is used as the character's name, and the second is what the character is saying."
+    e "Henway eway avehay wotay ringsstay eparatedsay ybay aay pacesay, hetay irstfay isay useday asay hetay aracterchay'say amenay, anday hetay econdsay isay hatway hetay aracterchay isay ayingsay."
+
+# ../tutorial_quickstart.rpyc:97
+translate piglatin tutorial_dialogue_64ffe685:
+
+    # e "This two-argument form of the say statement is used for dialogue, where a character is speaking out loud."
+    e "Histay wotay-argumentay ormfay ofay hetay aysay atementstay isay useday orfay ialogueday, hereway aay aracterchay isay peakingsay outay oudlay."
+
+# ../tutorial_quickstart.rpyc:99
+translate piglatin tutorial_dialogue_97a33275:
+
+    # e "If you'd like, you can run this game yourself by erasing everything in your project's script.rpy file, and replacing it with the code in the box above."
+    e "Fiay ouyay'day ikelay, ouyay ancay unray histay amegay ourselfyay ybay erasingay everythingay inay ouryay rojectpay'say criptsay.pyray ilefay, anday eplacingray itay ithway hetay odecay inay hetay oxbay aboveay."
+
+# ../tutorial_quickstart.rpyc:101
+translate piglatin tutorial_dialogue_c5e70d7e:
+
+    # e "Be sure to preserve the spacing before lines. That's known as indentation, and it's used to help Ren'Py group lines of script into blocks."
+    e "Ebay uresay otay reservepay hetay pacingsay eforebay ineslay. Hattay'say nownkay asay indentationay, anday itay'say useday otay elphay Enray'Ypay oupgray ineslay ofay criptsay intoay ocksblay."
+
+# ../tutorial_quickstart.rpyc:106
+translate piglatin tutorial_dialogue_90719f73:
+
+    # e "Using a string for a character's name is inconvenient, for two reasons."
+    e "Singuay aay ringstay orfay aay aracterchay'say amenay isay inconvenientay, orfay wotay easonsray."
+
+# ../tutorial_quickstart.rpyc:108
+translate piglatin tutorial_dialogue_910f286a:
+
+    # e "The first is that's it's a bit verbose. While typing \"Lucy\" isn't so bad, imagine if you had to type \"Eileen Richardson\" thousands of times."
+    e "Hetay irstfay isay hattay'say itay'say aay itbay erbosevay. Hileway ypingtay \"Ucylay\" isnay'tay osay adbay, imagineay ifay ouyay adhay otay ypetay \"Ileeneay Ichardsonray\" housandstay ofay imestay."
+
+# ../tutorial_quickstart.rpyc:110
+translate piglatin tutorial_dialogue_9c9d59c2:
+
+    # e "The second is that it doesn't leave any place to put styling, which can change the look of a character."
+    e "Hetay econdsay isay hattay itay oesnday'tay eavelay anyay aceplay otay utpay ylingstay, hichway ancay angechay hetay ooklay ofay aay aracterchay."
+
+# ../tutorial_quickstart.rpyc:112
+translate piglatin tutorial_dialogue_2a2d1e51:
+
+    # e "To solve these problems, Ren'Py lets you define Characters."
+    e "Otay olvesay hesetay roblemspay, Enray'Ypay etslay ouyay efineday Haracterscay."
+
+# ../tutorial_quickstart.rpyc:116
+translate piglatin tutorial_dialogue_16e8c5fd:
+
+    # e "Here's an example Character definition. It begins with the word \"define\". That tells Ren'Py that we are defining something."
+    e "Erehay'say anay exampleay Haractercay efinitionday. Tiay eginsbay ithway hetay ordway \"efineday\". Hattay ellstay Enray'Ypay hattay eway areay efiningday omethingsay."
+
+# ../tutorial_quickstart.rpyc:118
+translate piglatin tutorial_dialogue_34fe5aa0:
+
+    # e "Define is followed by a short name for the character, like \"l\". We'll be able to use that short name when writing dialogue."
+    e "Efineday isay ollowedfay ybay aay ortshay amenay orfay hetay aracterchay, ikelay \"lay\". Eway'llay ebay ableay otay useay hattay ortshay amenay henway ritingway ialogueday."
+
+# ../tutorial_quickstart.rpyc:120
+translate piglatin tutorial_dialogue_67f90201:
+
+    # e "This is followed by an equals sign, and the thing that we're defining. In this case, it's a Character."
+    e "Histay isay ollowedfay ybay anay equalsay ignsay, anday hetay hingtay hattay eway'eray efiningday. Niay histay asecay, itay'say aay Haractercay."
+
+# ../tutorial_quickstart.rpyc:122
+translate piglatin tutorial_dialogue_4e454a89:
+
+    # e "On the first line, the character's name is given to be \"Lucy\", and her name will be drawn a reddish color."
+    e "Noay hetay irstfay inelay, hetay aracterchay'say amenay isay ivengay otay ebay \"Ucylay\", anday erhay amenay illway ebay rawnday aay eddishray olorcay."
+
+# ../tutorial_quickstart.rpyc:124
+translate piglatin tutorial_dialogue_db11f026:
+
+    # e "These short names are case-sensitive. Capital L is a different name from lower-case l, so you'll need to be careful about that."
+    e "Hesetay ortshay amesnay areay asecay-ensitivesay. Apitalcay Lay isay aay ifferentday amenay omfray owerlay-asecay lay, osay ouyay'llay eednay otay ebay arefulcay aboutay hattay."
+
+# ../tutorial_quickstart.rpyc:128
+translate piglatin tutorial_dialogue_1d161320:
+
+    # e "Now that we have a character defined, we can use it to say dialogue."
+    e "Ownay hattay eway avehay aay aracterchay efinedday, eway ancay useay itay otay aysay ialogueday."
+
+# ../tutorial_quickstart.rpyc:134
+translate piglatin tutorial_dialogue_3710169c:
+
+    # l "Why are you trying to put words into my mouth? And who are you calling \"it\"?"
+    l "Hyway areay ouyay yingtray otay utpay ordsway intoay ymay outhmay? Ndaay howay areay ouyay allingcay \"itay\"?"
+
+# ../tutorial_quickstart.rpyc:136
+translate piglatin tutorial_dialogue_6d463776:
+
+    # l "What's more, what are you going to do about the Grue problem? Are you just going to leave me here?"
+    l "Hatway'say oremay, hatway areay ouyay oinggay otay oday aboutay hetay Ruegay roblempay? Reaay ouyay ustjay oinggay otay eavelay emay erehay?"
+
+# ../tutorial_quickstart.rpyc:145
+translate piglatin tutorial_dialogue_023bcd31:
+
+    # e "Here's the full game, including the two new lines of dialogue, both of which use the Character we defined to say dialogue."
+    e "Erehay'say hetay ullfay amegay, includingay hetay wotay ewnay ineslay ofay ialogueday, othbay ofay hichway useay hetay Haractercay eway efinedday otay aysay ialogueday."
+
+# ../tutorial_quickstart.rpyc:147
+translate piglatin tutorial_dialogue_48bb9547:
+
+    # e "The one-argument form of the say statement is unchanged, but in the two-argument form, instead of the first string we can use a short name."
+    e "Hetay oneay-argumentay ormfay ofay hetay aysay atementstay isay unchangeday, utbay inay hetay wotay-argumentay ormfay, insteaday ofay hetay irstfay ringstay eway ancay useay aay ortshay amenay."
+
+# ../tutorial_quickstart.rpyc:149
+translate piglatin tutorial_dialogue_56a9936f:
+
+    # e "When this say statement is run, Ren'Py will look up the short name, which is really a Python variable. It will then use the associated Character to show the dialogue."
+    e "Henway histay aysay atementstay isay unray, Enray'Ypay illway ooklay upay hetay ortshay amenay, hichway isay eallyray aay Ythonpay ariablevay. Tiay illway hentay useay hetay associateday Haractercay otay owshay hetay ialogueday."
+
+# ../tutorial_quickstart.rpyc:151
+translate piglatin tutorial_dialogue_d5984a21:
+
+    # e "The Character object controls who is speaking, the color of their name, and many other properties of the dialogue."
+    e "Hetay Haractercay objectay ontrolscay howay isay peakingsay, hetay olorcay ofay heirtay amenay, anday anymay otheray ropertiespay ofay hetay ialogueday."
+
+# ../tutorial_quickstart.rpyc:155
+translate piglatin tutorial_dialogue_a5bcac8b:
+
+    # e "Since the bulk of a visual novel is dialogue, we've tried to make it as easy to write as possible."
+    e "Incesay hetay ulkbay ofay aay isualvay ovelnay isay ialogueday, eway'evay iedtray otay akemay itay asay easyay otay riteway asay ossiblepay."
+
+# ../tutorial_quickstart.rpyc:157
+translate piglatin tutorial_dialogue_6b9a42d0:
+
+    # e "Hopefully, by allowing the use of short names for characters, we've succeeded."
+    e "Opefullyhay, ybay allowingay hetay useay ofay ortshay amesnay orfay aracterschay, eway'evay ucceededsay."
+
+# ../tutorial_quickstart.rpyc:163
+translate piglatin tutorial_images_e09ac970:
+
+    # e "A visual novel isn't much without images. So let's add some images to our little game."
+    e "Aay isualvay ovelnay isnay'tay uchmay ithoutway imagesay. Osay etlay'say adday omesay imagesay otay ouray ittlelay amegay."
+
+# ../tutorial_quickstart.rpyc:165
+translate piglatin tutorial_images_a664a8bc:
+
+    # e "Before we can show images, we must first put the image files into the game directory."
+    e "Eforebay eway ancay owshay imagesay, eway ustmay irstfay utpay hetay imageay ilesfay intoay hetay amegay irectoryday."
+
+# ../tutorial_quickstart.rpyc:167
+translate piglatin tutorial_images_1d6236ee:
+
+    # e "The easiest way to open the game directory is to click the Game Directory button in the Ren'Py launcher."
+    e "Hetay easiestay ayway otay openay hetay amegay irectoryday isay otay ickclay hetay Amegay Irectoryday uttonbay inay hetay Enray'Ypay auncherlay."
+
+# ../tutorial_quickstart.rpyc:169
+translate piglatin tutorial_images_e41986f0:
+
+    # e "All of the image files we'll be using here are in the game directory, under the tutorial directory, under the Ren'Py directory."
+    e "Llaay ofay hetay imageay ilesfay eway'llay ebay usingay erehay areay inay hetay amegay irectoryday, underay hetay utorialtay irectoryday, underay hetay Enray'Ypay irectoryday."
+
+# ../tutorial_quickstart.rpyc:173
+translate piglatin tutorial_images_0b9f7257:
+
+    # e "Here are some sample image definitions. They should be placed at the start of the file, without any indentation."
+    e "Erehay areay omesay amplesay imageay efinitionsday. Heytay ouldshay ebay acedplay atay hetay artstay ofay hetay ilefay, ithoutway anyay indentationay."
+
+# ../tutorial_quickstart.rpyc:175
+translate piglatin tutorial_images_5d67054c:
+
+    # e "The image statement begins with the keyword \"image\", which is followed by an image name, a space-separated list of words."
+    e "Hetay imageay atementstay eginsbay ithway hetay eywordkay \"imageay\", hichway isay ollowedfay ybay anay imageay amenay, aay pacesay-eparatedsay istlay ofay ordsway."
+
+# ../tutorial_quickstart.rpyc:177
+translate piglatin tutorial_images_4c9a51ec:
+
+    # e "The first word in the image name is the image tag. For the first image the tag is \"bg\", and for the others, it's \"lucy\"."
+    e "Hetay irstfay ordway inay hetay imageay amenay isay hetay imageay agtay. Orfay hetay irstfay imageay hetay agtay isay \"gbay\", anday orfay hetay othersay, itay'say \"ucylay\"."
+
+# ../tutorial_quickstart.rpyc:179
+translate piglatin tutorial_images_bda71aa3:
+
+    # e "This is followed by an equals sign, and a string giving an image name."
+    e "Histay isay ollowedfay ybay anay equalsay ignsay, anday aay ringstay ivinggay anay imageay amenay."
+
+# ../tutorial_quickstart.rpyc:181
+translate piglatin tutorial_images_6d88aaa3:
+
+    # e "A string giving an image name is only one of the dozens of kinds of displayable that Ren'Py supports."
+    e "Aay ringstay ivinggay anay imageay amenay isay onlyay oneay ofay hetay ozensday ofay indskay ofay isplayableday hattay Enray'Ypay upportssay."
+
+# ../tutorial_quickstart.rpyc:185
+translate piglatin tutorial_images_76b954de:
+
+    # e "Let's see what those look like in the game."
+    e "Etlay'say eesay hatway hosetay ooklay ikelay inay hetay amegay."
+
+# ../tutorial_quickstart.rpyc:192
+translate piglatin tutorial_images_f04e72ea:
+
+    # l "Now that the lights are on, we don't have to worry about Grues anymore."
+    l "Ownay hattay hetay ightslay areay onay, eway onday'tay avehay otay orryway aboutay Ruesgay anymoreay."
+
+# ../tutorial_quickstart.rpyc:196
+translate piglatin tutorial_images_d77ffa1c:
+
+    # l "But what's the deal with me being in a cave? Eileen gets to be out in the sun, and I'm stuck here!"
+    l "Utbay hatway'say hetay ealday ithway emay eingbay inay aay avecay? Ileeneay etsgay otay ebay outay inay hetay unsay, anday Iay'may uckstay erehay!"
+
+# ../tutorial_quickstart.rpyc:205
+translate piglatin tutorial_images_6c0c938b:
+
+    # e "Here's the script for that scene. Notice how it includes two new statements, the scene and show statement."
+    e "Erehay'say hetay criptsay orfay hattay cenesay. Oticenay owhay itay includesay wotay ewnay atementsstay, hetay cenesay anday owshay atementstay."
+
+# ../tutorial_quickstart.rpyc:207
+translate piglatin tutorial_images_1a4660b9:
+
+    # e "The scene statement clears the screen, and then adds a background image."
+    e "Hetay cenesay atementstay earsclay hetay creensay, anday hentay addsay aay ackgroundbay imageay."
+
+# ../tutorial_quickstart.rpyc:209
+translate piglatin tutorial_images_672c8cb8:
+
+    # e "The show statement adds a background image on top of all the other images on the screen."
+    e "Hetay owshay atementstay addsay aay ackgroundbay imageay onay optay ofay allay hetay otheray imagesay onay hetay creensay."
+
+# ../tutorial_quickstart.rpyc:211
+translate piglatin tutorial_images_2fc7baee:
+
+    # e "If there was already an image with the same tag, the new image is used to replace the old one."
+    e "Fiay heretay asway alreadyay anay imageay ithway hetay amesay agtay, hetay ewnay imageay isay useday otay eplaceray hetay olday oneay."
+
+# ../tutorial_quickstart.rpyc:213
+translate piglatin tutorial_images_802825f2:
+
+    # e "Changes to the list of shown images take place instantly, so in the example, the user won't see the background by itself."
+    e "Hangescay otay hetay istlay ofay ownshay imagesay aketay aceplay instantlyay, osay inay hetay exampleay, hetay useray onway'tay eesay hetay ackgroundbay ybay itselfay."
+
+# ../tutorial_quickstart.rpyc:215
+translate piglatin tutorial_images_b246dfdd:
+
+    # e "The second show statement has an at clause, which gives a location on the screen. Common locations are left, right, and center, but you can define many more."
+    e "Hetay econdsay owshay atementstay ashay anay atay auseclay, hichway ivesgay aay ocationlay onay hetay creensay. Ommoncay ocationslay areay eftlay, ightray, anday entercay, utbay ouyay ancay efineday anymay oremay."
+
+# ../tutorial_quickstart.rpyc:223
+translate piglatin tutorial_images_bc4ae0c7:
+
+    # e "In this example, we show an image named logo base, and we show it at a user-defined position, logopos."
+    e "Niay histay exampleay, eway owshay anay imageay amednay ogolay asebay, anday eway owshay itay atay aay useray-efinedday ositionpay, ogoposlay."
+
+# ../tutorial_quickstart.rpyc:225
+translate piglatin tutorial_images_9defda43:
+
+    # e "We also specify that it should be shown behind another image, in this case eileen. That's me."
+    e "Eway alsoay pecifysay hattay itay ouldshay ebay ownshay ehindbay anotheray imageay, inay histay asecay eileenay. Hattay'say emay."
+
+# ../tutorial_quickstart.rpyc:233
+translate piglatin tutorial_images_73d331f7:
+
+    # e "Finally, there's the hide statement, which hides the image with the given tag."
+    e "Inallyfay, heretay'say hetay idehay atementstay, hichway ideshay hetay imageay ithway hetay ivengay agtay."
+
+# ../tutorial_quickstart.rpyc:235
+translate piglatin tutorial_images_f34f62d5:
+
+    # e "Since the show statement replaces an image, and the scene statement clears the scene, it's pretty rare to hide an image."
+    e "Incesay hetay owshay atementstay eplacesray anay imageay, anday hetay cenesay atementstay earsclay hetay cenesay, itay'say rettypay areray otay idehay anay imageay."
+
+# ../tutorial_quickstart.rpyc:237
+translate piglatin tutorial_images_e06fa53a:
+
+    # e "The main use is for when a character or prop leaves before the scene is over."
+    e "Hetay ainmay useay isay orfay henway aay aracterchay oray roppay eaveslay eforebay hetay cenesay isay overay."
+
+# ../tutorial_quickstart.rpyc:246
+translate piglatin tutorial_transitions_9b8c714c:
+
+    # e "It can be somewhat jarring for the game to jump from place to place."
+    e "Tiay ancay ebay omewhatsay arringjay orfay hetay amegay otay umpjay omfray aceplay otay aceplay."
+
+# ../tutorial_quickstart.rpyc:253
+translate piglatin tutorial_transitions_3e290ea8:
+
+    # e "To help take some of edge off a change in scene, Ren'Py supports the use of transitions. Let's try that scene change again, but this time we'll use transitions."
+    e "Otay elphay aketay omesay ofay edgeay offay aay angechay inay cenesay, Enray'Ypay upportssay hetay useay ofay ansitionstray. Etlay'say ytray hattay cenesay angechay againay, utbay histay imetay eway'llay useay ansitionstray."
+
+# ../tutorial_quickstart.rpyc:268
+translate piglatin tutorial_transitions_9c0a86c4:
+
+    # e "That's much smoother. Here's some example code showing how we include transitions in our game."
+    e "Hattay'say uchmay moothersay. Erehay'say omesay exampleay odecay owingshay owhay eway includeay ansitionstray inay ouray amegay."
+
+# ../tutorial_quickstart.rpyc:270
+translate piglatin tutorial_transitions_3e490d40:
+
+    # e "It uses the with statement. The with statement causes the scene to transition from the last things shown to the things currently being shown."
+    e "Tiay usesay hetay ithway atementstay. Hetay ithway atementstay ausescay hetay cenesay otay ansitiontray omfray hetay astlay hingstay ownshay otay hetay hingstay urrentlycay eingbay ownshay."
+
+# ../tutorial_quickstart.rpyc:272
+translate piglatin tutorial_transitions_a43847df:
+
+    # e "It takes a transition as an argument. In this case, we're using the Dissolve transition. This transition takes as an argument the amount of time the dissolve should take."
+    e "Tiay akestay aay ansitiontray asay anay argumentay. Niay histay asecay, eway'eray usingay hetay Issolveday ansitiontray. Histay ansitiontray akestay asay anay argumentay hetay amountay ofay imetay hetay issolveday ouldshay aketay."
+
+# ../tutorial_quickstart.rpyc:274
+translate piglatin tutorial_transitions_6fcee414:
+
+    # e "In this case, each transition takes half a second."
+    e "Niay histay asecay, eachay ansitiontray akestay alfhay aay econdsay."
+
+# ../tutorial_quickstart.rpyc:278
+translate piglatin tutorial_transitions_033042cc:
+
+    # e "We can define a short name for a transition, using the define statement. Here, we're defining slowdissolve to be a dissolve that takes a whole second."
+    e "Eway ancay efineday aay ortshay amenay orfay aay ansitiontray, usingay hetay efineday atementstay. Erehay, eway'eray efiningday owdissolveslay otay ebay aay issolveday hattay akestay aay holeway econdsay."
+
+# ../tutorial_quickstart.rpyc:292
+translate piglatin tutorial_transitions_0ba82f00:
+
+    # e "Once a transition has been given a short name, we can use it in our game."
+    e "Nceoay aay ansitiontray ashay eenbay ivengay aay ortshay amenay, eway ancay useay itay inay ouray amegay."
+
+# ../tutorial_quickstart.rpyc:296
+translate piglatin tutorial_transitions_51ff9600:
+
+    # e "Ren'Py defines some transitions for you, like dissolve, fade, and move. For more complex or customized transitions, you'll have to define your own."
+    e "Enray'Ypay efinesday omesay ansitionstray orfay ouyay, ikelay issolveday, adefay, anday ovemay. Orfay oremay omplexcay oray ustomizedcay ansitionstray, ouyay'llay avehay otay efineday ouryay ownay."
+
+# ../tutorial_quickstart.rpyc:298
+translate piglatin tutorial_transitions_a7905e16:
+
+    # e "If you're interested, check out the Transitions Gallery section of the tutorial."
+    e "Fiay ouyay'eray interesteday, eckchay outay hetay Ransitionstay Allerygay ectionsay ofay hetay utorialtay."
+
+# ../tutorial_quickstart.rpyc:304
+translate piglatin tutorial_music_8b92efb7:
+
+    # e "Another important part of a visual novel or simulation game is the soundtrack."
+    e "Notheraay importantay artpay ofay aay isualvay ovelnay oray imulationsay amegay isay hetay oundtracksay."
+
+# ../tutorial_quickstart.rpyc:306
+translate piglatin tutorial_music_53910317:
+
+    # e "Ren'Py breaks sound up into channels. The channel a sound is played on determines if the sound loops, and if it is saved and restored with the game."
+    e "Enray'Ypay eaksbray oundsay upay intoay annelschay. Hetay annelchay aay oundsay isay ayedplay onay eterminesday ifay hetay oundsay oopslay, anday ifay itay isay avedsay anday estoredray ithway hetay amegay."
+
+# ../tutorial_quickstart.rpyc:308
+translate piglatin tutorial_music_a1e37712:
+
+    # e "When a sound is played on the music channel, it is looped, and it is saved when the game is saved."
+    e "Henway aay oundsay isay ayedplay onay hetay usicmay annelchay, itay isay oopedlay, anday itay isay avedsay henway hetay amegay isay avedsay."
+
+# ../tutorial_quickstart.rpyc:310
+translate piglatin tutorial_music_d9086d22:
+
+    # e "When the channel named sound is used, the sound is played once and then stopped. It isn't saved."
+    e "Henway hetay annelchay amednay oundsay isay useday, hetay oundsay isay ayedplay onceay anday hentay oppedstay. Tiay isnay'tay avedsay."
+
+# ../tutorial_quickstart.rpyc:312
+translate piglatin tutorial_music_45cd30df:
+
+    # e "The sounds themselves are stored in audio files. Ren'Py supports the Ogg Vorbis, mp3, mp2, and wav file formats."
+    e "Hetay oundssay hemselvestay areay oredstay inay audioay ilesfay. Enray'Ypay upportssay hetay Ggoay Orbisvay, p3may, p2may, anday avway ilefay ormatsfay."
+
+# ../tutorial_quickstart.rpyc:314
+translate piglatin tutorial_music_a776b6ad:
+
+    # e "Let's check out some of the commands that can effect the music channel."
+    e "Etlay'say eckchay outay omesay ofay hetay ommandscay hattay ancay effectay hetay usicmay annelchay."
+
+# ../tutorial_quickstart.rpyc:324
+translate piglatin tutorial_music_8b606a55:
+
+    # e "The play music command replaces the currently playing music, and replaces it with the named filename."
+    e "Hetay ayplay usicmay ommandcay eplacesray hetay urrentlycay ayingplay usicmay, anday eplacesray itay ithway hetay amednay ilenamefay."
+
+# ../tutorial_quickstart.rpyc:326
+translate piglatin tutorial_music_18650fe7:
+
+    # e "If you specify the currently-playing song, it will restart it."
+    e "Fiay ouyay pecifysay hetay urrentlycay-ayingplay ongsay, itay illway estartray itay."
+
+# ../tutorial_quickstart.rpyc:328
+translate piglatin tutorial_music_413d91fc:
+
+    # e "If the optional fadeout clause is given, it will fade out the currently playing music before starting the new music."
+    e "Fiay hetay optionalay adeoutfay auseclay isay ivengay, itay illway adefay outay hetay urrentlycay ayingplay usicmay eforebay artingstay hetay ewnay usicmay."
+
+# ../tutorial_quickstart.rpyc:330
+translate piglatin tutorial_music_a282a0e3:
+
+    # e "The queue statement also adds music to the named channel, but it waits until the currently-playing song is finished before playing the new music."
+    e "Hetay ueueqay atementstay alsoay addsay usicmay otay hetay amednay annelchay, utbay itay aitsway untilay hetay urrentlycay-ayingplay ongsay isay inishedfay eforebay ayingplay hetay ewnay usicmay."
+
+# ../tutorial_quickstart.rpyc:339
+translate piglatin tutorial_music_01ca6bad:
+
+    # e "The third statement is the stop statement. It stops the music playing on a channel. It too takes the fadeout clause."
+    e "Hetay hirdtay atementstay isay hetay opstay atementstay. Tiay opsstay hetay usicmay ayingplay onay aay annelchay. Tiay ootay akestay hetay adeoutfay auseclay."
+
+# ../tutorial_quickstart.rpyc:348
+translate piglatin tutorial_music_384937da:
+
+    # e "Unlike the music channel, playing a sound on the sound channel causes it to play only once."
+    e "Nlikeuay hetay usicmay annelchay, ayingplay aay oundsay onay hetay oundsay annelchay ausescay itay otay ayplay onlyay onceay."
+
+# ../tutorial_quickstart.rpyc:359
+translate piglatin tutorial_music_dc707e58:
+
+    # e "You can queue up multiple sounds on the sound channel, but they will only play one at a time."
+    e "Ouyay ancay ueueqay upay ultiplemay oundssay onay hetay oundsay annelchay, utbay heytay illway onlyay ayplay oneay atay aay imetay."
+
+# ../tutorial_quickstart.rpyc:366
+translate piglatin tutorial_music_abcc2214:
+
+    # e "Ren'Py has separate mixers for sound, music, and voices, so the player can adjust them as he likes."
+    e "Enray'Ypay ashay eparatesay ixersmay orfay oundsay, usicmay, anday oicesvay, osay hetay ayerplay ancay adjustay hemtay asay ehay ikeslay."
+
+# ../tutorial_quickstart.rpyc:372
+translate piglatin tutorial_menus_0426904b:
+
+    # e "Many visual novels require the player to make choices from in-game menus. These choices can add some challenge to the game, or adjust it to the player's preferences."
+    e "Anymay isualvay ovelsnay equireray hetay ayerplay otay akemay oiceschay omfray inay-amegay enusmay. Hesetay oiceschay ancay adday omesay allengechay otay hetay amegay, oray adjustay itay otay hetay ayerplay'say referencespay."
+
+# ../tutorial_quickstart.rpyc:374
+translate piglatin tutorial_menus_9c3b9154:
+
+    # e "Do you think your game will use menus?"
+    e "Oday ouyay hinktay ouryay amegay illway useay enusmay?"
+
+# ../tutorial_quickstart.rpyc:388
+translate piglatin choice1_yes_f6d95df8:
+
+    # e "While creating a multi-path visual novel can be a bit more work, it can yield a unique experience."
+    e "Hileway reatingcay aay ultimay-athpay isualvay ovelnay ancay ebay aay itbay oremay orkway, itay ancay ieldyay aay uniqueay experienceay."
+
+# ../tutorial_quickstart.rpyc:396
+translate piglatin choice1_no_72958b50:
+
+    # e "Games without menus are called kinetic novels, and there are dozens of them available to play."
+    e "Amesgay ithoutway enusmay areay alledcay inetickay ovelsnay, anday heretay areay ozensday ofay hemtay availableay otay ayplay."
+
+# ../tutorial_quickstart.rpyc:408
+translate piglatin choice1_done_acba9504:
+
+    # e "Here, you can see the code for that menu. If you scroll down, you can see the code we run after the menu."
+    e "Erehay, ouyay ancay eesay hetay odecay orfay hattay enumay. Fiay ouyay crollsay ownday, ouyay ancay eesay hetay odecay eway unray afteray hetay enumay."
+
+# ../tutorial_quickstart.rpyc:410
+translate piglatin choice1_done_d18afbdf:
+
+    # e "Menus are introduced by the menu statement. The menu statement takes an indented block, in which each line must contain a choice in quotes."
+    e "Enusmay areay introduceday ybay hetay enumay atementstay. Hetay enumay atementstay akestay anay indenteday ockblay, inay hichway eachay inelay ustmay ontaincay aay oicechay inay uotesqay."
+
+# ../tutorial_quickstart.rpyc:412
+translate piglatin choice1_done_2865a192:
+
+    # e "The choices must end with a colon, as each choice has its own block of Ren'Py code, that is run when that choice is selected."
+    e "Hetay oiceschay ustmay enday ithway aay oloncay, asay eachay oicechay ashay itsay ownay ockblay ofay Enray'Ypay odecay, hattay isay unray henway hattay oicechay isay electedsay."
+
+# ../tutorial_quickstart.rpyc:414
+translate piglatin choice1_done_59cac95d:
+
+    # e "Here, each block jumps to a label. While you could put small amounts of Ren'Py code inside a menu label, it's probably good practice to usually jump to a bigger block of code."
+    e "Erehay, eachay ockblay umpsjay otay aay abellay. Hileway ouyay ouldcay utpay mallsay amountsay ofay Enray'Ypay odecay insideay aay enumay abellay, itay'say robablypay oodgay racticepay otay usuallyay umpjay otay aay iggerbay ockblay ofay odecay."
+
+# ../tutorial_quickstart.rpyc:416
+translate piglatin choice1_done_2851a313:
+
+    # e "Scrolling down past the menu, you can see the labels that the menu jumps to. There are three labels here, named choice1_yes, choice1_no, and choice1_done."
+    e "Crollingsay ownday astpay hetay enumay, ouyay ancay eesay hetay abelslay hattay hetay enumay umpsjay otay. Heretay areay hreetay abelslay erehay, amednay oice1_yeschay, oice1_nochay, anday oice1_donechay."
+
+# ../tutorial_quickstart.rpyc:418
+translate piglatin choice1_done_ff761b03:
+
+    # e "When the first menu choice is picked, we jump to the choice1_yes, which runs two lines of script before jumping to choice1_done."
+    e "Henway hetay irstfay enumay oicechay isay ickedpay, eway umpjay otay hetay oice1_yeschay, hichway unsray wotay ineslay ofay criptsay eforebay umpingjay otay oice1_donechay."
+
+# ../tutorial_quickstart.rpyc:420
+translate piglatin choice1_done_664fe702:
+
+    # e "Similarly, picking the second choice jumps us to choice1_no, which also runs two lines of script."
+    e "Imilarlysay, ickingpay hetay econdsay oicechay umpsjay usay otay oice1_nochay, hichway alsoay unsray wotay ineslay ofay criptsay."
+
+# ../tutorial_quickstart.rpyc:422
+translate piglatin choice1_done_31d12b1e:
+
+    # e "The lines beginning with the dollar sign are lines of python code, which are used to set a flag based on the user's choice."
+    e "Hetay ineslay eginningbay ithway hetay ollarday ignsay areay ineslay ofay ythonpay odecay, hichway areay useday otay etsay aay agflay asedbay onay hetay useray'say oicechay."
+
+# ../tutorial_quickstart.rpyc:424
+translate piglatin choice1_done_88398d3e:
+
+    # e "The flag is named menu_flag, and it's set to True or False based on the user's choice. The if statement can be used to test a flag, so the game can remember the user's choices."
+    e "Hetay agflay isay amednay enu_flagmay, anday itay'say etsay otay Ruetay oray Alsefay asedbay onay hetay useray'say oicechay. Hetay ifay atementstay ancay ebay useday otay esttay aay agflay, osay hetay amegay ancay ememberray hetay useray'say oiceschay."
+
+# ../tutorial_quickstart.rpyc:432
+translate piglatin choice1_done_2828dbfc:
+
+    # e "For example, I remember that you plan to use menus in your game."
+    e "Orfay exampleay, Iay ememberray hattay ouyay anplay otay useay enusmay inay ouryay amegay."
+
+# ../tutorial_quickstart.rpyc:436
+translate piglatin choice1_done_503786e4:
+
+    # e "For example, I remember that you're planning to make a kinetic novel, without menus."
+    e "Orfay exampleay, Iay ememberray hattay ouyay'eray anningplay otay akemay aay inetickay ovelnay, ithoutway enusmay."
+
+# ../tutorial_quickstart.rpyc:441
+translate piglatin choice1_done_819e234a:
+
+    # e "Here's an example that shows how we can test a flag, and do different things if it is true or not."
+    e "Erehay'say anay exampleay hattay owsshay owhay eway ancay esttay aay agflay, anday oday ifferentday hingstay ifay itay isay uetray oray otnay."
+
+# ../tutorial_quickstart.rpyc:445
+translate piglatin choice1_done_47fa2268:
+
+    # e "Although we won't demonstrate it here, Ren'Py supports making decisions based on a combinations of points, flags, and other factors."
+    e "Lthoughaay eway onway'tay emonstrateday itay erehay, Enray'Ypay upportssay akingmay ecisionsday asedbay onay aay ombinationscay ofay ointspay, agsflay, anday otheray actorsfay."
+
+# ../tutorial_quickstart.rpyc:447
+translate piglatin choice1_done_826a600b:
+
+    # e "One of Ren'Py's big advantages is the flexibility using a scripting language like Python provides us. It lets us easily scale from kinetic novels to complex simulation games."
+    e "Neoay ofay Enray'Ypay'say igbay advantagesay isay hetay exibilityflay usingay aay criptingsay anguagelay ikelay Ythonpay rovidespay usay. Tiay etslay usay easilyay calesay omfray inetickay ovelsnay otay omplexcay imulationsay amesgay."
+
+# ../tutorial_quickstart.rpyc:449
+translate piglatin choice1_done_c2efd260:
+
+    # e "We look forward to seeing what you make with it."
+    e "Eway ooklay orwardfay otay eeingsay hatway ouyay akemay ithway itay."
+
+translate piglatin strings:
+
+    # tutorial_quickstart.rpy:5
+    old "Lucy"
+    new "Ucylay"
+
+    # tutorial_quickstart.rpy:377
+    old "Yes, I do."
+    new "Esyay, Iay oday."
+
+    # tutorial_quickstart.rpy:377
+    old "No, I don't."
+    new "Onay, Iay onday'tay."
+
diff --git a/tutorial/game/tl/piglatin/tutorial_sprite.rpy b/tutorial/game/tl/piglatin/tutorial_sprite.rpy
new file mode 100644
index 0000000..22928dd
--- /dev/null
+++ b/tutorial/game/tl/piglatin/tutorial_sprite.rpy
@@ -0,0 +1,49 @@
+
+# ../tutorial_sprite.rpyc:63
+translate piglatin tutorial_sprite_d2ca6a0c:
+
+    # e "Ren'Py supports a sprite system, which allows many similar objects to be shown on the screen at once."
+    e "Enray'Ypay upportssay aay pritesay ystemsay, hichway allowsay anymay imilarsay objectsay otay ebay ownshay onay hetay creensay atay onceay."
+
+# ../tutorial_sprite.rpyc:70
+translate piglatin tutorial_sprite_40df8d5d:
+
+    # e "The background behind me consists of one hundred and seventy-five stars, being moved at several different speeds, to give a starflight effect."
+    e "Hetay ackgroundbay ehindbay emay onsistscay ofay oneay undredhay anday eventysay-ivefay arsstay, eingbay ovedmay atay everalsay ifferentday peedssay, otay ivegay aay arflightstay effectay."
+
+# ../tutorial_sprite.rpyc:72
+translate piglatin tutorial_sprite_29c5e523:
+
+    # e "The OpenGL system should be able to animate this smoothly, but you might see a bit of stuttering if your computer is using software."
+    e "Hetay Pengloay ystemsay ouldshay ebay ableay otay animateay histay moothlysay, utbay ouyay ightmay eesay aay itbay ofay utteringstay ifay ouryay omputercay isay usingay oftwaresay."
+
+# ../tutorial_sprite.rpyc:74
+translate piglatin tutorial_sprite_90927173:
+
+    # e "You'll need to decide which older systems to support."
+    e "Ouyay'llay eednay otay ecideday hichway olderay ystemssay otay upportsay."
+
+# ../tutorial_sprite.rpyc:80
+translate piglatin tutorial_sprite_9afa1448:
+
+    # e "The sprite manager requires you to write a python function to move the sprites around."
+    e "Hetay pritesay anagermay equiresray ouyay otay riteway aay ythonpay unctionfay otay ovemay hetay pritessay arounday."
+
+# ../tutorial_sprite.rpyc:84
+translate piglatin tutorial_sprite_2c9a79ad:
+
+    # e "In many cases, all you need is something moving around the screen - like cherry blossoms, or snow."
+    e "Niay anymay asescay, allay ouyay eednay isay omethingsay ovingmay arounday hetay creensay - ikelay errychay ossomsblay, oray nowsay."
+
+# ../tutorial_sprite.rpyc:86
+translate piglatin tutorial_sprite_595d03b3:
+
+    # e "That's what the snowblossom function gives you - a simple way to have things falling from the top of the screen."
+    e "Hattay'say hatway hetay nowblossomsay unctionfay ivesgay ouyay - aay implesay ayway otay avehay hingstay allingfay omfray hetay optay ofay hetay creensay."
+
+# ../tutorial_sprite.rpyc:91
+translate piglatin tutorial_sprite_4f82c848:
+
+    # e "And that's it for sprites."
+    e "Ndaay hattay'say itay orfay pritessay."
+
diff --git a/tutorial/game/tl/piglatin/tutorial_video.rpy b/tutorial/game/tl/piglatin/tutorial_video.rpy
new file mode 100644
index 0000000..1253e86
--- /dev/null
+++ b/tutorial/game/tl/piglatin/tutorial_video.rpy
@@ -0,0 +1,43 @@
+
+# ../tutorial_video.rpyc:11
+translate piglatin tutorial_video_f34a17f5:
+
+    # e "Ren'Py supports playing movies. There are two ways of doing this."
+    e "Enray'Ypay upportssay ayingplay oviesmay. Heretay areay wotay aysway ofay oingday histay."
+
+# ../tutorial_video.rpyc:13
+translate piglatin tutorial_video_4aefd413:
+
+    # e "The first way allows you to show a movie as an image, along with every other image that's displayed on the screen."
+    e "Hetay irstfay ayway allowsay ouyay otay owshay aay oviemay asay anay imageay, alongay ithway everyay otheray imageay hattay'say isplayedday onay hetay creensay."
+
+# ../tutorial_video.rpyc:17
+translate piglatin tutorial_video_b927d009:
+
+    # e "To do this, we first have to define an image to be a Movie displayable. Movie displayables require a size argument, and also use properties to position themselves on the screen."
+    e "Otay oday histay, eway irstfay avehay otay efineday anay imageay otay ebay aay Oviemay isplayableday. Oviemay isplayablesday equireray aay izesay argumentay, anday alsoay useay ropertiespay otay ositionpay hemselvestay onay hetay creensay."
+
+# ../tutorial_video.rpyc:27
+translate piglatin tutorial_video_fbaa71e4:
+
+    # e "Then, we can show the movie displayable, which starts the movie playing."
+    e "Hentay, eway ancay owshay hetay oviemay isplayableday, hichway artsstay hetay oviemay ayingplay."
+
+# ../tutorial_video.rpyc:35
+translate piglatin tutorial_video_bbbb242d:
+
+    # e "When we no longer want to play the movie, we can hide it."
+    e "Henway eway onay ongerlay antway otay ayplay hetay oviemay, eway ancay idehay itay."
+
+# ../tutorial_video.rpyc:39
+translate piglatin tutorial_video_a66b154c:
+
+    # e "The other way to show a movie is with the renpy.movie_cutscene python function. This shows the movie fullscreen, either until it ends or until the user clicks."
+    e "Hetay otheray ayway otay owshay aay oviemay isay ithway hetay enpyray.ovie_cutscenemay ythonpay unctionfay. Histay owsshay hetay oviemay ullscreenfay, eitheray untilay itay endsay oray untilay hetay useray icksclay."
+
+# ../tutorial_video.rpyc:47
+translate piglatin tutorial_video_7b2dc95f:
+
+    # e "And that's all there is when it comes to movie playback in Ren'Py."
+    e "Ndaay hattay'say allay heretay isay henway itay omescay otay oviemay aybackplay inay Enray'Ypay."
+
diff --git a/tutorial/game/tutorial_video.rpy b/tutorial/game/tutorial_video.rpy
index dac1aec..de484e7 100644
--- a/tutorial/game/tutorial_video.rpy
+++ b/tutorial/game/tutorial_video.rpy
@@ -3,7 +3,7 @@
 # Ren'Py does support movies, and we'll add them sometime later.
 
 #begin movie_image
-image shuttle = Movie(channel="shuttle", play="shuttle.ogv", pos=(475, 50), anchor=(0, 0))
+image shuttle = Movie(play="shuttle.ogv", pos=(475, 50), anchor=(0, 0))
 #end movie_image
 
 label tutorial_video:

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/renpy.git



More information about the Pkg-games-commits mailing list