Working with Embedded Wizard: Managing localization
Embedded Wizard supports intrinsically the development of localized, multilingual GUI applications. In practice, you can manage in every constant or bitmap resource several, language specific contents. The selection of the right content occurs automatically just in the moment when the constant or resource is evaluated within an expression, e.g. when the constant is assigned to a Text view or a bitmap resource is assigned to an Image view.
Furthermore, you can configure a GUI component to automatically update its appearance every time the user changes the currently selected language. Thus except special application cases, the implementation of localized GUI applications able to switch the language dynamically at the runtime doesn't require a single line of code.
Add language members
The available languages are represented by language members. In principle, for every language you intend to support in your application you should manage in the project a corresponding language member. The name of the member identifies then uniquely the language variant within your implementation. Thus, if you plan to support the languages French and Spanish it is obvious to add two language members and name them French and Spanish.
If you take a look at your project you will notice, that it contains already one language member named Default. This member represents the fallback language variant to use wherever a constant or resource doesn't provide any localized value for the currently selected language. As such the Default language is ideal to represent the main language in your project. We, for example, use Default for the language English. A project supporting English, French and Spanish contains thus three language members Default, French and Spanish.
IMPORTANT
The presence of the language member Default is obligatory in every Embedded Wizard project. You should in any case avoid to delete it.
Localize a constant
The content of a constant member is determined by its attribute Values. Here you have the possibility to specify initialization expressions individually for every language existing in your project.
For example, the following screenshot shows the initialization expressions for a string constant named WelcomeText. As you can see, the constant contains individual values for the languages French, German and Spanish. The fallback language variant Default represents in this project the language English. The entry for Chinese is left empty. Thus evaluating the constant WelcomeText with Chinese as the currently selected language will result in the value from the entry Default:
Based on the specified attribute values Embedded Wizard determines which variants of the constant are expected to be available at the runtime. Accordingly, for every variant an individual copy of the constant is managed in the application. The following figure demonstrates the internal structure of the above example constant WelcomeText how it is stored in the resulting application:
Since constants are not limited to store strings you can manage in your project localized, multilingual constants containing e.g. color, int32 or even rect values. In this manner you can implement applications able to adapt its appearance and layout according to the currently selected language.
Localize a bitmap resource
The content of a bitmap resource is determined by its five attributes FileName, Format, FrameSize, FrameDelay and Dithering. Each of these attributes can be localized with individual initialization expressions for every language existing in your project. In the case, an attribute doesn't depend on the language selection, you simply specify a value for its Default language only.
For example, if you localize the attribute FileName, the affected bitmap resource will incorporate different, language dependent images. The following screenshot demonstrates such bitmap localized for the languages French, German and Spanish. The fallback language variant Default represents in this project the language English. The entry for Chinese is left empty. Thus evaluating the bitmap WelcomeLogo with Chinese as the currently selected language will result in the English version of the image specified in the entry Default:
Based on the specified attribute values Embedded Wizard determines which variants of the bitmap resource are expected to be available at the runtime. Accordingly, for every variant an individual copy of the bitmap is managed in the application. The following figure demonstrates the internal structure of the above example bitmap WelcomeLogo how it is stored in the resulting application:
Localize a font resource
The content of a font resource is determined by its 10 attributes FontName, Height, HeightMode, RowDistance, Bold, Italic, AspectRatio, Kerning, Ranges and Quality. Each of these attributes can be localized with individual initialization expressions for every language existing in your project. In the case, an attribute doesn't depend on the language selection, you simply specify a value for its Default language only.
Embedded Wizard handles localized, multilingual font resources in a different way, as it is habitual to do with bitmap resources and constants. Instead of permitting the application to select an individual, separate variant of a font resource at the runtime, Embedded Wizard combines all variants together and considers them as a single large virtual font. This virtual font incorporates thus glyphs from different real fonts resulting from the localization. In this manner text containing mixed Chinese and Arabic contents can be displayed easily, even if the Chinese and Arabic glyphs are originally defined in separate physical fonts.
The following screenshot demonstrates an example of how a font resource is localized to incorporate Chinese glyphs from a TrueType font Microsoft JhengHei and Latin glyphs from the font Arial. Please note the usage of the Ranges attribute. It determines which glyphs are taken over from the original font and incorporated into the resulting font resource:
Based on the specified attribute values Embedded Wizard picks out from the original fonts all desired glyphs, converts and packs them together. Similarly, the metrics of the resulting font are determined from the values provided by the original fonts. Embedded Wizard treats the metrics ascent, descent and leading individually and promotes always the largest value. In other words, if you have a font resource localized with a 32 pixel and 40 pixel height, then the resulting virtual font will be considered as having 40 pixel height.
The following figure demonstrates the internal structure of the above example font Font with Chinese and Latin glyphs how it is stored in the resulting application:
Select the actual language
At the runtime the language selection is controlled by the global built-in variable language. To switch the language, it is thus sufficient to initialize this global variable with the name of the desired language member. In the same manner the implementation can evaluate the value actually stored in the variable. For example, you can implement your GUI application to switch between languages every time the following code is executed:
// Depending on the actual value of the variable 'language' determine the // new language to activate. In other words, toggle between the languages // French, German and Spanish. if ( language == French ) language = German; else if ( language == German ) language = Spanish; else language = French;
The alternation of this variable has an effect on the next access to a localized, multilingual constant or bitmap resource only. Expressions, which have been already evaluated in the past are not updated retrospectively. For example, the following code assigns a localized bitmap resource WelcomeLogo to the both Image views, ImageView1 and ImageView2. Just before the assignment (thus just before the bitmap resource is evaluated in an expression) the language is changed. This results in ImageView1 being initialized with the French version of the bitmap resource while ImageView2 will show the Spanish version:
// 'ImageView1' will show the French version of the 'WelcomeLogo' bitmap // resource. language = French; ImageView1.Bitmap = SomeUnit::WelcomeLogo; // and 'ImageView2' will show the Spanish version of the bitmap resource. language = Spanish; ImageView2.Bitmap = SomeUnit::WelcomeLogo;
React programmatically to language selection
So far, the mechanisms behind the language selection have no effect on already created and initialized GUI components. From this arises the consequence, that if you want an already existing GUI component to update its appearance after the language has been changed you have to create a new instance of the component and replace the old instance with it. This approach is legal but somewhat cumbersome.
Much easier it is to implement in your GUI component the re-constructor ReInit. ReInit is a special method, which is called automatically by Embedded Wizard every time the global variable language changes its value. The method is called individually for every instance of the GUI component. Accordingly, if you have created several instances of the GUI component, every instance can react and adapt its appearance automatically.
The typical implementation of the ReInit method re-evaluates all initialization expressions in the GUI component, which depend on the selected language. For example, if you have a GUI component containing a Text and an Image view initialized with localized constant and a bitmap resource, the method ReInit could be implemented as follows:
// Re-Initialize the 'Text' view with the actual version of the 'WelcomeText' // constant. TextView.String = SomeUnit::WelcomeText; // Re-Initialize the 'Image' view with the actual version of the 'WelcomeLogo' // bitmap resource. ImageView.Bitmap = SomeUnit::WelcomeLogo;
The following example project demonstrates this implementation. Here the GUI component contains several buttons to select the language. Activating a button modifies the global variable language. This, in turn, causes all implemented ReInit methods being invoked. Since the GUI component itself implements such method, the component can react and update its appearance:
Please note, the example presents eventually features available as of version 8.10
React automatically to language selection
With an alternative approach it is even sufficient to configure the attribute MultiLingual of the class implementing the GUI component. In this case Embedded Wizard will automatically take care of the appropriate re-initialization operations when the language has been changed. You don't need anymore to implement the above described method ReInit.
Technically seen, with the attribute MultiLingual you instruct Embedded Wizard to generate for every data member (property, variable or array), which is initialized with an expression involving localized constants or bitmap resources, code for the corresponding re-initialization operation. In principle, this works exactly as if you had formulated the initialization operations in the ReInit method.
The following example project demonstrates this approach. As in the above example, the GUI component contains several buttons to select the language. Activating a button modifies the global variable language. This time, however, the GUI component is configured with the MultiLingual attribute, so that the component reacts and updates its appearance automatically without any ReInit method being implemented:
Please note, the example presents eventually features available as of version 8.10
When using the attribute MultiLingual please take in account following aspects:
•If this attribute is true, Embedded Wizard generates additional code for every initialization expression, which involves at least one localized constant or bitmap resource.
•The effect of this attribute is limited to the corresponding class only. Classes derived from it don't inherit this attribute. Similarly, initialization expressions found in a base class are not affected.
•You have to set this attribute true for every class containing language dependent initialization expression.
Furthermore, by using the prefix operators %- (percent minus) at the beginning of an initialization expression you can explicitly exclude this expression from being re-evaluated even if it involves a localized constant or bitmap resource. Similarly, with the prefix operator %+ (percent plus) you can force the expression to be re-evaluated even if it evidently doesn't depend on any language specific operand.
For example, in the following screenshot you see the String property with its initialization expression suppressed from being re-evaluated. Thus this property will be not updated when the language is changed, even if the the expression contains language specific operands (e.g. the constant Application::WelcomeText):
In the following screenshot the property is initialized with the return value of a method GetText. Per default, such expressions are never re-evaluated when the language is changed. With the preceding %+ operator you force Embedded Wizard to do this. Now, when the language is switched, the method GetText is invoked and its return value is assigned to the property String:
Test the component with different languages
In the upper area of the Embedded Wizard window you see the Build toolbar. This toolbar contains various combo boxes to conveniently switch between profiles, languages and styles available in your project:
In particular the second combo box is convenient to test how your GUI component or application will appear with different languages. When you change the selection in the combo box the content shown actually in the Canvas area is updated immediately. Similarly, the actual combo box selection determines the initial condition when you start a new prototyping session. This means, the Prototyper window will appear with the currently selected language.