Sponsored By

A developer's guide to effective localization in Unreal EngineA developer's guide to effective localization in Unreal Engine

This article shares insights based on the development of Wizard of Legend 2, detailing the complexities encountered in Unreal Engine localization.

Shayan Aminnezhad

January 17, 2025

10 Min Read

Introduction

Localization is one of the most critical yet often underestimated aspects of game development. As global audiences grow, players expect to experience games in their native language, making effective localization a necessity, not a luxury. However, it's much more than just translating text—it involves addressing technical challenges, cultural nuances, and workflow optimizations to ensure a smooth and seamless experience across multiple languages.

In this article, I’ll walk you through the complexities of localization in Unreal Engine, sharing insights based on my experience with Wizard of Legend 2. From gathering and managing text to overcoming issues like incorrect formatting, gender-specific language, and font handling, I’ll highlight key areas that can cause delays and how to mitigate them.

This is not an introductory article, so I expect you to be familiar with Unreal’s basic localization tools. If you’re new to the subject, resources below are great to learn the basics. Once you’re ready, let’s dive into the real-world challenges and best practices to help you plan your localization process more effectively.

Gathering text

Gathering text is straightforward. Open the Localization Dashboard, press the "Gather Text" button, and voilà, it's done!

However, there are two major problems that will take up a significant amount of your time:

1. Irrelevant Texts

Unreal gathers many irrelevant texts. In our case, about 80% of the text that appeared in the gathering results was irrelevant. These seemed intended for engine localization, not game content, but they appeared regardless of the filter preferences set.

To address this, you need to filter the locations where your gather text command looks for text. At the later stages of development, this can be a daunting task, and it’s challenging to ensure that your filters cover all of your game content.

2. Incorrect Text Types

Another common issue is encountering many texts with the wrong type. In Unreal, every localizable text should be of type FText, but developers sometimes use FString instead. Worse, they might use FText initially but later change its value using FString—which is easy to do, as converting between FText and FString is very easy.

It’s a good idea to familiarize your entire team with localization principles in Unreal from the start and assign someone to supervise the localization process. You should periodically run the "Gather Text" command and ensure that your filters cover the majority of your texts. As your project grows in size, it becomes much harder to find the texts that need localization.

Later, I will explain how to automate your pipeline so that AI can translate your texts into other languages, allowing your QA team to spot unlocalized text while testing the game in a different language.

FText vs FString Hell

If you've watched the tutorials mentioned earlier, you know that converting FString to FText (or vice versa) is a bad idea. But it’s so easy to do that I want to remind you again!

We had some cases where FText was cast to FString, passed to a function, and then cast back to FText inside the function. The text appeared to be a regular FText unless you attempted to access its original string or sent it over the network to a client with a different language.

Casting from FString to FText is also automatically done by the Blueprint system if you change the type of your text from FString to FText or vice versa. So, keep an eye on these conversions and fix them as soon as you spot one.

There are a few cases where casting FString to FText makes sense (e.g., printing debug text on the screen), but in general, it’s a red flag.

Human languages are a mess!

We decided to introduce gender customization very late in development. From a gameplay perspective, it seemed simple: create a female model, add a UI to let the player choose the wizard’s gender. Done, right? Unfortunately, no!

Some languages, like Persian and Kurdish, are gender-neutral, but others, like French and Spanish, are not. The introduction of gender customization forced us to retranslate every sentence involving our character, since its gender was determined at runtime, and the text also had to be dynamically crafted based on the gender.[1] 

Unreal already supports the {var}|gender(masculine, feminine, neuter) construct. If you pass ETextGender to the var parameter in the FormatText function, it works perfectly. However, we didn’t use this feature.

Our development language was English, which is largely gender-neutral. But to support gender using Unreal’s construct, we would have had to define a {var} for gender in all our texts. This would have allowed us to pass ETextGender to the FormatText function, which other languages could use if needed. This approach is easy to forget, and implementing it late in development requires significant effort.

Instead, I wrote a custom construct that could be absent in the original text, and implemented a processor that could parse the construct and select the correct string based on the character’s gender. This allowed our English text to remain clean. The construct is very  similar to the Unreal construct [masculine|feminine]

Additionally, this construct is flexible. Although we didn’t need it, you could introduce a header like [header: masculine|feminine|neuter] to support different genders for the speaker and target.

Another issue you’ll need to address is pluralization and singular forms. I encourage you to use Unreal’s {number} {number}|plural(one=,few=,many=,other=) construct.

Certain languages may present other challenges. For example, in Turkish, the percent symbol comes before the number (e.g., %5 instead of 5%). Additionally, text highlighting might not work in languages like Chinese, where words aren’t separated by spaces. These issues are difficult to spot, so allocate time to handle them.

