Localization is VERY Important

I hope Epic come up with a great LC solution, because things are becoming scary to me :rolleyes:
I’ve read this and this, but it’s not quite there yet.

http://i1234.photobucket.com/albums/ff408/BrUnOXaVIeR/UE-LC_zps6d10b562.jpg~original

I have Data Asset that stores an array of string with keys. I have a different asset for every language and I just load the one I need. I have a function that uses binary search to find the key in the array and return the associated string. It works pretty fast. :slight_smile:

This in not the way :eek: you only need use one idiom, a external tool from epic do it the changes. Btw you dont use string, use text variables.

I am using FText. I convert those strings to Text, the actual localized object is a FText, but there’s no need to store translation values as Text.
And which external tool is that? I’ve never read about it and have no idea what it is.

I’ve seen Epic’s tutorial but UE4’s localization system doesn’t suit my needs. ;/

How does it not suit your needs?

There’s no point storing a load of strings for all languages, then converting them to text afterwards. You should store them in FText and use the command line tools (e.g. GatherTextCommandlet or whatever it’s called) to generate your translation files for you to fill in.

I can’t find anything about this on docs. Any link?

I don’t know if it’s documented to be honest (and I don’t know how complete the system is, but it should be reasonably there). Data stored in blueprint FText that doesn’t have the transient flag, and text wrapped in a LOCTEXT macro should all be collected by the text gathering process, and collated into a text file which can be translated. Translated text files should be placed in the appropriate directories, after which it should be possible to run the game with the relevant languages.

Well, if there’s no docs its because there’s no system yet.
I know they are working on this, but I think nobody have any idea when will it be ready; the reason why I am storing strings for now.

https://www.unrealengine.com/blog/41-update-preview

NEW EXPERIMENTAL FEATURE: TRANSLATION EDITOR
The Translation Editor makes it easier to edit translations for strings in your game code and assets.
Experimental Feature: Translation Editor
Note: This tool is still an early work in progress. This tool can be enabled in your editor preferences under the Experimental section.

Oh, I missed that. Thanks!

That tool only allows you to translate the editor itself, not your game. Unless there is an additional step you need to do to show your game’s LOCTEXTs.

I would also like to know what’s the “right” way to create localization. (Okay, always use FText, and then…?)

Then you should start editor with special command line parameter that will generate a file which can be translated and then loaded to the editor so that it is bundled and packaged. Though it is not documented, so I don’t know if it is even finished.

^ This is what you need to do. I’m no longer familiar with the command switches, but the main commandlet is the GatherTextCommandlet, which in turn should run the other commandlets for other stages of localisation dependent on config setup.

This stuff really needs documenting, to be honest.

There is a system, and it’s at least partially working. I know this, because I’ve used it and shipped a product using UE4 already :wink:

Yeah, can’t use that editor with game content, only Editor strings.
The whole thing about “GatherTextCommandlet” is the missing piece. I have idea what to do with that.

really :(, On my world of dreams i thinking that this tool working like a vicious engine translate system.

I’ve run the game with UE4Editor.exe ShooterGame -GatherTextCommandlet, nothing seems to have changed.

Does any sample game uses localization?

Sarge (UE dev) had posted a lot of info on localization before the forum outage. I still have them in my email, allow me to repost them:


Hey Everyone,

I’m the primary architect behind UE4’s internationalization (i18n) and localization (l10n) systems. I’ll do my best to answer the questions that have come up here and try to paint a picture of UE4 future in regards to i18n and l10n.

What’s the current state of things?

- The text localization systems are effectively finished. There's polish, probably bugs, and still some "desired" features we want to hit but you can do an end-to-end localization pass on your game's text in UE4.
    - You can localize your text as well as numbers, percentages, currency, dates, and times.
    - We have support for allowing "safer" text concatenations through FText::Format().
    - We have support for locale aware text comparison (i.e. sorting, filtering)
    - We have support for locale aware word wrapping

- The audio localization system is only half done. You can build content that will be compatible with the future audio localization changes, but you can't actually localize that audio yet.
    - If you want to build content ready for audio localization you'll need to use DialogueVoice and DialogueWave asset types

How do I localize my game’s text?

- In order to localize your game's text, the text must be entered into a Text variable or if you are writing source code you must use a LOCTEXT or NSLOCTEXT macro.
- You must run the GatherTextCommandlet with the proper ini configurations (these configurations tell the commandlet what to do and were to gather text from).
- You need to get your translations into the archive files produced by the GatherTextCommandlet. You can use the in-editor Translation Editor (which I think supports games now) or you can use other methods. In the future we're likely to support interfacing with external groups like OneSky to help with your translation effort.

How do I see my translations in editor?

- You can't see your translations in editor except through the Translation Editor itself. This may be a feature we'll support in the future, but it's a complex problem since the editor wasn't built from the ground up with that feature in mind.
- You can see your translations in-game if you run a cooked build of your game or run the editor with -game (which is effectively a non-cooked version of your game)

What’s missing?

- Documentation. Currently your best resource is going to be the AnswerHub or the Forums. There's already a bunch of answered questions on the topics of localization and the process so you should review those before posting your own questions.

What are we working on now?

- Audio localization
- More platform support. Currently only Windows and Mac have the full gambit of features because they have integrated with the ICU library. We are working to bring this library to our other platforms like mobile and consoles. Even without ICU though you can translation and see your translation in-game. You just won't have support for the more locale aware run-time i18n features.
- I'll make it a priority to work with our documentation team to get localization documentation done, though this work hasn't started.

What’s the future look like?

- Hot language swapping support
- In-editor preview (hopefully)
- OneSky integration
- In-editor localization configuration process management tools (instead of editing config inis and running the cmdlet yourself)
- Plural form support
- On device translator support
- and more if I get my way :)

