|
A common question in the Smalltalk world is "how do I globalize my
application".
Windows 2000 introduced MUI which was extended into Windows XP and will
probably become a standard part of Windows Longhorn. So what is MUI?
"Windows Multi-language User Interface (MUI) includes resources for each
supported UI language separated from their binaries and provided in separate
language directories. The MUI allows users to set the user-interface language
according to their preferences, provided the required language was added to the
system. This allows large corporations to rollout the operating system
worldwide, while allowing their local users or groups to select the UI language.
It also allows users of different languages to share the same workstation: one
user might choose to see system menus, dialog boxes, and other text in Japanese,
while another user might choose to see the corresponding text in French."
Smalltalk MT has full support for MUI, and allows the user to develop an
application that can show resources in different languages or to change
languages on the fly.
There are several new APIs that help us.
Firstly, how do we determine the base language installed on the system (i.e.
is this English windows or Spanish Windows). Language identifiers are 16 bits
long and consist of 5 bits of sublanguage and 11 bits of primary language. To
retrieve this try in a workspace:
WINAPI GetSystemDefaultLangID&0xFFFF
we have to mask the result with 0xFFFF to only look at the 16 bits of the
LangID. To find the name of the system default language we can use:
result := String new: 30.
WINAPI GetLocaleInfo: LOCALE_SYSTEM_DEFAULT with: LOCALE_SLANGUAGE
with: result basicAddress with: 30.
In my case the SystemDefaultLangID is 1033 and the name of this is 'English
(United States)'.
Now how do we find all of the user interface languages that are supported on
this system? This involves a callback so we cannot accomplish it all in a
workspace. We need a class method containing the callback method. Why a class
method? Because we need to pass a known address to the callback API. It is not
that difficult. Create a class called Globalization. Add a class method in the
.EXPORT category. To do this right click on the * on the class side and choose
Add Category. Select the .EXPORT category and right click and select New Method.
The Win32 API says the callback EnumUILanguagesProc has two parameters so create
a method like this:
EnumUILanguagesProc: lpLocaleString param: lparam
"
Callback procedure for showing UI languages available
"
Processor outputDebugLine: 'LangID %s' _with: lpLocaleString.
^TRUE
Now we can call this callback procedure from our workspace.
WINAPI EnumUILanguages: (Globalization methodAddressAt: #EnumUILanguagesProc:param:)
with: 0 with: 0
This will write out to the debug monitor the LangIDs of all the UI languages
available on this system. These will be listed as hex strings which is not
terribly useful since all of the other APIs need a numeric LangID. Luckily it is
easy to convert these.
EnumUILanguagesProc: lpLocaleString param: lparam
"
Write out the UI languages available as strings
"
|result localStr locale|
localStr := String fromAddress: lpLocaleString.
locale := ('0x',localStr) asHexInteger.
result := String localNew: 100.
WINAPI GetLocaleInfo: locale with: LOCALE_SLANGUAGE
with: result basicAddress with: 100.
Processor outputDebugLine: 'Lang %s' _with: result.
^TRUE
This will list the language names available. For example this lists for me:
STIMAGE.EXE TID=1704! Lang English (United States)
STIMAGE.EXE TID=1704! Lang French (France)
STIMAGE.EXE TID=1704! Lang German (Germany)
STIMAGE.EXE TID=1704! Lang Italian (Italy)
STIMAGE.EXE TID=1704! Lang Spanish (International Sort)
STIMAGE.EXE TID=1704! Lang Russian
STIMAGE.EXE TID=1704! Lang Portuguese (Portugal)
This is because I have MUI installed with a several languages for testing.
|