Final stages of the Your Dry Delight French/Mandarin localization with a nifty language swapping game loading feature! Thumbnail image by Discord member Vikachu/Viak.


YDD TL Update

With the RE:H Google Play build out, this means we can go back and work on some of our backlog (while still forging ahead on the new project)! The translators have been waiting patiently for us to implement updates, so we’re working hard on getting those done and back to them for (final?!?) review.

Title screen of Your Dry Delight in French

The release will have both French and Simplified Chinese text.

Generally speaking, doing translations in Ren’Py is a simple matter. Extract some text, translate it in parallel, and plug it back in. However, as with any text-heavy application, things get messy when you run into languages that do not use ASCII, especially if some of your fonts don’t support these non-ASCII characters.

Playing YDD in French, then loading a Chinese save and seeing empty boxes in the history screen because the French font doesn't support Chinese characters

Boxes in the history log because of loading a Chinese save from a French game!

The font used for English YDD supports all the characters used in French just fine, but when we added in Chinese and played with loading saves in different languages…names seemed to disappear, and the history log revealed boxes.

Cue some pythonic solutions…

Playing YDD in various languages and loading other saves in other languages

Having fun loading saves multilingually.

Hooray, now you can smoothly load a save made in an arbitrary language, and everything should show up in your currently selected language!

Similar problem with Red Embrace’s Russian translation, so we’ll be adding the fix over there too.

Red Embrace history log with English interface having loaded a Russian save

Playing in English and loading a Russian save.

Red Embrace history log in Russian with XXX for MC's name instead of Макс

Sometimes the font just simply broke and turned into Xs.

# dictionary for mapping the history to the language
default all_tl_langs_history = {None:[], "french":[], "chinese_simp":[]}
# dictionary mapping character speakers to character names
define char_dict = {"richter": ["r", "rp"], "leslie": ["l", "lp"], "meyer": ["m", "mp"], "???": ["um", "u", "up1", "up2"] }
init python:

    def change_lang_font():
        '''change all the necessary variables when changing languages'''
        global lang, richter, leslie, meyer, what_prefix, what_suffix
        print("chnging lang font stuff")
        if _preferences.language == "chinese_simp":
            renpy.change_language("chinese_simp")
            gui.interface_text_font = 'fonts/SourceHanSerifSC-Regular.otf'
            gui.text_font = 'fonts/SourceHanSerifSC-Regular.otf'
            gui.name_text_font = 'fonts/NotoSansMonoCJKsc-Bold.otf'
            gui.namebox_borders = Borders(0, 5, 5, 5)
            gui.name_text_size = 36
            gui.button_text_font = gui.interface_text_font
            gui.choice_button_text_font = gui.name_text_font
            gui.confirm_text_font = 'fonts/NotoSansCJKsc-Regular.otf'
            
            lang = '_cn'

            richter = "里彻"
            leslie = "莱斯利"
            meyer = "迈耶"
            what_prefix = '“'
            what_suffix = '”'
        else:
            gui.text_font = "fonts/IstokWeb-Regular.ttf"
            gui.name_text_font = "fonts/JosefinSans-Regular.ttf"
            gui.interface_text_font = "fonts/IstokWeb-Regular.ttf"

            gui.text_size = 28
            richter = "Richter"
            leslie = "Leslie"
            meyer = "Meyer"
            if _preferences.language == "french":
                renpy.change_language("french")
                lang = '_fr'
                what_prefix = '« '
                what_suffix = ' »'
            else:
                renpy.change_language(None)
                lang = None
                what_prefix = '"'
                what_suffix = '"'
        
    from copy import deepcopy
    def change_lang_history():
        '''replace the history in the save with the history in the correct language'''
        print("change lang history")
        global _history_list
        _history_list = deepcopy(all_tl_langs_history[_preferences.language])

    def change_char_names():
        '''redundant function to make sure names are changed correctly when language is changed'''
        global richter, leslie, meyer, what_prefix, what_suffix
        if _preferences.language == "chinese_simp":
            richter = "里彻"
            leslie = "莱斯利"
            meyer = "迈耶"
            what_prefix = '“'
            what_suffix = '”'
        else:
            if _preferences.language == "french":
                what_prefix = '« '
                what_suffix = ' »'
            else:
                what_prefix = '"'
                what_suffix = '"'
            richter = "Richter"
            leslie = "Leslie"
            meyer = "Meyer"
    # call the changing variable functions when loading a save
    config.after_load_callbacks.append(change_lang_font)
    config.after_load_callbacks.append(change_lang_history)
    # make sure character names are changed when changing languages
    config.change_language_callbacks.append(change_char_names)

    def copy_history_entry_for_all_tls(event, interact=True, **kwargs):
        '''copy the history in the correct language and save it so that it can 
        replace the current language history'''

        if not interact:
            return

        if event == "end":
            # variable for remembering what language the player is currently in
            curr_lang = _preferences.language

            # loop over all translation languages
            for lang in all_tl_langs_history.keys():
                # change the current language so that we can get the string_id
                _preferences.language = lang
                # make sure character names are changed so that the correct speaker/name 
                # shows up together with the history entry!!!
                change_char_names()

                history = all_tl_langs_history[lang]  # @UndefinedVariable

                # create a history entry
                h = renpy.character.HistoryEntry()

                # get the spoken entry in the correct language
                # Example: on-screen is showing richter: 'hello Leslie'
                # e will be richter: 'ni hao, 莱斯利'
                e = renpy.game.script.translator.lookup_translate(renpy.game.contexts[-1].translate_identifier)

                speaker = None # default value
                # loop over the character name dictionary to figure out
                # who is speaking and what their name is in the correct language
                for k, v in char_dict.items():
                    if e.who in v:
                        ch = k
                        if ch != "???" and ch is not None:
                            speaker = eval(ch)
                        elif ch == "???":
                            speaker = "???"
                        else:
                            speaker = None
                        break
                    
                h.who = speaker
                h.what = e.what

                history.append(h)

                # remove oldest entries from history so that the history log doesn't get too long
                while len(history) > config.history_length:
                    history.pop(0)

            # change the language and character names back to the original language that
            # the player is in
            _preferences.language = curr_lang
            change_char_names()

    # run this history copying every time some new dialogue is said
    config.all_character_callbacks.append(copy_history_entry_for_all_tls)

Ask Answers

No questions to answer from our Ask Box for you this week! Feel free to send in your queries about anything RE:H or AG related.