When asked about developing multiple language applications, I have always made the wise crack: “Once I sell every English speaking person a copy of my software, then I will worry about translating it to another language”
Well now that I am consulting on projects in Europe and other spots around the globe, I am seeing how the other half lives. In many parts of the world there is more than one primary language or neighboring countries that speak different languages. Developers in these areas are forced to deal with multiple language applications on a daily basis, and now that I am assisting them, so do I.
What we will be covering in this weeks webinar and article, is a Preferred Language option at log in time. Sometimes the “language” of the operating system is not the preferred language. We will look at:
- Detecting the OS Language
- Providing a combo box of Supported Languages as part of Log in
- Storing and restoring the preferred language using the Default Manager Class
- How this all works with the Multiple Language Captions, etc. within the WX environmen
- Setting up the IDE to use Google Translate
First a quick primer on some of the multiple language features of WD in case you have not worked with multiple languages before.
On the language tab of the project description, you configure your project with the languages you will be supporting. This interface also allows you to configure formatting options for numbers, dates, time, etc.
As you can see in this project we are supporting 6 languages. You may be wondering why we have both English and American listed. There are several words with alternate spellings such as Color vs Colour, Center vs Centre, etc.
Once you have the languages configured for your project the descriptions for statics, captions, etc. allow you to enter what will be displayed for each language.
For instance notice the different caption values for this entry control
Another multiple language feature of the IDE is the translation of strings. Notice the odd, icon behind the strings in this line of code
Clicking on that Icon gives you a translation screen similar to that for captions. BTW, if you seem to have an issue with this screen not seeming to want to save your changes when using Google Translate, you might want to contact support for an update. I reported a bug with this interface and they provided me with a DLL that fixed the issue.
There is a bit of a trick to getting this icon initially. You will notice that this line of code doesn’t initially have the icon.
In order to get to the translation screen initially highlight the string, including the quotes, right click and chose Translate from the popup menu. It is very important to make sure you select the quotes as well other wise you will end of with a translated string inside an extra pair of quotes that will not behave correctly.
Now that you have seen how the multiple language captions and strings get into your project, its time to move on to the purpose of this article. When you application runs it will use the language selected as the default in the project description. You can address this issue as part of setup so that the default language is setup when the application is installed. We decide instead to allow the user of the application to select a preferred language at run time.
So lets go through the code and see what we did.
As always with WX there are many ways to do things, I prefer to do my global variables inside a class, and I also hard coded structured arrays for lookups that don’t necessarily need to be configurable by the end user. I have refer to these as “Fixed Lookups”. A list of supported languages definitely a instance of a list that the end user doesn’t need to edit.
So I have a SystemsVariables Class
Inside this class I defined a structure that is then used for several “Fixed Lookups”
Then I declare an array of that structure to use for the Language List
In the constructor method, I declare an instance of the structure. Remember a structure is a type of variable to use it you have to declare an instance of it.
Then I added the supported languages to the array inside the constructor method as well. Notice there are constants for the languages.
If you have not worked with classes you may have a question about the constructor method. When an instance of a class is created the constructor method is automatically ran, so in this case since this will be fixed data that doesn’t change, we can put the code to setup the array in the constructor method and it will run when we declare an instance of the class shortly.
In the project code of the project an instance of the SystemVariables class is declared.
As mentioned this runs the constructor method and populates the array. I like using this method of declaring global variables because in my code they are referenced as GLO.VariableName which makes it obvious that they are global variables.
We use the Default Manager class to store the selected language in the registry. If you are not familiar with my open source Default Manager class you can read more about it here.
Let’s break this statement apart and see what it is doing. GetDefault is a method of the Default Manager Class, that retrieve a value. In this instance it is retrieving a value from the windows registry named “Language” and if a entry is not found than a value of nationEnglish will be returned. Once the value is return the Nation function of WX is called to set the display language of the application. So if this is the first time the application has been ran the language will be set to English, otherwise it will be set to what ever language was stored in the registry.
So now lets move on to the login screen and take a look at the code there. First the combo control is set to use the Array we declare in the SystemVariables class.
A global variable is declare for the procedure. We will see its use shortly.
Then in the end of initialization code, the value of the combo box is set. We see here another form of the Nation statement. In this form it returns the nation set for the application. Since the code we just looked at in the Project code has set the Nation based on the Registry, this line of code will set the combo box to that language.
When selecting a row from the combo box, the Nation statement is again used to set the language to the selected language. If you review the content tab of the combo box again, you will see that it displays the Language name, but returns the value, which when we declared the array we used the constants for the languages. The procedure global “LanguageChanged” is set to true and I promise we will see what it is used for shortly.
In the code of the login button, once the login has been validated we have the below code. As promised I will now explain the use of LanguageChanged. If the user has selected a different language we want to store that value in the registry, so that it will be the default the next time the application runs. This is using the SaveDefault method of the Default Manager class. But the next line of code may be something you are not familiar with. Use opens a Window while close all the existing open windows. Win_Main is the main window containing the ribbon bar for the application, and is already open prior to the login screen being called. Changing the nation does not refresh the captions of windows already opened, so the menu would be in the wrong language if the user changed the language. By issuing the Use statement the Main Menu is reopened and this time displays the correct captions..
That is all there is to allowing the user to select the language at run time, and storing their preference so they don’t need to select it every time.
Now for a little bonus material. After seeing the description screen for an edit control with six configured languages, you may have been thinking:
- Man, Uncle Pete sure speaks an impressive number of languages. – That ain’t likely!
- Man, Uncle Pete must have a stack of translations languages on his desk. – That sounds like way more work than I want to do!
- Man, Uncle Pete must keep Google Translate open on one of those 4 monitors all the time and be the master of copy and paste! Sadly this use to be the case until I found out just how easy it is to configure the WX IDE to use Google Translate directly.
Hopefully I can save you the pain of not knowing just how easy it is to add Google translate to the IDE. First from the Home tab, select Options, and then General options of WinDev from the popup menu.
Then on the Translation tab of that window, select Google Translation as the Translation Engine and put your Google Translate API key in the provided entry field.
In order to get a Google Translate API key you need to have a Google account and go to Googles API Console Note: this is a billable service, but before you get to worried I don’t think my monthly bill has been over 10 cents US yet!
Once you have setup the IDE to use Google Translate, you will notice a translate icon beside the caption for each language in the controls description.
Clicking on this icon will bring up the below popup menu.
In this instance I clicked on the icon beside French. And notice the menu gives me the choice to use any of the other languages as the basis for the translation. When you select an option, it uses Google translate to translate the provide text and fill in the selected caption. So in order to do the translations for the application I simply type in the English caption, and then for each of the other languages I click on the Icon and have it use the English value for translation.
This interface is fantastic, but I feel it could be even better. First there is an issue with multiple line captions. If you try to translate a string that has a carriage return in it, the translated string will contain a /r/n instead of a carriage return. Unfortunately this displays “/r/n” instead of a carriage return. This looks like RTF to me. I am not sure if this is a Google or a pcSoft issue. I have reported it as a bug to pcSoft and have not heard back from them yet, but I am hoping that they can do something on their side to replace the /r/n with a carriage return instead.
I have also made the suggestion to add a new option to the popup menu to translate all other languages based on the current language. So instead of my current method of typing in the English caption, and then clicking and selecting the menu option for each of the other 5 languages, I could instead, Enter the English Caption, then click the icon beside it and select translate all the other languages and it would translate the other 5 based on the English caption, With 1 button click instead of 5. Man, we WX developers sure are spoiled ain’t we!
Note: pcSoft does sell some add on products for translations. I do not have any first hand experience with these products, and will therefore reserve my comments concerning them. Hopefully someone that has worked with them will step forward with some information on them.
Be sure to go over to wxLive.us and watch the Uncle Pete’s corner webinar that is the companion to this article.
Uncle Pete’s Corner is webinar series on all things WX, to watch the recorded version of this webinar, many other WX related webinars or to watch future ones live go to wxLive.us