Hyderabad Jobs Book Website FREE PowerBuilder Training I Love Hyderabad Hyderabad Colleges
Home Business Emails Hyderabad Classifieds Contact Us
7 Wonders of Hyderabad Web Hosting Yellow Pages Our Network

 
Webpowerbuilder.hyderabad-colleges.com

Mastering PowerBuilder

HomePrevious Lesson: Developing Multilingual PowerBuilder Applications
Next Lesson: Course 3:: Session 27 :: Page 30

Introduction

The major issue in developing multilingual application is displaying text, messages and user interaction in the local language. We can write the program in any language like English, French etc.; The user doesn't care about the language of PowerScript we use to develop the application since it is not what he sees.

In any PowerBuilder application we display the text to the user in two places. The first one being on all visual objects such as Windows, Menus, Visual User Objects and DataWindows. The second one being messages using MessageBox() function.

One solution to this problem is making copies of all the visual objects and change the text into the target language and change all the messages in the MessageBox() into the target language. In this method we are not using any of PowerBuilder OO functionality and maintenance of these applications will be very difficult. For example if a company has ties in 10 different countries, we have 10 copies of the same application. Later if we need to do some changes in the system we need to change at 10 different places. So this method is not feasible.

Another solution is to create base language objects first, say in English and create objects for each target language by inheriting from these base objects. In the descendent objects replace the visual text with the target language alphabets. Later if you want to do any changes just do it in the base language object; Since all other objects are descendents of base language objects, the changes will be reflected in all the descendents.

However, the above solution is not a complete solution.

DataWindow object can't be inherited. We need to create copies of the base language DataWindow objects and do changes in all the copies. Any change needs to be applied in all the copies. There is no PowerBuilder solution for this problem.

This solution do not solve the MessageBox() problem. For example, if you are calling a MessageBox() some where in the middle of the ancestor event script with English language message, all the descent objects will display English version of the message. To make it to display in the local language, you need to override the ancestor event and write all the code in the descent. It is similar to the problem we faced in the first solution.

The solution to the MessageBox() problem is not to hard code the messages in the application. Instead, write down all the messages that you need to use in the application and assign a message number to each message. Now translate all those message texts into different languages. Store these messages either in a text file or in a database table and retrieve appropriate message depending on the local language and display it to the user. If you decide to store in a text file you may want to maintain different section for each language.

[English]
80001=Could not find any file
...
[French]
80001=Impossible de trouver des fichiers

If you decide to store in a database table you may want to make message number and the language id as the primary key.
ColumnName Data type
MessageID Number
LanguageID String
MessageText String

Once you do this, in the code you may want to create a function as shown below and call the function instead of MessageBox().

f_MessageBox( 10030, 80001, "French" )
// f_MessageBox() using INI file.
String ls_TitleText, ls_MessageText
ls_TitleText = ProfileString( "Messages.INI", &
	as_LanguageID, String( ai_TitleID ), "" )
ls_MessageText = ProfileString( "Messages.INI", &
	as_LanguageID, String( ai_MessageID ), "" )
MessageBox( ls_TitleText, ls_MessageText )
return 0

The above is a simple example. We are taking two message ids, one for the title and the other is for the message text. You may want to take parameters for buttons, default button and the icon to display on the left also. One more functionality in a typical application is the use of parameters in the messages. For example, you may want to create a message "File %1 not found" and want to replace '%1' with the parameter name at runtime. If you don't define parameterized messages, you will end up creating thousands of messages.

Instead of using text files you can as well store messages in the registry. However, it would kill the registry performance for all applications. The best solution would be to store it in a database and maintain a separate database connection for this purpose.

There is one more problem we need to solve, that is opening appropriate version of menu, window and user objects. For example, in the French version you need to open 'w_login_f', instead of 'w_login_e' window. There are two solutions to this problem as explained below.

The first solution is use CASE statement to check the language and open appropriate window. For example:

// gs_Language is a global variable.
CHOOSE CASE gs_Language
	CASE 'English'
		Open( w_login_English )
	CASE 'French'
		Open( w_login_French )
	CASE ELSE
                MessageBox( "Error", "Language Error" )
                HALT
END CHOOSE

Even though the code looks simple it is not advisable. Instead you can use a different format of Open() function. Open(), OpenSheet(), OpenWithParm() and OpenSheetWithParm() comes in different flavors. You can use a string that contains the window name as a parameter to these functions. This method would be more simple and efficient than the above one.

String ls_WindowName
Window lw_Window
ls_WindowName = "w_login_' + gs_Language
Open( lw_Window, ls_WindowName )

Refer to the above function syntax in the online help. You don't have to open the menus, because most of the time you assign the menu to the window. This can be done in the descendent windows at painting time. You can open the French version of the window and assign the French version of the menu in the window properties dialog box. However, you may be using menu variables to invoke as popup menus (right mouse button menus). A typical example would be:

// Declare an instance menu variable in the Window.
m_dw_popup_menu im_popup menu
// In the rButtonDown event of the DataWindow.
im_popup_menu.PopMenu( Parent.PointerX(), &
        Parent.PointerY() )

This code is fine if you are developing a single language version application. In international applications:

// Declare an instance menu variable in the Window.
Menu im_popup menu
// Create a menu instance
String ls_PopMenuName
ls_PopMenuName = 'm_dw_popup_menu' + gs_Language
im_popup_menu = CREATE USING ls_PopMenuName
// In the rButtonDown event of the DataWindow.
im_popup_menu.PopMenu( Parent.PointerX(), Parent.PointerY() )

Here we are making use of USING clause in the CREATE statement. This clause is available from PowerBuilder version 5.0 onwards.

Having discussed the problems involved in creating international PowerBuilder applications and the solutions wondering is there any tool that can automate any of the above processes? Of course. PowerBuilder has an 'Translation Assistant' utility. Till version 5.0 you need to purchase this product separately. With version 6.0 it is being bundled with Enterprise PowerBuilder edition. Now, let's see what exactly Translation Assistant utility is and how it works.

HomePrevious Lesson: Developing Multilingual PowerBuilder Applications
Next Lesson: Course 3:: Session 27 :: Page 30

Copyright © 1996 - 2006 HamaraShehar.com Pvt. Ltd. All Rights Reserved.
Domain Registration, Website Design, Website Hosting by HamaraShehar.com