Localisation and Internationalization
It seems that how Gambas
deals with localisation and internationalization is not very clear,
so here is a little article about that...
The Language Environment Variables
The behaviour of an international program must be adapted according to:
- The country of the user.
- The language of the user.
, these two pieces of information are extracted from the two following
system environment variables: $LC_ALL
, or $LANG
is used only if $LC_ALL
is not defined. We will only use
from now in this document.
The syntax of $LANG
is the following:
- xx is a two characters string in lower case, and represents the user language.
- YY is a two characters string in upper case, and represents the user country.
- ZZZZ is usually the system charset.
All characters that follows the xx_YY
string are ignored by Gambas
To run a program under a different localization, you can do:
$ cd /path/to/my/project
$ LANG=fr_FR gbx2
Or you define the LANG variable
in the Environment
tab of the project property ../../comp/gb.form/dialog
In your project, you have two different kinds of strings:
- Strings that are seen by the user (a label text, a message...), and so that must be translated.
- Strings that are internal (a collection key, a field name, a program setting...), and that must not be translated.
You must explicitely tell Gambas
which strings must be translated, and which strings must not.
Strings that are to be translated must be enclosed between braces:
PRINT "A string that must not be translated"
PRINT ("A string that must be translated")
internally uses the GNU translation system: the translated strings are stored in xx_YY.mo
have the same definition as above.
have two sets of string manipulation functions: those that deals with ASCII
only, and those that can deal with UTF-8
Each time you have to manipulate a string that must be translated, then you must use the UTF-8
These functions are all members of the static String class
Otherwise, I suggest you always use ASCII
characters and ASCII
native functions, because they are faster.
The ASCII native functions are: Asc
See String Functions
for all of them.
You often have to translate a Gambas
number or date to a string, and the contrary.
Then, you must know if the string that represents the numeric value or the date will be seen by the user.
Because in that case, the numeric value or the date must be translated according to the user country and language
localization settings. And so, you must use the Gambas
functions that use localization settings
These functions are: Str$
, and Val
() convert any value to a localized string, whereas Val
() tries to convert any string to a specific value by
guessing the value datatype from the string contents: for example, if Val
() sees date separators or time separators,
according to the localization settings, it will assume that the string must be converted to a date.
Otherwise, if the string representation of the numeric value or the date will not be seen by the user
(an application settings stored in a text file for example), then you must use the Gambas
functions that do not use
These functions are: CBool
You will use CStr
() to convert to a string, and all other functions to convert from a string to a specific datatype.
The conversion should be fully bijective, i.e. CStr(CXXX(anyString)) = anyString
, and CXXX(CStr(anyValue)) = anyValue
Beware, there is no full guarantee!
A localization difficulty comes from right-to-left written languages: Arabic, Farsi, Hebrew. The user interface must reverse
some of its components to follow the writing direction.
That should be automatic, as soon as you always
use layout containers like HBox
, or containers that have
their Arrangement property
The other part of the GUI (menus, labels, widget scrollbars...) should adapt, provided that
the underlying toolkit (Qt
or GTK+) behaves correctly.
To try a reversed GUI, you can set the $GB_REVERSE
before starting your program. Please tell if
something does not display correctly.
Here is what you see if you run LANG=fa LANGUAGE=fa gambas2
on my Mandriva: