Locale Catalogue Resource Files
The Locale Catalogue Mechanism
Marking Static Strings for Translation
Locale catalogue resource files are used to provide translations for an application. These files act as a structure (similar to a hashmap) containing pairs of original strings (used as identifiers) and their corresponding translations. The resource files are maintained in a source file format (*.4s) and must be compiled into *.res files before use.
The basic structure of a locale catalogue resource file is as follows:
<output_file_name> {
<key1_string> { "<locale string 1>" }
<key2_string> { "<locale string 2>" }
...
}
Extended Syntax:
// comment line
<appname|default>[_language[_country]] {
<key> { <value> }
<group_key> {
<element_key1> { <value1> }
<element_key2> { <value2> }
}
}
1. output_file_name:
2. Naming Conventions:
3. Simple Structure:
4. Complex Structures:
5. Key Formatting Rules:
6. Compilation:
7. Escape Characters:
Example
The following is an example of a locale catalogue resource file for the hello_world application with German (de_DE) translations:
// comment: locale catalogue resource file for hello_world application
hello_world_de_DE {
Find {"Finden"}
Cancel {"Stornieren"}
Yes {"Ja"}
No {"Nein"}
common {
actions {
accept {"akzeptieren"} // The application string identifier for this value will be: common.actions.accept
}
}
}
Breakdown of the example:
The Locale Catalogue mechanism is designed to enable text translation and replacement in application forms at runtime, based on the UI locale settings. It provides a streamlined method for defining external resource files that the runtime system can reference to assign localized text to UI elements. This feature is essential for implementing internationalization (i18n) in applications and adapting terminology to fit specific business contexts based on the deployment region.
Key Features:
To specify strings for translation in source code or form files, use the %"string" notation. This notation marks the string for replacement at runtime with the corresponding text from the compiled resource files.
Example in .fm2 form files:
Example 1: Static String Localization
%"static_string": static_string is a literal that acts as both the identifier and default text.
.4gl file:
MAIN
DISPLAY %"common.actions.accept"
END MAIN
.4s file:
hello_world_de_DE {
common {
actions {
accept {"akzeptieren"} // The application string identifier for this value will be: common.actions.accept
}
}
}
The identifier common.actions.accept is used to locate the translated text in the resource files.
The LSTR() function returns a translated string corresponding to the string identifier passed as a parameter. It is a versatile function that allows dynamic translation of strings based on the active UI locale, supporting both constant strings and variables. This capability is crucial for internationalizing applications, as it enables dynamic loading of localized text based on user settings or application context.
LSTR(<string_identifier>)
<string_identifier>: The string key or identifier used to fetch the corresponding translated string from the loaded locale resource files.
Example: Basic Usage
MAIN
-- Loads translation for 'common.actions.accept'
DISPLAY LSTR("common.actions.accept")
-- Loads translation for 'hello_message'
DISPLAY LSTR("hello_message")
END MAIN
Example: Dynamic String Localization
MAIN
-- Loads translation for the static identifier 'Hello World'
DISPLAY %"Hello World"
-- Dynamically constructs and loads the translation for 'Hello World'
DISPLAY LSTR("Hello" || " World")
END MAIN
This method enables the construction of identifiers dynamically, making it highly versatile for various scenarios.
Example: Using LSTR() with Variables
MAIN
DEFINE status STRING
LET status = "approved"
-- Loads translation for 'order.status.approved'
DISPLAY LSTR("order.status." || status)
END MAIN
The LSTR() function returns a translated string from a resource file with the currently active UI locale corresponding to the identifier provided as its parameter:
Application data keys can be stored in a database and dynamically translated using the LSTR() function.
Example:
SELECT order_warning INTO rec.order_warning FROM orders WHERE ...
LET msg = LSTR(rec.order_warning)
DISPLAY BY NAME msg
The SFMT() operator is used to fill the placeholders in strings with certain values. You can use any valid expression as a parameter with SFMT(), and numeric or date / time expressions are converted to strings based on the current format settings (DBDATE).
SFMT(expression_string, parameter [, parameter [...]])
expression_string is a string expression;
parameter is any valid expression to replace the placeholders.
A placeholder in a string is represented by a percent symbol, followed by the number of the parameter. For instance, %2 refers to the second parameter. You can use the same placeholder more than once in the string. If you need to include a literal percent symbol, you'll need to escape it by using %%.
Example .4gl file:
MAIN
DEFINE l_date DATE
DISPLAY SFMT("String with the paramenters placeholders: #1 is %1; #2 is %2 .", "First parameter", 2)
CALL fgl_putenv("DBDATE=DMY4/")
LET l_date = "25.02.25" # DBDATE format in variable is DMY2. when for runtime it's set to DMY4/
MENU
ON ACTION "English"
DISPLAY translated_string("en_US", l_date)
ON ACTION "German"
DISPLAY translated_string("de_DE", l_date)
ON ACTION "Ukrainian"
DISPLAY translated_string("ua_UA", l_date)
ON ACTION "Exit"
EXIT MENU
END MENU
END MAIN
FUNCTION translated_string(p_ui_locale STRING, p_date DATE) RETURNS (STRING)
CALL fgl_set_ui_locale(p_ui_locale)
RETURN SFMT(%"The date in format %2 is %1.", p_date, fgl_getenv("DBDATE"))
END FUNCTION
Source files (*.4s) must be compiled into binary resource files (*.res) using the genrb tool.
Compilation Command:
genrb [OPTIONS] [FILES]
Common Options:
Example Compilation:
genrb -v -d ./output ./source/hello_world.4s
The compiler uses \\ as an escape character for special characters like:
Resource files are loaded at runtime based on the current UI locale setting. The application searches through several paths:
File Loading Order:
The highest priority is given to the most specific file (<app_name>_<language>_<country>.res). At runtime, strings from the loaded resource files are merged, with later-loaded files taking precedence.
Setting UI Locale
The Lycia client determines the default UI locale based on browser language settings. It sets the environment variable QX_UI_LOCALE for the application.
Overriding UI Locale
Example: