This document serves as a reference for the Unreal Engine 3 localization system.
Localized Text Files
See the Localized Text Files page for information about the file format, as well as working with string and binary data.
The engine looks for localizated text files in a configurable selection of paths (Core.System.LocalizationPaths, defaulting to "Engine\Localization"). When localizing a resource, it first looks in the currently configured language localization file. If it fails to find a localized version of that resource, it then looks for an entry in the international (English) localization file (.INT).
In addition to using the Full Loc Export... in UnrealEd, the
exportloc commandlet is also available.
exportloc commandlet will export localized strings in UnrealScript packages to a localized text file:
Setting the Active Language
The language can be changed by setting the Language variable in your game project's Engine configuration file to the specified language, which correlates to a localization directory.
For example, this is how you would set the language to Japanese:
To test the localization, create a fake language called XXX. Replace all characters with the letters X. This makes it real easy to spot missing localized text.
Translators should work on the localization files (text), not the content (binary). Be wary about accepting resaved content from external teams. Who knows what other properties, hacks, etc. can be applied to those content packages!
When new objects are created that require localization, simply perform a Full Loc Export... from within the editor. This will not stomp on existing loc data because this data will already be in memeory at the time of export.
Our workflow for Gears of War was to provide each international (English) localized text (.INT) file, as well as an updated diff for the file, in order to demonstrate to the translators what new localized objects or object properties had been created (re-exported) since the last update; they were responsible for propagating to these new strings to their language version of the file.
Alternatively, if one's faith in the localization team's ability to handle diffs is low, one could re-xport localized text files for each language individually by simply set the engine language to the target language before opening the editor and exporting.
In this manner, you can just send the INT files directly to translators. For Gears of War, localization teams were provided with localization files and watermarked builds so that the content can be tested in-game. We only accepted changes that were made to the localization files, for reasons described above.
We do not have any additional steps to get the localization files into something more editing-friendly, such as Excel. We rely on the localization teams to massage the data into whatever internal formats they need.
NOTE: Streaming localized textures are not supported by the engine by default because the texture offset into the cooked texture file is stored in the seekfree package.
Audio localization requires some setup. The easiest (and recommended) process is to split off all the sound cues and put them in packages in 'MyGame\Content\Sounds', then put all the localized audio wave packages in subfolders named by the three letter language code.
This yields something of this ilk -
When localized sound cues are loaded, it will load the sound waves for the selected language. This means any sound cue changes will be applied uniformally to all languages with a single edit.
A sound cue is judged to be localized if it references sound waves in a three letter subfolder that matches a known language code, or it has subtitles. If you use the above folder layout, everything will be localized as you expect. See the case study below for a more concrete example.
Some videos have a corresponding .txt file which to relate to keys in the 'Subtitles' localization text file, along with their appearance time. The .txt files are simply for subtitles, nothing to do with the audio being played. These must be made by hand, with the appropriate timings (the first line is number of ticks per second, that the rest of the lines use to determine start/stop times for the line).
For audio in the movies, make a Bink movie and mix in all the languages into the movie as a collection of channels. What we do is remap the front left, front center and front right tracks to the localized audio, then have common rear and subwoofer tracks for all languages.
FBinkMovieAudio::SetSoundTracks() will return the array of channels that maps to the speakers, thusly -
| || INT || FRA || ITA |
| Front Left || 0 || 6 || 9 |
| Front Right || 1 || 7 || 10 |
| Front Center || 2 || 8 || 11 |
| Subwoofer || 3 || 3 || 3 |
| Rear Left || 4 || 4 || 4 |
| Rear Right || 5 || 5 || 5 |
For information on localizing the editor controls, see the Editor Localization page.
Case Study: Localization in Gears of War
In Gears of War, the audio for each character has been divided into three categories:
Each category corresponds to a sound package. So, Gears' main character Marcus has three packages: Marcus_Dialog.upk, Marcus_Chatter.upk and Marcus_Efforts.upk. Only the dialog and chatter packages require localization, as the efforts package does not contain sound with any speech. Certain characters which don't deliver intelligible dialog have only an efforts package, and aren't localized.
The sound system in UE3 makes the distinction between a sound source (a .wav -- SoundNodeWave in Unreal terms) and the use of a sound (a SoundCue). Localization exists at the wave level, so that localization data for a sound is shared with the wave amongst the cues
that use it. So, we further divide the localized sound packages into a wave package and a cue package; the former contains only SoundNodeWave objects, the later only SoundCue objects. In making this distinction, we can swap out the wave packages of different languages without affecting the sounds cues referenced by the levels/assets.
So, using Gears' Marcus character as an example, the complete package break-down for a character is as follows:
Marcus_Dialog_Cue -- package containing only SoundCue objects for Marcus' dialog lines;
Marcus_Dialog -- package containing only SoundNodeWave objects for Marcus' dialog, in English;
Marcus_Dialog_jpn -- as above, but in Japanese;
.... -- etc. for other languages
Marcus_Chatter_Cue -- SoundCue objects for Marcus' chatter (gameplay) lines;
Marcus_Chatter -- English SoundNodeWaves for Marcus' chatter;
Marcus_Chatter_jpn -- As above, for Japanese;
Marcus_Efforts -- Contains both SoundCues and SoundNodeWaves for Marcus' efforts (unlocalized).
Under the hood, the loading code will look at the engine language setting and attempt to load a language-localized version of a package before loading the default English-language version. The expected naming convention is that the language-localized version of a package is suffixed with "_ext", where ext is the language extension returned by appGetLanguageExt. If no language-localized version is present, or if the engine language setting is English ("int", or international), an un-suffixed version of the package will be loaded. This allows for 'partially-localized' languages -- languages for which subtitles are available (via .ini loc export of the SoundNodeWave packages) but fully localized audio is not.
- Dialog -- sound which are lines of dialog that are issued in unique scripted situations.
- Chatter -- lines of dialog issued by a player as a result of an unscripted gameplay situation. For example, frustration with a jammed gun, triumph when taking down an enemy, etc.
- Efforts -- gameplay sounds containing no speech -- grunts, yells, pained sounds, etc.
Please see the following site for codes used to represent the names of languages: http://www.loc.gov/standards/iso639-2/englangn.html
Our current set is -
| INT || American English (not Rest of World English) |
| JPN || Japanese (no TTS support) |
| DEU || German |
| FRA || European French (not Canadian French) |
| ESM || Latin American Spanish (Modern?) (no .NET, Speech Recognition support) |
| ESN || European Spanish (Iberian? Castilian? Traditional?) |
| ITA || Italian |
| KOR || Korean (no TTS support) |
| CHT || Chinese Traditional (No Speech Recognition or TTS support) |
| RUS || Russian (No Speech Recognition or TTS support) |
| POL || Polish (No Speech Recognition or TTS support) |
| HUN || Hungarian (No Speech Recognition or TTS support) |
| CZE || Czech (No Speech Recognition or TTS support) |
| SLO || Slovakian (No Speech Recognition or TTS support) |