Hellothere! We take your privacy seriously, and want to be as transparent as possible. So: We (and our partners) use cookies to collect some personal data from you. Some of these cookies we absolutely need in order to make things work, and others you can choose in order to optimize your experience while using our site and services. It's up to you!
Additionally, we and our advertising partners store and/or access information on your device and also process personal data, like unique identifiers, browsing activity, and other standard information sent by your device including your IP address. This information is collected over time and used for personalized ads, ad measurement, audience insights, and product development specific to our ads program.
If this sounds good to you, select \"I Agree!\" below. Otherwise, you can get more information, customize your consent preferences, or decline consent by selecting \"Learn More\". Note that your preferences apply only to Tumblr. If you change your mind in the future you can update your preferences any time by using the Privacy link beneath each ad. One last thing: Some of your data may be processed by our advertising partners based on legitimate interests instead of consent, but you can object to that by choosing \"Learn More\" and then disabling the Legitimate Interests toggle under any listed Purpose or Partner on their respective settings pages.
Papers, Please was released on August 8th, 2013 without multilingual support. Even though it would've been great to support other languages besides English, I decided to push that work until after the game's initial release. This massive post will go over my process for localizing the game.
Before writing this post I knew it would be long, but not this long. It's too big for the TIGForums devlog where it belongs. Instead of breaking it up into multiple forum posts, I created this blog for hosting. It came as no surprise that tumblr also can't handle a single post of this size.
Undeterred and unwilling to move again to wordpress or something, I've broken this post into two parts. Most of the information in Part 1 is pretty technical. Skip to Part 2 for a less technical topics. Anyways, let's get started.
Not sure it'd be worth it.There were some requests for localized versions of the beta, and I had a general idea that I may want to eventually localize it. But it would've been a lot of work without knowing for sure that it was worth the signifcant time, effort, and money investment.
No time to set up a good system for it.This is a common theme for me. I work alone and among all the stuff I had to do to finish the game, "localize it" was near the bottom. Along with setting up the game to accept localizations, I'd also need to coordinate with others to do the actual translations. In the end, that process took 4 months so in retrospect I'm glad I didn't try to fit that into the initial release.
Limiting to a single language is much easier during development.Papers, Please is full of documents with precise layouts and an obscene number of different, tiny, pixel fonts. When creating things for the first time, the ability to iterate quickly in Photoshop on a single image/document was great. There would've been a lot of wasted work if localization-friendly assets had to be generated each time I changed something early on. Waiting until the game was completely done made everything easier.
Haxe/OpenFL somewhat discourages separation of code and data.One tricky aspect of using Haxe/OpenFL to make the game is that updating a data file takes just as long as updating the source code. The build tools recompile the assets and code at the same time so the common incentive to keep data out of the code in order to improve iteration didn't really apply. This makes rapid prototyping really easy but sets you up in a slightly bad way for later production.
So for the initial release I'd resolved to ignore localization. But I've worked on localized games before and I had some basic understanding about the things I'd need to make Papers, Please localizable. These were a few small things I squeezed into the initial release:
Some displayed text was split out from the code and moved into the data.Haxe has a nice feature where you can reference a specially-formatted xml file from a class definition to have it pull text from the data. These identifiers are helpfully validated at compile time; if you mistype something, you'll get an error message right away.
Limited the use of text as much as possible.This sounds laughable considering how much text is in the game, but there were plenty of cases where I decided to replace some planned text with an icon or to remove it entirely.
Used sane document layouts.Anything is possible with Photoshop, but I kept the general parameters of what a localized version of the game would need in my mind as much as possible. That basically meant reducing the amount of distorted, rotated, variably-colored, or very-tightly-fit text.
The game came out in August and I spent the next month or so fixing bugs. After that I took a short break and the requests for localizations started piling up. Fan translations appeared and at that point I felt it was time to refactor and restructure the game to support thorough and easily-created localizations.
The first step when localizing a game is to figure out exactly what needs to be changed for a non-English version. The ultimate goal is to allow any string in the game to be replaced. Where are the strings?
All images were authored in Photoshop and any text was just placed by hand using simple paragraph alignment and wrapping features. Documents were built up this way with markers (lone black pixels) for variable, game-set text.
As mentioned above, a common way to localize strings in data is to not put the strings directly in. Instead, you put a reference id which points to a global database of strings. Then you can just swap out the database for a new language and all the strings pointed to by the references change at once. The game already had Text.xml, so technically I already had this kind of support in place. I'd just need to move every single display string in every single data file into Text.xml and replace it with the reference identifier.
Unfortunately, Papers, Please has a lot of data files covering all kinds of different textual data. I decided right away that this technique wouldn't work well for me. I'm the kind of person that prefers straightforward and clear over almost anything else when it comes to assets and code. Swapping out all the perfectly readable strings with reference ids would both be a lot of work, and severely reduce the readability of every single data file in the game.
The key step here is #3, the extractors. The game supports three types of structured textual data: XML files, CSV files, and TAB files (a custom tab-indented hierarchical format). For each of these types, I wrote a simple extractor class that edits the already-loaded structure in-place. So, for example, it's possible to create an XmlExtractor for a particular data file and context:
Ok, bear with me here. The XmlExtractor here is built to handle Ends.xml. When the game wants that file, it loads it up into the Xml structure, then uses this extractor to transform the strings. To do that, it first finds all "end" elements (children of the root). For each of those, it builds a context id by combining "end:" with the "id" attribute value of the "end" element -> "end:turned-over-ezic-docs". It now iterates all child "page" elements and checks their "text" attribute ("pages/text"). These two parts define the context id and the string id.
Now comes the Loc.csv lookup. The context id is compared to the CONTEXT column and the string id is compared to the "ID" column in Loc.csv. (String id values get modified slightly before lookup to work around minor edits: all spaces, symbols, and punctuation are removed). If the extractor finds a match, it modifies the value of the attribute to the "TEXT" column for that row.
Later on, when more specialized structures are built from this loaded Xml instance, they'll find the localized strings in the attributes. What was once "Glory to Arstotzka" in English is now "Gloria a Arstotzka" in Spanish. Because this transformation happened at such a low level (in the Xml loading routines), the rest of the code doesn't require any changes.
There were some tricky considerations to make this work smoothly though. For one, the game's simple scripting language for generating immigrants uses only the English names for certain things. This required ignoring some strings during the load-transform process and manually translating them for document display only.
This extractor system has the really nice feature of also allowing me to automatically collect all the strings that need to be localized. For a special export process, the game runs through each extractor, loads up the targeted asset file, iterates each element/node/whatever, and spits out the context, id, and English text into a "starter" Loc.csv. That means I could tweak a few things and easily regenerate Loc.csv before the translators got their hands on it.
The localization task here is to replace that fixed text for each individual language, generating a new set of document images that are loaded when the game boots up (or the language setting is changed). This was the big challenge for localizing Papers, Please. Each document was lovingly crafted with just the right text and just the right space. All in English. I knew at every moment during development that this would be a huge pain in the ass to localize. I was right.
The easiest solution on my end would be to just hand off all the images to the localizers and let them deal with it. This is probably the most common way of doing image localization. Most fan translation groups have a few graphic artists on the team for this exact purpose.
3a8082e126