As for the problem pointed out by the initial post on this thread, that user is unnecessarily circumventing UE4’s integrated i18n systems. The issue is that currently the TextRenderComponent doesn’t directly take a Text variable. So instead they would just need to drop a Text literal node, type their message, then convert that literal node to a String and pass that into the TextRenderComponent. By doing it this way you get all the features I’ve mentioned previously except the hot swapping, and it’s significantly easier to manage. We are working to make the TextRenderComponent localization safe in the near future.

Let me know if you have any more questions!

-Justin


I then asked how specifically to run that commandlet, how to do localization, etc. Here’s his reply:


I just realized you guys don’t have access to our old licensee support forums. The below text are some responses on those old forums.


The UE4 loc system is rather new and has yet to be documented fully. Using LOCTEXT and FText is definitely the right thing to do, but we don’t use any localized keywords on uobjects like we did in UE3. Instead any FText property is automatically assumed to be localized.

The loc processing is broken down into steps(individual parts). Each step is controlled by a subsection inside config files that live in the UE4\Engine\Config\Localization folder.

You will be interested in the Engine.ini and/or Editor.ini as examples for how to create a config file for your game project

All steps are driven by a single GatherText commandlet. To run this commandlet for the engine target you would use the following commandline args: -run=GatherText -config=…\Config\Localization\Engine.ini

Step - GatherTextFromSource - iterates over all specified source files looking for LOCTEXT and NSLOCTEXT macros and extracts the source text.

Step - GatherTextFromAssets - iterates over all the uassets specified and iterates through all the properties of all the objects looking for FText properties and extracts the source text. This step currently needs optimization work for large projects.

Step - GenerateGatherManifest - Creates a loc manifest from all the gathered strings, this will include audio loc in the future. The manifest functions as the authority for all the text that is currently being used. It does not hold translations. A single manifest is used by all culture variations.

Step - GenerateGatherArchive - Creates/Updates a loc archive for each of the specified cultures. Archives hold translations for source strings. Identical source text with the same namespace share translations regardless of their key. Archives currently only grow in size, nothing is ever removed implicitly.

Step - GenerateTextLocalizationResource - Creates the locres files which the engine loads up and uses. This step combines the information from the manifest and the specified cultures archives to generate a translation table.

You can currently see what things in your product are running though the new localization system by passing -leet on the commandline. Anything that shows up in leet is in the loc system.


You should not be using the Engine.ini file for gathering loc for your project. The ini file you pass to the commandlet tells the commandlet what to gather and where to put it. The Engine.ini gathers the localized text for the engine. Editor.ini gathers text for the editor. You should create a Game.ini to pass to the commandlet.

I like to think the ini configs for the gather commandlet are pretty straight forward. Things are broken down into steps, which are sub commandlets, which you can configure however you want.

Here’s an example of the Engine.ini at Epic’s current head revision, you should follow your Engine/Editor.ini as an example for how to build your own DO NOT COPY THIS ONE as things may be different in your build.

[CommonSettings]
SourcePath=…/…/…/Engine/Content/Localization/Engine
DestinationPath=…/…/…/Engine/Content/Localization/Engine
ManifestName=Engine.manifest
ArchiveName=Engine.archive
SourceCulture=en
CulturesToGenerate=en
CulturesToGenerate=ja
CulturesToGenerate=ko
CulturesToGenerate=zh-CN
CulturesToGenerate=sp

;Gather text from source code
[GatherTextStep0]
CommandletClass=GatherTextFromSource
IncludePaths=Engine/Source/Runtime
IncludePaths=Engine/Source/Rocket
IncludePaths=Engine/Source/Developer
IncludePaths=Engine/Config/
ExcludePaths=/Engine/Config/Localization/
ExcludePaths=/Engine/Source/Developer/NoRedist/CommunityPortalServices/
ExcludePaths=/Engine/Source/Developer/NoRedist/UnrealEngineLauncherServices/
ExcludePaths=/Engine/Source/Developer/NoRedist/BuildPatchServices/
SourceFileSearchFilters=.cpp
SourceFileSearchFilters=
.h
SourceFileSearchFilters=.c
SourceFileSearchFilters=
.inl
SourceFileSearchFilters=.mm
SourceFileSearchFilters=
.ini

