Implementing Translations


Introduction

In this tutorial I'll be discussing how to add a language option to your Ren'Py game. This is solely for the implementation of a translation, NOT to generate a translation from the script. There is no automated translation button built into Ren'Py, and I highly recommend against using machine translation for official game releases, as the practice is highly frowned upon and has substandard results. 

When working for Afterthought Studios, I worked with a team of translators to make the Russian translations of Afterthoughi's games. I then implemented the translations into the scripts. However, the process can be confusing when you only do it once every six-to-twelve months or so. Thus I made a guide for myself some time back to avoid confusion.  I've decided to share and update the tutorial for anyone who might find it useful.

WARNING: As a heads up, this code was written for a version of Ren'Py that is now long out of date. It may no longer work as intended. I'm leaving this here  so folks can use it as a reference point to get familiar with the process. 

Step One

To  get a basic understanding of the translation framework built into Ren'Py, I recommend reading this Documentation page.

Once you have your game's script completed in the original language (I'll be using English in the example), you will want to generate a blank script for translation into another language (Russian, in this example.) To do this, you will select the project in The Ren'py Launcher and go to the Actions menu, where you will click "Generate Translations."


This will take you to a second menu, in which you will input the name of the language you are generating scripts for. Be sure to use all lowercase letters.


Now press "Generate Translation," making sure to have the box next to 'generate empty strings for translations' checked. 


Ren'Py will generate blank files for your project, which can take a few moments depending on how large your project is. Once it's done you'll find the blank scripts for translation in your project's "game" folder, like so:

[Your Game]/game/tl/russian


Your files will be ready for the translation to be input. This will be done manually. The team we worked with input the translation into the script as they worked, so everything could be matched up  and double checked. Some programmers receive translations via spreadsheets, some scripters input the translations themselves. It all depends on what you/your team and the translator's preferences are.

Here's what one of the scripts looks like before the translation is filled in.


You can see that the contents of original script (in this case, the English text) is available in comments. The lines above the comments are what allows Ren'py to replace the English line with the Russian line, when the game is played in Russian. Below the comment is an empty dialogue line with the appropriate character label defined, which will eventually be filled with the translation.

# game/script.rpy <--file from which the lines are taken
translate language script_#######:  #<--string for replacing original script with translation
# n "Commented version of line from original script."
n "Translated version of line."

Here is what the same script looks like after the translation is implemented:


!! Important !!

Be sure that any strings like the following:

translate russian script1_f978b7f5:

 match the capitalization of your game folders. If the folder is "/game/tl/russian" make sure "russian" is always lowercase, or you might get weird issues. At one point I had an error in which only the menus appeared translated, but all of the text was still in English. It was because of a mismatch in capitalization. 

Another issue that sometimes crops up has to do with how characters are defined. When Ren'Py converts a script into an empty script to be filled with translations, it will automatically convert some lines that won't be translated in the same manner as the rest of the script.

For example, the script we generated for Forgotten, Not Lost included the character definitions, which our translators naturally translated. 

# game/script.rpy:79
translate russian start_3989d14d:
    #define mad1 = Character("Madalene")
    define mad1 = Character("Мадалена")

But this caused the translated names to override the names in English, no matter which language you played the game in, due to how Ren'Py works. To prevent this, you must do the following:

define e = Character(_('Eileen'), color="#c8ffc8")

You will find this in the scripts of the Russian translation:

translate russian strings: 
    old "Eileen" 
    new "Эйлин"

In the end, our Russian Strings looked like this:


and the error was resolved.

Now that the above is done, you should have a functioning translated script. Be sure that your UI is also translated. If you use imagemaps for your GUI, you'll want to have translated versions of any UI images and add them to your translated file folder, like so:

[Your Game]/game/tl/russian/images

Now, you'll need a way to allow your players to select the language they want to play in. For Afterthought Studio's games, I had the option pop up in a splash screen upon opening the game. If the player has already made their selection, the splash screen won't pop up again. 

