Guiliani  Version 2.5 revision 6773 (build 33)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Internationalization

Introduction

Since most products will be aimed at an international market, with customers all over the globe, they need a multilingual user interface, which allows the users to operate it in their native language.

Developing a GUI in multiple languages imposes some challenges on the developer. The most obvious one is that texts should not be represented by simple strings within the source code anymore. If you wish to change them at runtime, or allow an external translation bureau to easily translate all texts, it soon becomes pretty clear that a dedicated language management mechanism is required. In Guiliani this can be found in form of the CGUILocalisationHandler class.

The localisation handler

The localisation handler (CGUILocalisationHandler) maps abstract text identifiers onto actual text strings in a given language. Having this mapping allows you to reference text independent of the chosen language, simply by its ID. When browsing through Guiliani's API you will therefore find that most interfaces will allow you to hand over a text either by a string or by using a text ID. If you simply wish to display a static non-internationalized text, then a string will do for you. In case you need a text to be translated when changing languages, use text IDs instead.

Accessing the localisation handler can be done comfortably via the GETLOCALEHDL helper macro. Its interface allows you to retrieve the string mapped to an ID, to set the string behind an ID, or to load a complete language file. Please refer to the localisation handler's API documentation for detailed help.

Language files

Language files for Guiliani are UTF-8 encoded plain text files. They are typically, though not necessarily, marked by the ending .lng. The order in which text strings appear line by line inside the language file must correspond to the order of the corresponding text IDs in the UserTextResource.h file. You can edit these files using your favourite editor as long as it supports reading/writing UTF-8 encoded files (e.g. the standard Windows Editor does support UTF-8). Be aware that the language-file must contain a BOM (Byte Order Mark) as the first three bytes. These bytes should thus read: 0xef, 0xbb, 0xbf.

Unicode strings

Most languages will use characters that are not part of the standard ASCII set. This is where Unicode comes into play. Without going into too much detail, as there is plenty of comprehensive documentation on this topic available on the web, it is important to know that Unicode is a standard for the consistent representation of text on computers, allowing you to represent almost any known written character, ranging from simple Latin, via Greek or Cyrillic, to Klingon.

Now there are various ways of encoding Unicode. An encoding maps (possibly a subset of) the range of Unicode code points to sequences of values in some fixed-size range, termed code values. The most common encodings are UTF-8 and UTF-16. Both have their advantages and disadvantages and depending on your target platform and font-engine of choice, it may be desirable to use one or the other. Guiliani features a smart string class called eC_String, which is capable of storing strings in either of the two formats, and to convert between them (and plain ASCII). You will notice that Guiliani will make use of this class and avoid using plain CHAR or WCHAR pointers.

Text Fragments

Sometimes it is necessary to have dynamic parts inside Text-Resources, i.e. values which should be displayed as part of a text. These dynamic parts are called Text-Fragments and can easily be used in Guiliani. You can simply insert placeholders for your variable parts in side the text-representation using "{XXX}" where XXX is the index of the placeholder. If the target language needs a different order for these dynamic parts, they can of course be re-ordered to fit the needs. Also there is practically no limitation of the number of dynamic parts in a Text-Resource.

Example: "Hello {1}, the current date is {2}. You have {3} unread mails." ID: TXT_GREET_USER Having this Text-Resource, you can register 3 Text-Fragments to appear inside the text and be dynamically updated during runtime.

GETLOCALEHDL.RegisterTextFragments(TXT_GREET_USER, 3); // will register three text-fragments for the Text-Resource
eC_String kUserName = GetUserName(); // get user-name from database
// the last parameter is a boolean value indicating if controls currently using the Text-Resource should be notified immediately
GETLOCALEHDL.SetTextFragment(TXT_GREET_USER, 0, kUserName, false); // set the first text-fragment
GETLOCALEHDL.SetTextFragment(TXT_GREET_USER, 1, GetDate(), false); // set the second text-fragment
// update the third text-fragment and notify all controls of the new text
GETLOCALEHDL.SetTextFragment(TXT_GREET_USER, 2, eC_String(GetNumberOfUnreadMails()), true);
GETLOCALEHDL.UnregisterTextFragments(TXT_GREET_USER); // unregister text-fragments

With RegisterTextFragments you can register text-fragments for a Text-Resource which can then be updated dynamically during runtime. SetTextFragment is then used to update specific parts of the text with dynamic values. Text-Fragments are persistent and keep their values when switching the languages during runtime. When Text-Fragments are no longer used for a Text-Resource, they can be unregistered with UnregisterTextFragments.