;Gather text from assets
[GatherTextStep1]
CommandletClass=GatherTextFromAssets
IncludePaths=/Engine/Content/
ExcludePaths=/Engine/Content/Editor/
ExcludePaths=/Engine/Content/Developers/
ExcludePaths=/Engine/Content/Localization/
ExcludePaths=/Engine/Content/TestPackages/
ExcludePaths=/Engine/Content/QA_Assets/
ExcludePaths=/Engine/Content/EngineSounds/
ExcludePaths=/Engine/Content/Maps/Automation/
PackageExtensions=.umap
PackageExtensions=
.upk
PackageExtensions=*.uasset
ExcludeClasses=Texture
ExcludeClasses=TextureCube
ExcludeClasses=Texture2D
ExcludeClasses=StaticMesh
ExcludeClasses=Material
bFixBroken=false

;Write Manifest
[GatherTextStep2]
CommandletClass=GenerateGatherManifest

;Write Archives
[GatherTextStep3]
CommandletClass=GenerateGatherArchive
bPurgeOldEmptyEntries=true

;Write Localized Text Resource
[GatherTextStep4]
CommandletClass=GenerateTextLocalizationResource
ResourceName=Engine.locres

;Write Text Localization Report
[GatherTextStep5]
CommandletClass=GenerateTextLocalizationReport
DestinationPath=\epicgames.net\root\UE3\Localization\WordCounts
bConflictReport=true
ConflictReportName=EngineConflicts.txt


1. What is the pipeline for localizing text?

The pipeline is highlighted in the document that you linked, though some of the verbiage has changed.

  1. Gather text from sources ( source code files, assets, ini files, etc… )
  2. Generate new manifest
  3. Update archives with new strings
  4. Send archives and manifest to translation team
  5. Integrate translation teams archives/manifest back into main
  6. Build Localization Resources files (*.locres)
  7. Profit!

The GatherText commandlet performs all the above steps except the ones involving the translation team. We currently create one configuration for the Gatherer that gathers strings, updates manifest/archives, and builds locres files.

I highly recommend that you the you use an automation task to run the GatherText commandlet daily.

2. Do the Engine.archive files get stomped by running the GatherText commandlet?

No. Updating archives is currently an additive only process. We don’t currently ever prune unused translations from archives. Manifests on the other hand are completely replaced/stomped when the Gatherer runs.

3. Is there a document that describes the different types of FText format specifiers?

I’m unsure what you mean regarding “format specifiers”, but if you are asking about FText::Format, at head revision it supports 2 different kinds of format args.

Ordered Args - {0}, {1}, {2}, etc… curly braces denote the beginning and end of the format arg and the number indicates the param passed.

Named Args - {Name}, {ID}, {Health}, etc… curly braces denote the beginngin and end of the format arg and the text between the braces the name of arg to be found in the FFormatNamedArgs collection passed in.

There isn’t a document that covers this but we are creating extensive tests for each of the FText features. TextTest.cpp can show you examples of how to perform valid culture aware formatting, comparison, and sorting.

4. How is ICU enabled (and what does it stand for)?

At current head revision ICU is enabled by default on Windows. In the future we will be enabling it on all platforms. ICU stands for ‘Internation Components for Unicode’ and is a open source library that specializes in software internationalization concerns. http://site.icu-project.org/

5. What directs the engine to load a different language resource? Can it be changed at runtime?

Currently, BaseEngine.ini specifies a Culture that will be used as the culture on startup. Alongside the Culture option are LocalizationPaths which tell the engine where to look for loc specific files (*.locres). You will find that an Internationalization category is in BaseEngine.ini/BaseEditor.ini/BaseGame.ini which allows you to customize these options further.

On startup you can specify on the commandline -culture=“ja-jp” to override the ini setting.

In game/editor, you can hot swap the current culture by typing MODE CULTURE=en-us. Right now swapping cultures at runtime just dumps and reloads the localization tables, but this will cause all FTexts to immediately have updated strings, since they only contain a pointer to the string in the loc tables. If your product uses FText correctly (aka not casting them into strings and caching the value) your product should be able to fully refresh upon swapping.


Thanks for the info, Sarge! I’ll try this soon.

We also have some intro docs on FText (including some of the format information) here: FText in Unreal Engine | Unreal Engine 5.1 Documentation

We’ve got localization on an upcoming doc sprint (tentatively August), and I’ll make sure all of Justin’s great notes here get incorporated when we tackle that topic! :slight_smile: