# Unreal Localization Support

Audience: UnrealScript Programmers, C++ Programmers, Translators.
Last Updated: 05/01/99

### External Localization Links

- Microsoft Global Development Page
- To Find a Translator
- Visual C++ Unicode documentation (requires Visual C++)
- Windows Code Pages List (requires Visual C++)
- Unicode Test Page
- Worldwide Web Consortium: International Resources

### Overview of Unreal localization support

The design goals for Unreal's translatability are:

- Make Unreal-technology based games easily translatable, where translations to UNICODE languages (basically, all worldwide languages that are significant to the PC and consumer electronics markets) require no changes to source code or binary data files.
- Build localization support into the engine at a fundamental level so that all the translation work can be done by a translator person without taking programmer or level designer time.
- Make translations modular, so that translations can be installed after a game has been purchased.
- Keep translations robust, so that when updates/patches to a game are released, they don't need retranslated; and if a particular piece of text hasn't been translated, be able to fall back gracefully on the international english text.
- Make the translation support portable, which means that Windows resources (which are great for translating pure Windows apps) are problematic.

The approach we chose is to place localized text in .ini style files which correspond to Unreal package files. Translation capability is available in UnrealScript and C++ in three key areas:

- Native script support: default string properties of actor (and object) classes can be defined using the "localized" keyword in UnrealScript (or CPF_Localized in C++). These default properties contain the international english text as specified by the programmer or level designer. However, text in the current language's .ini files overrides text in the .u files, so translations can be performed purely by creating a new .ini file, without modifying any code.
- In C++ and UnrealScript, there are Localize() functions which take an arbitrary key name and return its corresponding localized text. This is intended mainly for C++ code where there is no convenient UObject containing default properties in which to place the translatable string.
- The translation .ini files contain a [LocalizedNames] section which enables mapping UnrealScript names (C++ FName's) to localized text. This is used in areas of the engine which are based on FName's internally but must use a localized representation of those FName's for display and user interaction purposes. For example, the Preferences windows are based on direct editing of named UnrealScript properties (like SoundVolume) which must be translated into other languages, and which also may benefit from being translated into more human-readable English, for example "Sound Volume Level".

### Authoring UnrealScript code for translatability

Put all readable text into string instance variables, and use the "localized" keyword to designate them as localized, and use the "localized" keyword when declaring the class. For example:

This code will be a bitch to translate because it will require messing with the code:

    class OuchSayer expands Trigger;
    function Trigger( Pawn A, Actor B )
    {
    	A.Message( "Ouch, you touched me!" );
    }

This code will be easy to translate because it can be done in an .ini file by a non-programmer:

    class OuchSayer expands Trigger localized;
    var() localized string[64] Msg;
    function Trigger( Pawn A, Actor B )
    {
    	A.Message( Msg );
    }
    defaultproperties
    {
    	Msg="Ouch, you touched me!"
    }

The other advantage of this approach is that it makes it easy for a writer to go through and clean up the English text in a game. This has been beneficial in Unreal development, because we have a lot of level designers and programmers writing game text which needed reworking due to stylistic inconsistencies.

### Character set

Unreal is designed to use the 16-bit UNICODE character set. The standard Unreal fonts include only the first page of UNICODE language characters, but our built-in TrueType font importer enbales you to import (with optional antialiasing) any Unicode TrueType font, i.e. for piecing together Unreal fonts that support the roman languages, Japanese, and Korean.

### Localized file extensions

Each language has a characteristic file extension, which Unreal uses to try to find the localized text for a given package file. For example, we define the following extensions:

- Filename.int: International English text.
- Filename.fr: French text.
- Filename.de: German text.
- Filename.esp: Spanish text.
- Filename.itt: Italian text.

When Unreal loads a package file (such as an .unr level file, or a .u class file), it searches for localized text in the following places. For example, when loading MyLevel.unr:

- If using a language other than English, it looks in that language's localized file, such as MyLevel.fr for French.
- If that file was not found, it looks in the international English version, MyLevel.int.
- Otherwise, the text stored in the raw package file is used.

### Preparing level text for translation

Lots of game text is stored within .unr level files, for example the text messages stored with Counters, Triggers, and TranslatorEvent actors. The intent is that level designers will write the first-pass version of this text in English, and then the text will be localized (or the English version cleaned up) by a translator or writer, who edits the .ini files and never modifies the .unr level file itself.

Not modifying binary data files (such as .unr level files, and .u class files) is an important concept, because many aspects of Unreal, including network play, rely on the exact binary contents of these data files. If translations were performed by having someone actually modify the .unr levels, or .uc scripts (thus affecting the .u binary files), it would be impossible for French or German people to play on American Unreal servers, etc.

UnrealEd supports a special console command analyze an Unreal binary file (such as an .unr or .u file) and generate an .ini style text file containing the international English version of the text. For example, to process UnrealI.u, type on the console:

        dumpint UnrealI.u

And that generates the file UnrealI.int, the international text for the package. That file can then be given to translators, who rename it to their appropriate language's extension (such as UnrealI.fr or UnrealI.de) and translate all of the text within.

### Hardcoded C++ translation support

    CORE_API const char* Localize( const char* Section, const char* Key, const char* Package=GPackage );

- Looks in the localization file corresponding to Package (i.e. Engine.int for the Engine package, using international English) and returns the localized string for Key, found in the Value section. If Package isn't specified, it defaults to the current package being compiled.

    CORE_API const char* LocalizeError( const char* Key, const char* Package=GPackage );
    CORE_API const char* LocalizeProgress( const char* Key, const char* Package=GPackage );
    CORE_API const char* LocalizeQuery( const char* Key, const char* Package=GPackage );
    CORE_API const char* LocalizeGeneral( const char* Key, const char* Package=GPackage );

- These functions work like Localize but they look in a the section corresponding to their function name instead of taking Section as a string. For example, LocalizeError looks in the "Error" section.

### Hardcoded UnrealScript translation support

    intrinsic function string[192] Localize( name KeyName, name SectionName, name PackageName );

- This puppy does the same thing as the C++ Localize function.

### Debugging translations

When a C++ or UnrealScript localization function is called for which no corresponding localized .ini file entry is found, the returned string is displayed as <?Package.Section.Key?>, and an entry is written out to the log to record the missing translation. This is a non-critical error. Because this is easy to screw up, I recommend coverage testing all lines of code which lookup localized text.

### Non-technical information for translators

You can edit .int files with a text editor like Notepad. A typical .int file will contain a lot of data that looks like this:

    [Errors]
    FileOpen=Error opening file
    FileNotFound=Can't find file '%s'
    FileClose=Error closing file

    [Progress]
    Saving=Saving file %s...
    Closing=Closing

Bold text indicates the text to be translated. For clarity, these .int files contain three kinds of data:

- Section headings, such as [Errors] and [Progress]. These are used internally by Unreal. Do not translate these!
- Key names such as FileOpen= and FileClose=. These are used internally by Unreal to identify the text. Do not translate these.
- Translatable text such as Error opening file and Saving file %s.... This text always immediately follows the "=" sign. Translate this.

So, for example, the result, translated file above might look like:

    [Errors]
    FileOpen=Fehleröffnung Datei
    FileNotFound=Kann nicht Datei %s finden
    FileClose=Schließende Datei des Fehlers

    [Progress]
    Saving=Einsparungdatei %s...
    Closing=Schließen

There are several important points to keep in mind:

- Be sure to test all translated text thoroughly in the game to make sure it's complete and it fits in the space available. Some areas that contain text, such as the menus, have a limited amount of space and the translated text will overflow if it's too large.
- When you see symbols like %s or %i in the text, leave them and be sure not to move them around. These characters are used by Unreal to designate where numbers, and other text appear. For example, changing "Loading item %i from file %s" to "Loading file %s, item %i" will cause Unreal to crash when it displays the text. Unreal typically formats a message like "Loading item %i from file %s" into something like "Loading item 10 from file Unreal.unr"
- The standard Unreal fonts should contain all of the ANSI characters necessary for translation into standard ANSI languages.

### Limitations

- Unreal's text printing support is currently limited to left-to-right. Support for other orientations, or bidirectional text (i.e. for Arabic or Hebrew) is not provided, but could be pieced together without too much pain.

### End