Announcement

Collapse
No announcement yet.

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

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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:

    Click image for larger version

Name:	ExperimentalLocDashboard.png
Views:	1
Size:	64.2 KB
ID:	1146365

    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):

    Click image for larger version

Name:	WindowMenuLocDashboard.png
Views:	1
Size:	90.1 KB
ID:	1146366

    Adding a target for localization

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

    Click image for larger version

Name:	AddNewTargetLocDashboard.png
Views:	1
Size:	53.8 KB
ID:	1146368

    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:

    Code:
    [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:

    Click image for larger version

Name:	NewTargetLocDashboard.png
Views:	1
Size:	49.6 KB
ID:	1146367

    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):

    Click image for larger version

Name:	GatherConfiguration.png
Views:	1
Size:	50.4 KB
ID:	1146369


    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:

    Click image for larger version

Name:	CulturesLocDashboard.png
Views:	1
Size:	104.7 KB
ID:	1146370

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

    Click image for larger version

Name:	CultureJapanLocDashboard.png
Views:	1
Size:	21.1 KB
ID:	1146371


    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”

    Click image for larger version

Name:	AddBlueprint.png
Views:	1
Size:	307.1 KB
ID:	1146372

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

    Click image for larger version

Name:	BlueprintTextVariable.png
Views:	1
Size:	176.6 KB
ID:	1146373

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

    Click image for larger version

Name:	compileBlueprint.png
Views:	1
Size:	73.4 KB
ID:	1146374

    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:

    Click image for larger version

Name:	NewClass.png
Views:	1
Size:	121.3 KB
ID:	1146375

    I’ll call the new class MyClass:

    Click image for larger version

Name:	NewClassMyClass.png
Views:	1
Size:	63.2 KB
ID:	1146376

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

    Code:
    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:

    Click image for larger version

Name:	GatherButton.png
Views:	1
Size:	44.2 KB
ID:	1146377

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

    Click image for larger version

Name:	GatherProgress.png
Views:	1
Size:	48.8 KB
ID:	1146378

    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:

    Click image for larger version

Name:	ContentLocalizationFolder.png
Views:	1
Size:	25.3 KB
ID:	1146379

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


    Code:
    {
    	"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:

    Click image for larger version

Name:	CultureArchive.png
Views:	1
Size:	18.2 KB
ID:	1146380

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

    Code:
    {
    	"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):

    Click image for larger version

Name:	EditTranslations.png
Views:	1
Size:	41.1 KB
ID:	1146381

    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.

    Click image for larger version

Name:	TranslationEditorOverview.png
Views:	1
Size:	88.5 KB
ID:	1146382

    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:

    Code:
    {
    	"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:

    Click image for larger version

Name:	CountWords.png
Views:	1
Size:	44.2 KB
ID:	1146383

    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:

    Click image for larger version

Name:	CompileTranslations.png
Views:	1
Size:	38.7 KB
ID:	1146384

    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:

    Click image for larger version

Name:	PrintSomeString.png
Views:	1
Size:	27.8 KB
ID:	1146385

    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:

    Click image for larger version

Name:	AdvancedPlaySettings.png
Views:	1
Size:	86.1 KB
ID:	1146386

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

    Click image for larger version

Name:	StandaloneGameAdvancedSettings.png
Views:	1
Size:	10.7 KB
ID:	1146387

    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):

    Click image for larger version

Name:	AdditionalLaunchParameters.png
Views:	1
Size:	17.9 KB
ID:	1146388

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

    Click image for larger version

Name:	StandaloneGame.png
Views:	1
Size:	111.7 KB
ID:	1146390

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

    Click image for larger version

Name:	StandaloneGameLocalized.png
Views:	1
Size:	726.4 KB
ID:	1146389

    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:

    Click image for larger version

Name:	StandaloneGameLocalizedConsole.png
Views:	1
Size:	234.5 KB
ID:	1146391

    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):

    Click image for larger version

Name:	StandaloneGameSource.png
Views:	1
Size:	734.2 KB
ID:	1146392


    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:

    Code:
    [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:

    Click image for larger version

Name:	LocCooking.png
Views:	1
Size:	122.7 KB
ID:	1146393

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

    Click image for larger version

Name:	LocPackaging.png
Views:	1
Size:	209.9 KB
ID:	1146394

    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!
    Last edited by Joe Conley; 03-07-2016, 03:55 AM.

  • replied
    OneSky plugin can not use, there's no place to configure prject id and project name

    Leave a comment:


  • replied
    Gathering From Meta Data does no longer work. It just produces entries in the Game_Conflicts.txt and adds no entries to the Game.manifest:

    >From metadata for key DisplayName of enum value Autumn of enum ESeason in None

    Leave a comment:


  • replied
    I just spent ages trying to figure out why this didn’t work, and finally found out why... should anyone also be as dense as me; don’t assume the default ‘Game’ target is a viable target for gathering text. You still have to create a new target to gather text.

    One thing though; I tried exporting translations as a .po file and opening them in Virtaal (a .po editing tool), and it didn't let me. Virtaal claimed the .po files were empty. Any ideas?

    Leave a comment:


  • replied
    It's simply great

    But i have a question: how can i translate UE's FTexts?
    For instance, i'm using Fkey s for my hotkey system, and i'm using their DisplayName for getting the FText to display on screen, but it come obviously not translated, because i can't gather its data (for example, space bar will always be "Space ba

    How can i do to gather and translate them?

    Leave a comment:


  • replied
    When i delete or change some text that text still exist in list even when i use GatherText

    Leave a comment:


  • replied
    Great Post!

    I have a question. I would like to use the same approach for swapping out text, but with images. Is it possible to do?

    Leave a comment:


  • replied
    Hi,
    Thanks for your tutorial.

    I made a custom widget with some buttons to select language at first time install and run the game. and it's saved to my save file, but I don't know how i can tell to game how to use that language at startup.

    I can read saved language from game instance at startup but i don't how to tell the game every time runs with -culture=*CultureName*

    I developing for Android / iOS

    Thanks

    Leave a comment:


  • replied
    I tried to make a shortcut macro, but the Gather Text doesn't find it:

    Code:
    #define LOCA( InKey ) FInternationalization::ForUseOnlyByLocMacroAndGraphNodeTextLiterals_CreateText( TEXT( "MyGame" ), TEXT( InKey ), TEXT( InKey ) )
    Any ideas, why not?

    Leave a comment:


  • replied
    Does this new system imply we cannot have different strings with the same English text and different translations since the string IDs (category.key combinations in the Unreal 3 internationalization files) are gone?

    Leave a comment:


  • replied
    Originally posted by Elvince View Post
    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,
    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.

    Leave a comment:


  • replied
    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,

    Leave a comment:


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

    Leave a comment:


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

    Code:
    .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.

    Leave a comment:


  • replied
    In order to localize UMETA data the following works (https://answers.unrealengine.com/que...ization.html):

    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:

    Click image for larger version

Name:	UMETAData.png
Views:	1
Size:	18.4 KB
ID:	1105843

    Leave a comment:

Working...
X