Localizing Ink with Unity

Johnnemann Nordhagen
4 min readMay 4, 2019

Inkle Studios’ Ink scripting language is one of the absolute best tools for narrative games. I recommend it wholeheartedly to anyone looking for an easy, powerful tool for creating written content for games.

We used Ink for all the text in Where the Water Tastes Like Wine — our character dialogues as well as the small branching vignette stories in the game. Where the Water Tastes Like Wine also has two unique requirements that necessitated additional planning and implementation, however: Localization and Voiceover.

Recently I’ve been asked quite a lot about our process for localizing our Ink-based content, so I thought I would write a little bit about how we did that. I’ll start with one big caveat: this works much better if you stick to simple uses of Ink as a flow-control tool, and breaks entirely if you rely heavily on Ink’s features for dynamic text replacement.

That is, if you use lots of mid-line diverts, glue, joining, or variable text, it becomes much more difficult or impossible to localize your Ink. Keep this in mind when writing your content!

If you are doing voiceover for your content as well, you’ll also want to avoid these features — having actors record variations of lines for each different way you present the text will make your sessions much more expensive and complicated to track, in addition to the technical complexities of implementing a VO system.

If you have avoided this, localizing becomes fairly easy. Here’s how we did it for WTWTLW. First, we went through and used Ink’s tagging system to mark each line with a unique identifier. For characters we used the character name, chapter, subject, and line number, e.g. “#Shaw_Chap1_Joy_Line2”. For vignettes, we used the internal unique vignette name plus line number, “#Violin_Line4”.

An example of tagging a vignette line

When displaying the Ink content, the parser also gives us access to the tags associated with each line at the same time. In our display code we simply look for the presence of tags (for simplicity, we only use the one tag, although using multiple tags is a supported Ink feature). If the tag exists, we look up the value in our localization database (WTWTLW uses Inter Illusion’s I2Loc Unity add-on, but any localization solution will have a key-value pairing setup that’s similar). We then display the localized text in our UI.

A snippet of C# code dealing with Ink text parsing and display

This has an interesting side effect. Essentially, the content of the Ink file is immaterial at this point — the tag contains all the value that we need. If the line was blank, or gibberish, the system would still display the correct text because the authoritative source has now become the localization database. This means that typos and rewrites must be done in the database, rather than in the Ink file (or better yet, in both places!). For WTWTLW, we would make corrections in the Ink files, and we had a script that dumped the contents of those files into the spreadsheet so that the two would always be in sync, although as we came close to shipping the corrections would be made directly in the localization sheet to avoid mishaps with our production text.

However, currently Ink does not support tagging choices. So for choice text, there are two main options: You can go through and swap each choice with a key that is then looked up in the localization DB, or you can use the choice text as its own key. Both of these options have their downsides. In the first instance, you will make the Ink file much harder to read and understand, because instead of things like [Feed the horrible bird your flesh] you will have [Grackle_Choice04]. In the second case, you will have complicated localization keys, with the potential of mismatch between the key and the value if you need to rewrite that text for any reason. You will also be locked into one translation for a particular string. If you have written a choice [Say hello] in multiple places, for instance, your translators will not be able to interpret that differently based on context.

Where the Water Tastes Like Wine uses the second approach, in order to make the Ink editing process as painless as possible. Ideally some future version of the Ink language will allow for tagging choices to make this easier.

Since we could not use dynamic text in Ink itself, for the few cases where WTWTLW required inserting values into text, we used a C#-side text tagging replacement system. This allows you to do e.g. “She’s telling him about {NewStory}. You try to hide your surprise — it’s the story of {OldStory}!” Then your translators can simply reposition the tags as required by their language, and your C# string-replacement code can swap the localized value for the variables within.

For our VO system, we used the same tags and looked them up in our system to find the VO file that corresponded with the line, then played that. Ink’s powerful tagging system allowed for an easy 2-in-1 solution for VO and localization!

It’s unfortunate that this approach doesn’t allow for usage of some of Ink’s more flexible and interesting text features, but localization will always require some degree of being constrained in what you can do with your text — Ink’s logic flow is still a wonderful tool to have at your disposal for narrative games of all types.

If you have more questions about Ink or our localization or VO processes using it, I’m happy to answer them! Please drop me an email.

--

--

Johnnemann Nordhagen

Johnnemann has been making games for decades. He has worked on titles such as Bioshock, Gone Home, and Where the Water Tastes Like Wine