CREATING A LOCALIZATION READY GAME IN UE4: Part 1 - Text

Creating a localization ready game in Unreal Engine 4 is fortunately really simple. Just follow this one basic rule and you’ll be set.

Use Text instead of String for any value ever displayed to the user.

Text is a new base type we’ve introduced into Unreal Engine 4 that handles internationalization and localization concerns for your game while abstracting all that into a concise, minimal package.

If you are creating a Blueprint just use Text literals and variables in graph and objects. Any text you type in can automatically be found, extracted and setup for translation by the engine.

Variable_BluePrints-500x176-1083849454.png

If you’re a programmer, you need to use NSLOCTEXT macros anytime you put a display text literal in your code, or if you are creating a class/asset you should use an FText UProperty.


FText TestHUDText = NSLOCTEXT( "Your Namespace", "Your Key", "Your Text" )

Check out this documentation page for the details.

That’s it.

I bet you’re thinking ‘Wow! That seems really simple; there’s gotta be a catch. Localization is supposed to be hard.’ Well, there aren’t really any catches but some people will be tempted to cheat around this rule by converting between Text and String values.

Unfortunately, this is where you can run into problems. If you convert a String to a Text, that Text will be treated as culture invariant, aka it will not be translated. So it’s super important that you enter your display text in Text values initially. Converting a Text to a String is also not advised. Text values abstract away access to the direct String which allows for some great features such as live language toggling and provide you with guaranteed localization safe operations.

Now there are valid reasons to convert back-and-forth between Text and String but you need to be extra careful when doing this otherwise you’ll break localization for that aspect of your game. User input is in general a fine example of when it is ok to convert Text to String to do some additional processing, as the value is guaranteed to be culture invariant.

Another thing to be aware of is that though we’ve been working on the localization and internationalization systems for some time now, we still haven’t converted every single API in the engine to use the proper types. Please bear with our dust as we continue to improve the engine in this aspect, which will hopefully guide users to best practices.

I’d love to hear what you think about localization in UE4 and what features you feel are the highest priority!

I , good to know, now i have to change all my string for text, ouch,

btw is planning “Format” text for sprites. f.ex “Press the button {sprite}.”

Nice!

This may be a stupid question but after I place a text in a blueprint - where do I actually do the localization?

Thank you.

The longer I use UE, the more I like it. Great!

[=;25313]
btw is planning “Format” text for sprites. f.ex “Press the button {sprite}.”
[/]

You can use our SRichTextBlock to do sprite substitution. FText::Format() is only used to concatenate together different pieces of text.

You would do something like this in the SRichTextBlock:

“Press the button <img src="MySpriteSlateBrush"/>.”

You can find in-depth examples in our STestSuite.cpp code aka SlateViewer. If you don’t like the markup syntax you can write your own parser implementation to define your own.

It might make sense to localize the text “Press the button {sprite}.” and then using FText::Format() substitute the proper rich text markup for the correct sprite. This would be easier on the translators, since there is less markup involved.

[=;25313]
now i have to change all my string for text, ouch,
[/]

The good news is that you can swap between FText and FString UProperties without requiring a special conversion of your data. You will need to re-save those assets though before the text can be extracted for proper localization.

[=BechD;25325]
Nice!

This may be a stupid question but after I place a text in a blueprint - where do I actually do the localization?

Thank you.
[/]

Hi BechD,

The actual process of localizing your “localization ready game” is a little more involved. We’ll outline all the details in the near future in our documentation and probably as a blog/forum post. The short of it is that you run a commandlet that extracts the text from your assets/code and bundles them into a set of json files. You then enter translation into these json files and rerun the same commandlet which also packs a binary version of the text and it’s translation for use by the engine.

We’re going to be offering the ability to integrate with translation companies directly as well, such as OneSky, which will smooth out the process dramatically. :slight_smile:

Is it possible to implement a boolean trigger in the format for example switching between plural and singular phrases. Something like “You won {0} {round|rounds}” depending if argument {0} == 1 or != 1?

I know those stuff can be very complex, but some stuff like amounts are quite offen used.

[=plucked;25592]
Is it possible to implement a boolean trigger in the format for example switching between plural and singular phrases. Something like “You won {0} {round|rounds}” depending if argument {0} == 1 or != 1?
[/]

