Download

Localization Dashboard preview, and explanation of UE4's text localization process

In Unreal Engine 4, we have a method for collecting all the localizable text in source code and content browser assets and saving it into files for translation.

An overview of our Localization system is here:

Localization > Localizing Text > Overview

Previously, in order to get your project ready for the gathering of localizable text there was a good amount of setup you needed to do, then the actual collection was done with commandlets (small applications run on the command line) that would do the gathering for you.

Enabling the Localization Dashboard

In a future version of UE4, we want to make this process a lot friendlier, so we are currently developing a UI frontend for the localization system that we are calling the “Localization Dashboard”.

This feature is currently in development, but in the main branch (and probably 4.8) it’s available in an “experimental” state for adventurous users to try and provide feedback (in other words, it’s by no means production ready). To access it, first you must enable the feature in the Editor Preferences: Experimental section:

When you do this, it makes the “Localization Dashboard” menu item available via the Window menu (this may not be the permanent location for accessing the Localization Dashboard, but it is currently accessible from here):

c1dc496363d9e7c78c5f54ef523bedab6a4ca07b.png

Adding a target for localization

From here, you can add a new Target for localization:

These targets become separate files on disk and you can choose which ones to load or not load. You can also add additional ones later for downloadable content, etc.

Currently, when adding a new target, the target is added to the Content/Localization/TargetName folder. This folder is not included automatically in the list of localization directories that are loaded when your game starts, but for now we can add it manually in a config file (in the future this should be made more automatic). In the DefaultEngine.ini file in your project’s Config directory, add a line like the following:


[Internationalization]
+LocalizationPaths=%GAMEDIR%Content/Localization/NewTarget

Where “NewTarget” is the name of the localization target you just added.

Back in the Localization Dashboard, the settings of the new localization target that was added can be modified by clicking on the name of the target:

In the new target’s properties, you can define which text files (source code files), packages (content browser asset packages), and metadata (comments in the code used to create tooltips in the editor), that the target should gather (you can also define which other targets this target is dependent on, but we won’t get into that right now):

The directories I’m specifying here are relative to the project directory, and here I’m specifying the ./Source directory for text files, since this is where all the source code text files exist, and ./Content for the Packages search directories, since all content browser content lives here. Right now these include paths are text fields that you have to type paths into in a specific way, but eventually there will be a button to pop up an operating system folder picker dialog, which will then be converted into a path relative the correct directory automatically. Also, for file extensions, I’m specifying “.uasset” for Content Browser assets, and “.cpp” “*.h” for text files. We’ll probably make something like this the default for most projects but for now it’s a little manual.

Adding a new culture

Below this, in the “Cultures” section you can choose the Native culture. For our projects the native culture is English because we are an English-speaking company so all the source text is written in English, but it is possible to define the source language as a different language. You can also add new cultures for localization here as well with the Add New Culture button:

Here I will choose Japanese (Japan) (ja_JP) from the list of cultures:

CultureJapanLocDashboard.png

Adding text to localize

From here, we need to add some text to our project to gather.

In a previous blog post Justin Sargent described how to add localization ready text to your project:

Creating a localization ready game in Unreal Engine 4: Part 1-Text

First I will add a Blueprint class with some text to translate. You can create a new Blueprint class by opening the Add New menu in the Content Browser, and selecting “Blueprint Class”

In the Blueprint Class Editor, click the new variable button, and give your variable a name:

Then once you compile your Blueprint class, you can enter the actual text to translate in the default value of the variable:

compileBlueprint.png

Next, I will add a C++ with some localizable text.

I’ll select “New C++ Class” from the file menu, and create a new C++ class with no parent:

I’ll call the new class MyClass:

In the resultant MyClass.cpp in your project’s Source directory, I’ll add the following Localizable text macro:


MyClass::MyClass()
{
	FText TestHUDText = NSLOCTEXT("Your Namespace", "Your Key", "Your Text");
}

Gathering the text