Fonts

Handling fonts for different languages can be a real headache.

You might be tempted to create a single font that supports all the languages in your game. This isn’t a good idea because, for example, the font used for Chinese might overlap with the English font, and merging them could create inconsistencies. Even if you manage to separate the fonts cleanly, there’s a limit to the number of glyphs a font can support.

Another approach is to use Unreals asset localization, creating localized versions of your font asset. Unfortunately, this approach has its own drawbacks. When you change the game’s language, in-game texts change immediately, but Unreal only loads the localized font assets when the game is restarted. This results in players seeing question marks until they restart the game or switch back to the original language.

A better solution is to use Unreal’s font handler feature, which allows you to choose a specific font based on the current locale. While this works, it's not ideal. For example, in the settings menu, you might want to display each language's name both in the current language and in its native script (e.g., "Farsi (فارسی)"). If the font is only selected based on the locale, you either have to support Persian letters in all your fonts or you'll see question marks.

What’s the best approach?

The approach I found best is to use Unicode ranges and assign each font to a specific range.

Our default font covered all European languages, but Chinese and Japanese were more challenging. Since the Unicode range for Kanji characters is mixed, and simplified Chinese, traditional Chinese, and Japanese all use the same range, it was impossible to have separate fonts for each language. We tried various fonts, some of which promised to support both Chinese and Japanese, but when we tested them, we found missing characters. Some fonts were acceptable, but Chinese users found them unreadable. Eventually, the translators came to the rescue and provided me with the link below, which offers standard Chinese fonts: https://github.com/wordshub/free-font.

Translation pipeline

Working with a translation team is a challenging management and software development task.

As a programmer, you need to create a pipeline that facilitates communication between your team and the translation team. Since each team’s structure is different, I won’t go into specifics, but I’ll offer some general advice.

First and foremost, understand the software your translation team is using. Ensure that encoding is consistent throughout the pipeline. If not, you may encounter issues like numbers showing up instead of carriage returns or previously translated texts becoming corrupted. A good rule of thumb is to handle the conversion yourself. For example, if they’re using Excel, give them Excel files instead of CSVs (especially since Microsoft Excel doesn’t ask for encoding when importing CSVs!). Depending on your workflow, you might need to write some converters or even create your own format (e.g., for versioning or tagging).

The ideal workflow is to provide the translation team with a single file and retrieve the same file after translation. However, since translation deadlines are usually before the release date, some content might not be ready. In such cases, you can use string tables: write the texts in there and once the content is ready, you can reference the string table for the localized text. However, as translation progresses, your team might realize they missed some texts, and you might need to provide additional files. How you manage multiple files will depend on your pipeline, but be prepared for this.

Building a robust pipeline is time-consuming, and you’ll likely need to refine it several times, but it can significantly speed up the process.

You can start by using the commands available in Unreal’s Localization Dashboard. These can be easily called in a Python script without needing to open the engine. I’ve included a simple example at the end of the document.

With these building blocks, you can do all sorts of interesting things. For example, you could export your texts every night, convert them, and upload them automatically to your translation team. After the localization deadline, you can adjust your merge pipeline to check for word count. If new text has been added, you can prevent the merge from proceeding.

Another useful application is to gather all your texts and use AI translation services to translate them, then have your internal QA team test the game and identify unlocalized texts before you send them to the translation team.

Finally, note that text compilation isn't triggered when you build the game, so you'll need to trigger it manually—or better yet, configure your build pipeline to call CompileText automatically.

Platform considerations

If you are planning to publish your game on platforms like PlayStation and Xbox, be aware that hardware, software, and concepts are referred to differently across platforms. Platform owners expect you to follow their standards in all the languages you support; otherwise, your game may be rejected. For example, you cannot simply use the word "Controller" across all platforms. The term "Controller" is called differently on each platform, so your game should refer to it according to the platform-specific terminology.

You could create a construct that takes the current platform as a parameter and selects the appropriate term based on the platform, or alternatively, you can use different text for each platform.

It’s a good idea to create a table of these terms, alongside their expected translations in different languages for each platform, and provide it to your localization team early in the process. Reviewing all the texts afterward can be time-consuming and error-prone.

Conclusion

Localization can be challenging and time-consuming, and you need to be prepared for it. It is an essential part of modern game development. Players expect to engage with games in their native language, and failing to provide this at launch can lead to negative reviews and missed opportunities. I hope this article has provided valuable insights into the challenges and solutions, and that it helps you approach localization with a clearer understanding.

Good luck with your localization efforts, and I wish you great success!

Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like