FText::Format does not “officially” support such a syntax, though ICU, which is the foundation of our internationalization systems, does.

We are planning a proper implementation of the plural form support, but the situation is a little more complicated then the example you’ve provided. The Unicode Common Locale Data Repository breaks language plural forms into 6 separate categories - Zero, One, Two, Few, Many, Other. Each language has different rules for deciding which category a number falls into, but all numbers for all languages fall into one of these 6 categories.

The plan is to simplify the problem down significantly. Ideally, users will only need to be aware of the plural requirements of their native language and implement for those. In doing so the Unreal Engine will be able to naturally slip in additional required forms for other languages during localization.

Good to hear thats something on your mind. I can imagine that the parsing logic will be very complex even with the simplest things come in mind.

In my experience its also difficult to train translator those stuff. Often we use a spreadsheet with a annotion about the meaning of a text. But those sheets will get quite big over time and this increases the possibility to use inconsistent words.

Glad to know this will be builtin in the engine. Is a must have for most games these days.
Waiting for more details on how to implement the actual localized text.

CAN WE LOCALIZE ALL THE CAPS?

Joking aside, it’s a really nice feature. Extremely useful and time-saving.

[=Kenomica;26275]
CAN WE LOCALIZE ALL THE CAPS?
[/]

If you’re using FText in your product try passing -leet on your commandline for a fun surprise, also a great way to catch technical loc issues before you have actual translations. :slight_smile:

Naturally you can do this on the editor as well.

I would like to make a suggestion, if it has not been implemented.
Would allow passing parameters to a variable of type Text via blueprints.

With that, we could have purchased the following:
“Hello {1}, have a good {2}”

And then in Set node inside Blueprint, we could pass additional parameters, and we could have a button to add/remove parameters depending on the text.

thanks for the answers, Sarge.

[=Weskey;27410]
Would allow passing parameters to a variable of type Text via blueprints.
[/]

Hey Weskey,

There is already a Text Formatting node exposed in Blueprints which allow you do what you’re describing.

Keep in mind that the indexing starts with 0 not 1 so your example would need to be… “Hello {0}, have a good {1}”.

The Text Format node also allows you to use “named args” instead of “ordered args”.

“Hello {Name}, have a good {Timespan}”

Named args make it significantly easier for translators so you should favor them whenever possible. :slight_smile:

What would the process look like for localizing textures? For example, let’s say I have an exit sign in my level, and I’ve authored 2 exit sign textures, one with the word “EXIT” (English) and one with the word “SORTIE” (French).

[=sds-;47874]
What would the process look like for localizing textures? For example, let’s say I have an exit sign in my level, and I’ve authored 2 exit sign textures, one with the word “EXIT” (English) and one with the word “SORTIE” (French).
[/]

There is no out of the box system for that, you should handle those manually which is not hard with blueprint.

Technically you could use a canvas render target as a texture on your mesh, which then you populate with your FText, which takes care of the localizations, but two issues, first it’s not gonna look as good as when you import custom textures yourself and more importantly, it’s unnecessarily too expensive especially if you’re going to use those kind of meshes multiple times in a level.

So in the end, I still suggest handling them manually and just replace the texture based on the current language.

[=sds-;47874]
What would the process look like for localizing textures? For example, let’s say I have an exit sign in my level, and I’ve authored 2 exit sign textures, one with the word “EXIT” (English) and one with the word “SORTIE” (French).
[/]

Hi ,

Our process for localizing textures is a bit rough atm. How it basically works is you create two texture assets with the same name, one as the original and the other marked for a specific locale. Right now the concept of “marking” an asset package as being for a specific locale is based on the folder struct it is placed in.

So when the engine goes to load an asset package it first checks to see if there are any packages available by the same name for the currently specified locale. If it doesn’t find one it falls back to the original package and loads that.

This process can be used to localize any asset package in Unreal, though, I wouldn’t recommend doing this with asset types which have many other entangled dependencies or partial data that is intended to be shared across all locales.

Dear Sarge,

I asked this question on the AnswerHub

How do we Localize Text Render Components?

Shouldn’t the base data type of this component be an FText, not an FString?