Now that there is some text in this project, it can be gathered into text files for the localization process… Back in the localization dashboard, by pushing the “Gather” button in the target created earlier, the gather process can be started:

There will be a progress bar showing the status of the gather:

a0094de14cd17f4bdbba1e514414ee850bad35a4.png

Now if you look in your project’s Content > Localization folder, you’ll see a folder for your new target, and inside that folder will be various files including the .manifest that contains all the source text information:

ContentLocalizationFolder.png

After gathering, the manifest file now contains information about the two pieces of source text added:


{
	"FormatVersion": 1,
	"Namespace": "",
	"Children": 
		{
			"Source":
			{
				"Text": "Text to translate "
			},
			"Keys": 
				{
					"Key": "E0A3DC654F9EAE9C6E41D4BD38FEC632",
					"Path": "/Game/TestLoc.Default__TestLoc_C.SomeText"
				}
			]
		}
	],
	"Subnamespaces": 
		{
			"Namespace": "Your Namespace",
			"Children": 
				{
					"Source":
					{
						"Text": "Your Text"
					},
					"Keys": 
						{
							"Key": "Your Key",
							"Path": "Source/SampleLoc/MyClass.cpp - line 8"
						}
					]
				}
			]
		}
	]
}

Also there are separate folders for each culture you added to your project, and inside of those files there is an .archive file containing all the translation information:

CultureArchive.png

At this point, the file contains two entries for the two pieces of text added earlier, but no translations have been added:


{
	"FormatVersion": 1,
	"Namespace": "",
	"Children": 
		{
			"Source":
			{
				"Text": "Text to translate "
			},
			"Translation":
			{
				"Text": ""
			}
		}
	],
	"Subnamespaces": 
		{
			"Namespace": "Your Namespace",
			"Children": 
				{
					"Source":
					{
						"Text": "Your Text"
					},
					"Translation":
					{
						"Text": ""
					}
				}
			]
		}
	]
}

(There is even an archive for the native culture, the only difference being that this archive has it’s translation field filled automatically for every piece of text with the source text.)

Translating the text

The .manifest and .archive files are not intended to be hand-edited because we believe hand-editing text files makes for an unfriendly and error-prone workflow. Back in the Localization Dashboard you can click on the “Edit Translations” button to open the translations for each language and modify them (there are also buttons for exporting and importing from .po files if you want to want to use a different software for localizing these texts):

ae4db2f894310fbd2fea0ec7c74ecedf410d4baa.png

This opens the Translation Editor, which itself is still a work in progress but can be used to translate text into other languages and save the changes back to the .archive file for that language.

You can edit translations here or export them to .po (portable object) format for import and editing in your translation tool of choice, and then import them back into the .archive in UE4 later.

The Translation Editor splits your localizable text into 3 tabs, “Untranslated” and “Completed” are self-explanatory, but if you have source control enabled and you retrieve the history of your translations via the “Get History…” button, the “Needs Review” tab will show any text that was translated but for which the source text later changed, providing an easy mechanism to make small tweaks to reflect the changes to the source text in your translated text. The “Context” tab will show the Namespace and Key that uniquely identify a piece of localizable text, and any additional context such as the name of the source file or asset this text came from.

Saving the changes made in the Translation Editor and looking at the .archive file again shows the results have been reflected here:


{
	"FormatVersion": 1,
	"Namespace": "",
	"Children": 
		{
			"Source":
			{
				"Text": "Text to translate "
			},
			"Translation":
			{
				"Text": "翻訳されるテキスト"
			}
		}
	],
	"Subnamespaces": 
		{
			"Namespace": "Your Namespace",
			"Children": 
				{
					"Source":
					{
						"Text": "Your Text"
					},
					"Translation":
					{
						"Text": "あなたのテキスト"
					}
				}
			]
		}
	]
}

Back in the Localization Dashboard, there is a display to show you what percentage of your target has been translated into the various cultures you added. If you now hit the “Count Words” button, it will update this display to show that everything has been translated:

CountWords.png

Compiling to binary format

So far we have created FText source texts, gathered these into .manifests and .archives, and added translations for additional cultures. But UE4 does not use the contents of.archive files directly when launching your game. It instead uses a binary .locres (Localization Resource) file. So lastly, in order to generate this file, we can use the “Compile” button:

CompileTranslations.png

Launching the game in different cultures

Finally, let’s look at how to choose which culture the game will use when you launch it. To see which region is being chosen, I’ll print the localized text we added to a blueprint earlier. I’ll open up TestLoc and add a quick print text:

441403697c956e25b16db8207ea7ad36c893acf5.png

Now I’ll save that Blueprint and place an instance of it in the level.

For various reasons, it’s not possible to load anything but the source text when doing Play-in-Editor (currently it would overwrite the source text with localized text if you made any changes), so we have to launch the game as a separate process to verify. The quickest way to verify is by launching a Standalone game from the Editor.

From the play menu drop down, choose Advanced Settings:

446ef79eba9998d8648d33c23162ef49103fe919.png

In the Play in Standalone Game section, click the drop-down arrow to expose more settings:

7eb2b45ed6e342ebc52f5f9cf842a2d0dc496b14.png

In “Additional Launch Parameters” add -culture=CultureName where CultureName is the 2 or 4 letter code that identifies a culture by language or language and region combo, such as “en” for English, “en_US” for English (United States), or “ja_JP” for Japanese (Japan), etc. (this will match the culture folder names inside of your Content/Localization folder):

AdditionalLaunchParameters.png

From there, select “Standalone Game” from the “Play” menu drop down to launch a new Standalone game:

7a3d008119047051dc7475acf8e59736368fd29c.png

The text I translated earlier for the ja_JP culture now displays:

90be1a220b9132f0aadc23a1b82a07fc378749ad.jpeg

This debug text soon disappears, so you can open the console by pressing the console key twice to view the console history in the case you miss it:

0992cb1d73b856e30fd08946aea894c78d6f59e7.jpeg

Now if you go back and change Additional Launch Parameters to read “-culture=en”, the original source text will be displayed. (This also happens if you don’t specify any culture, it will display the default culture):

44ccf49ac8e0287f5d3acffc1ac8f197a0fdd68c.jpeg

Cooking and packaging localized games

For cooked games, the culture setting can also be set in your project’s configuration files, specifically DefaultEngine.ini in the Config folder of your Project, by adding a section like this:


[Internationalization]
Culture=ja_JP

When cooking your project via UnrealFrontend or the new Project Launcher (available from the Window menu), you can select which languages to cook:

Additionally when packaging your project you can select which languages you want to package:

One last thing you need to be careful about when packaging is, with the above packaging settings, you chose which locales you want to package your localization data for, but Unreal Engine also needs ICU to know which locales exist. Because the ICU data itself for each locale is not small, we only include English by default, so you will need to pick a different setting for “Internationalization Support” in Packaging settings:

(see this post for screenshot)

That’s pretty much all there is to explain currently, but rest assured we’ll continue to improve the localization workflow in newer versions of UE4!

Thanks for this! This unwraps many of the mysteries of localization in UE4. Looks pretty simple overall.

One question: Regarding UMG and putting text directly in Text Blocks, does the localization dashboard pick up on these? Or do we have to bind text blocks to a text variable?

Hey Jared,

UE4 will find and allow you localize the text you enter directly into TextBlocks in UMG. A variable is not required. :slight_smile:

Thank you :slight_smile: That’ll save us some time.

When can we expect to have possibility to have custom keys for Blueprint Text fields? GUID’s aren’t particularly translator-friendly.

This looks like a really useful tool, already looking forward to trying it out

This tool is wonderful. A great improvement from manually opening and editing the files.

Edit: Is it possible to get a compile button on each Translation Editor window? So we can translate without going back to the Localization dashboard.