To do this, I used the following code in options.rpy:

init -3 python: 
    if persistent.lang is None: 
        persistent.lang = "english"
    lang = persistent.lang
init python: 
    config.main_menu.insert(3, (u'Language', "language_chooser", "True"))
init python:
    if lang == "english":
        style.default.font = "font_name_here_1.ttf" #english font here 
    elif lang == "russian": 
        style.default.font = "font_name_here_2.ttf" #russian font here

Please note that not all fonts will be compatible with a given language, so you may need to change the font depending on the language selection.

If you want players to be able to choose the language upon opening the game, put the following in script.rpy:

label language_chooser: 
    scene black 
    menu: 
        "{font=Arimo-Regular.ttf}English{/font}": $ renpy.change_language(None) 
        "{font=Arimo-Regular.ttf}Русский{/font}": $ renpy.change_language("russian")
    $ renpy.utter_restart() #alternatively, use "return" if you don't want to go to the main menu.

And in case your players want to switch languages after starting the game:

Put the following in your imagemap for the Main Menu or Options Menu for screens.rpy:

hotspot(#,#,#,#) action ShowMenu("language_chooser") #insert coordinates appropriately

This is how I've implemented translations in the past. As Ren'Py updates, I'll try to improve on this tutorial as I am able to. 

This code is compatible with SteamAPI, so you can use it in conjunction with achievements and such. (ie. having an achievement unlock when players change the language.)

I hope this helps anyone who might need it. If you have any questions, please feel free to leave a comment and I will try to get back to you. 

If you found this helpful at all, please consider leaving me a token of your appreciation, if you are able to. 

Comments

Log in with itch.io to leave a comment.

Hey, this post was a long time ago, but I can't figure something out: when I try to make a menu option for changing the languages, I get an error where it says that it expected a statement in the line that says renpy.change_language(None).

No worries! I will try to help as I'm able. There's a pretty good chance my code has become outdated, but let's see what we  can figure out!


So according to this renpy documentation page

renpy.change_language(language, force=False)
Changes the current language to language, which can be a string or None to use the default language.

Have you changed "language" (the brackets) to the new language on that menu?

(+1)

I've tried that now. It didn't work. I apologise: I should have been more specific. The syntax error of 'expected statement' appeared in all instances where I used the renpy.change_language() fxn.

No worries! Would you be able to share a snippet of the code? Hopefully looking at it might clue me in to the issue. 

renpy.change_language(language, force=False)

label language_choose:
menu:
'English':
renpy.change_language(None)
'toki pona':
renpy.change_language(tokipona)
$ renpy.utter_restart()

Is that enough? Just tell me if you want more.

(+3)

2 years later and I still visit this...

Do you think it is possible to show user a kind of menu choice for choosing language? After label start, before the story begins?

I think you could use the same script bit currently included before the menu, just edit it a bit so that it's after the game starts but before the story begins and take out the

renpy.utter_restart()

and/or add it to the "options" menu. It may take some tweaking. If I recall correctly I saw something similar on lemmasoft forums, I'll check my bookmarks for you.

Also wow, 2 years already? Gosh I'm behind on stuff I wanted to post here, lol.

Anyway I think I found the post I was thinking of:

https://lemmasoft.renai.us/forums/viewtopic.php?f=8&t=61623&p=540707&hilit=langu...

(1 edit) (+2)

Hi. I'm still learning how to generate translation too. Why my script.rpy file is not translated by the way? I'm rather confused since I put all the definition here (like character name, transition effect and such). I have to change the character name into the language I translated. Is there any way to override this?

(+1)

Ah, never mind then. It's because my script.rpy doesn't contain any strings so it's not translated. I figured it just now hahaha.

Oh! Sorry I just saw this. Glad you got it figured out! It's a bit confusing at first, I totally forgot to note that strings are a necessary evil. :)