Application Localization

Official Content
This documentation is valid for:

Automatic translation is a process carried out at specification time that changes every string constant (see exceptions below) into its translated counterpart (static translation) or into an automatically generated message identifier reference (run-time translation). Message identifier references are resolved at run-time by the generated code.

How is automatic translation activated? At the Environment level, select the proper value for the Translation type instead of "No translations" value.

What is translated?

The automatic translation process translates every string constant that appears in your GeneXus code. Exceptions are:

  • String literals in HTML forms (those that are not the Text Block control).
  • String literals that you do not want to be translated (see below).
  • Help (see more in HelpTranslation).
  • The first parameter of the SetLanguage function and GetMessageText function.
  • String literals in formulas' definition.
  • String that follows the commands Do, Sub, Event (*) (i.e. Subroutines and Events names)

A "string constant" is a set of characters enclosed in single or double quotes used in your application code. Value ranges, Enumerated Domains Methods and Properties, Combo box and Radio button values are also string constants. They are case sensitive and leading/trailing spaces are ignored.

To avoid translating a string constant you must prefix it with the ! character as in:

  • !"Client name" or !'Client name'

The translation cycle

When automatic translation is activated, GeneXus automatically builds a list of string constants used in your GeneXus code as objects are specified. These string constants are assumed to be in the Language specified in the Kb Language property. Once the above list is complete and translated into any required language, your application is also translated.

The steps required to translate you application are:

  1. Set the Translation type property to either Static or Run-time (please note that Run-time is not available for all generators).
  2. Select a predefined Language object (in the Localization node in the KB Explorer) or create a new one for the target language you want your application to be translated into.
  3. Specify the entire application. This way, all strings to be translated are created in the Language objects and are ready for translation.
  4. Translate every string constant into the target language. (You can use GeneXus Translation Tool)
  5. If you selected Run-time translation, just add a SetLanguage function call (see below) to your code, specify, generate and... translate.
  6. If you selected Static translation you must select the Language in the Translate to language Environment property, specify, generate and... translate.

Static translation

Static translation is achieved at specification time. The resulting application cannot change the language at runtime. Static translation is the best performing translation option as no runtime code is added. To activate Static translation set the "Translation type" property (at Environment level) to Static, and select the language you want to translate into in the Translate to language property. The full translation cycle is described above.

When to use static translation

Static translation is available for all generators (many generators only have this value for the Translate environment property). Static translation provides the best performing code as no runtime overhead is added: translation is performed at specification time. Having your application in different languages requires different executables (one for each language). If you plan to have your application translated into different languages using Static translation, you should set up a new Environment for every new language you want to translate into.

Notice that if your languages references different ISO code pages, you will need to change the windows regional settings configuration for each language generation process.

For instance, if you have languages such as Japanese, Chinese, Thai and so on; the static translation process needs to correctly configure the associated Language for non-Unicode programs (Windows configuration). If this is problem for your environment switch to run-time translation.

Run-time Translation

Run-time translation is available for .NET, Java and .NET Core generators. Run-time translation is the most versatile solution with a little performance overhead (compared to Static translation). When using Run-time translation you can:

  • Manage a single set of executables running in different languages;
  • Allow the end-user to select the desired application language among the list of available languages;
  • Add new languages to your application without changing the executable code.

The Language object

To be able to translate your application you must first select one of the predefined Language objects, or create a new one. A Language object defines a new language that can be referenced later for translation. Language objects have several properties and the list of string constants already found in your code (none if you did not specify any program) ready to be translated.

Predefined GeneXus languages

When you create a new Knowledge Base or open an existing one, a set of predefined string constants and Languages are created in it (or updated if they already existed). They are used in the generated code for messages, button captions, labels, etc.

The predefined languages are:

  • English
  • German
  • Italian
  • Japanese
  • Portuguese
  • Simplified Chinese
  • Spanish
  • Traditional Chinese
  • Arabic

You can view them in the KB Explorer, in the localization node (under customization):

LocalizationNode

Cross reference

GeneXus provides a cross reference to where string constants are used.

Language consolidation and distribution

Several options for language management are included.

Export options

  • Include GeneXus Messages --> Include the GeneXus messages in the XPZ.
  • Include Untranslated Messages --> Include the untranslated messages in the XPZ.