I tried the experimental version of 4.9 and it kinda works better than doing everything manually. :slight_smile:

When can we expect to see the ‘Localization Dashboard’ as no longer experimental?

What kind of tools are you usin at Epic to translate the games ? The translation editor is fine, but I don’t really want to send UE4 + my game to a localization company, so I guess there is a way to export in some kind of standard tool.

Or is there ?

I use poedit myself. Not that I can get this to work in a packaged build. :\

(I wanted to just append this to the first post, but apparently I’ve used all 30 images you can attach to one post. Oh well…)

One last thing you need to be careful about when packaging is, with the above packaging settings, you chose which locales you want to package your localization data for, but Unreal Engine also needs ICU to know which locales exist. Because the ICU data itself for each locale is not small, we only include English by default, so you will need to pick a different setting for “Internationalization Support” in Packaging settings:

Hey Gwenn,

As TTaM mentioned you can export to .po files and edit with a text editor or other editor that handles .po files. I also added an interface for creating your own localization plugins to export and import your translations from. There’s a OneSky plugin that I added that you can use for that service, or you can use that plugin as a template for how to create your own.

Thanks,

Joe

Hey Joe, just wondering if you had an update/eta on when we might be able to pull dialogue strings (subtitles within Dialogue Wave assets) into the Loc Dashboard in order to export .po files for translation? We need to start nailing down our Localization pipeline, and audio/subtitles are a key part of this. Is the plan still to release this in 4.12?

I’ve asked the same question here…

https://udn.unrealengine.com/questions/239178/localization-dashboard-asset-audio-localization.html

Thanks!
Jesse

Hi,

Thanks for the dashboard explanation. That’s great to see it coming.

I’m stuck with a case where I don’t know how to get a translation working.
Let’s say that I’m pulling data from my database and I want to use translation on one data, how can I get this?

If I’m doing FromString, it will be culture invariant ;(
Should I use a Format?

Thanks,

Thank you for this write-up, it was excellent.

One question though, how do I localize the meta data?

There is a Gather from Meta Data option that lists Wildcard paths, and Key Specifications. How are these used?

To be clear, I’m asking about this kind of meta data:



UENUM(BlueprintType)
enum class ControllerSetup : uint8
{
    Conventional    UMETA(DisplayName = "Conventional"),
    Southpaw        UMETA(DisplayName = "Southpaw")
};


Thank you.

In order to localize UMETA data the following works (Enums with Localization - UE4 AnswerHub):

Gathering from meta-data is a separate step to gathering from source code or assets.

If you’re using the Localization Dashboard, then you can gather from meta-data by enabling “Gather from Meta Data” option, and adding a path and key to gather text from.

Something like this:

b91b3658a00a01e20739c01217b722dffb2a64ab.png

How do I get the localized text from enumerations? Currently, I have the following:



.h
UENUM(BlueprintType)
enum class ControllerSetup : uint8
{
    Conventional    UMETA(DisplayName = "Conventional"),
    Southpaw        UMETA(DisplayName = "Southpaw")
};

.cpp
FText UMyGameInstance::GetControllerSetupText(ControllerSetup controllerSetup)
{
    const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ControllerSetup"), true);

    if (!EnumPtr)
        return FText::GetEmpty();

    return EnumPtr->GetEnumText((int32)controllerSetup);
    //return EnumPtr->GetDisplayNameText((int32)controllerSetup);
}


I see the enumeration in the localization files, and it is translated. However, I can’t get the proper text for the selected locale.

Thank you.

Does anyone know how to get the localized string from a UENUM?

Hi,

In the Children Json Format, Keys is an array, What the purpose of it? Are you handling, in the same namespace, different keys with the same default text as just one translation?

Thanks for the clarification,

I’m seing FTextStringHelper::ReadFromString in UT that seems to come from 4.12 but I can’t see it under Github, is it planned to be delivered with 4.12?
As it seems to adressed my question of Database String FText.