Import options

Programming considerations

Language names and description criteria

Shared translations among GeneXus users worldwide can save translation time. It can be achieved if we all have a well-known Language naming convention. GeneXus suggests using the English name for languages as Language object names, and the language name of each language in its language as the Language object description. For example, Spanish:Español, Italian:Italiano, etc.

Format function

Syntax: Format( <FormatExpression>[, <StringExpression1>[, ...]] )

The Format() function is very important for translation purposes as statements may be built differently in different languages.

FormatExpression is a string expression (character or varchar) having zero or more parameter markers (up to 9, from 1 to 9). For example: Format( "%1's age is %2 years old.", "John", "13"). In the example, parameter markers are %1 and %2. They state where the values of "John" and "13" are to be embedded in the resulting string. The result must be "John's age is 13 years old".

If a '%' sign must be included in FormatExpression, it must be preceded by the '\' (backslash) sign. For example: "This is not a parameter marker: \%1".

GetMessageText function

Syntax: GetMessageText(<MessageCode>, [LanguageObjectName])

The GetMessageText function searches the Language "LanguageObjectName" (or the current language if that parameter is omitted) for a given message code. No errors are returned by this function. If the MessageCode is not found in the current Language, the MessageCode is returned. It is, therefore, a good design method to use full-text message codes that can be used as message texts.

SetLanguage function

Syntax: SetLanguage (LanguageObjectName)

LanguageObjectName is the name (not the description) of a Language in your Knowledge Base. The SetLanguage function returns 0 if the Language can be changed. Otherwise, it returns a non-zero value. If the specified language cannot be loaded, then no language change is performed and the current language remains as if the method had not been executed. Once the SetLanguage function has been executed successfully, the Language setting remains active for the rest of the session. In Web applications, this means that the GeneXus code automatically saves the value of the current language in the current session.

Note: in order to refresh all the texts and language-dependent elements of the web page, a refresh command should be added after the call to SetLanguage function. This refresh command will make a GET of the web page, a different behavior than if the command is not used after a SetLanguage function (check SAC #24129). (remember that making a GET of the web page implies that values inputted on editable fields will be lost)

GetLanguage function

Syntax: GetLanguage()

The GetLanguage function returns the name (not the description) of the currently active Language object. The most common usage is to set a variable of your own with the currently selected Language as in the following example. Variable &MyLanguage holds the value of the currently active Language. It is also shown on the screen as a Combo Box allowing the user to select any other available languages.

Event Start
    &MyLanguage = GetLanguage()
    ...
EndEvent

Event &MyLanguage.Click
    If SetLanguage(&MyLanguage)<>0
       ...
    EndIf
EndEvent

Avoiding translation of automatic string constants

Applications include constants that should not be translated. To avoid translating a string constant, you must specify the '!' sign as the starting string constant character, like in the following examples.

  • "Client name" or 'Client name' will be translated
  • !"Client name" or !'Client name' will not be translated

Common translation problems

Translated Conditions/Where/If Commands In some cases the translated application does not properly work with existing data. Such is the case, for example, of the following comparison: ClientCategory = "Good". When translated into Spanish, the generated code should look like this: ClientCategory = "Bueno". This is fine as long as you want to run it against your current Spanish data. The underlying problem is that Data Base data has translatable text ("Good" in the example). Alternatives for fixing the problem are:

  • Use Enumerated domains. Enumerated Domain codes are not translated, but their descriptions are.
  • Change the literal to a non-translatable literal !"Good".

Notes

  • As of Android 7.0 (Nutshell), it is possible to define multiple languages on the device settings. Taking advantage of this feature, GeneXus automatically infers which language of the Knowledge Base is closer than the primary dialect set on the device. In this terms, if the primary user language setting is not supported by the application, it will prefer the secondary language (and so on). This process continues until finding one language that matches the user preferences, or it will be used those set on the Kb Language property as default.
    For example, suppose that the app uses English/Italian, and the default is English.
    - If the device is set to use Spanish (only), then the app will be displayed in English (default).
    - But, if the device is set to use Spanish/Italian, then the app will be displayed in Italian.

See also

Kb Language property
Translation type
Translate to language property
Environment Preferences
Autoresize form controls property