Category: Blogs

Single Worldwide Binary: What’s the Problem?

December 14, 2021 By lavieroboies

It is commonly accepted that the best strategy to provide support multiple languages with one single EXE is to use resource DLLs (a.k.a. Satellite DLLs). By the way, generating such resource DLLs with appTranslator is as easy as filling one checkbox!
But why do we have to bother playing with a whole set of DLLs? After all, several translations of one given resource (such as a string or a menu) can easily be stored in a single EXE. And if you call SetThreadLocale() to select your language, voilà, your resources will be loaded in the expected language. Not!

SetThreadLocale() is not the solution

Once upon a time, there was Windows NT4 (and even, 3.51, 3.5,…). In these times, the single worldwide binary was a realistic option… as long as you didn’t have to target Win9x, under which SetThreadLocale() was a no-no!Then came Windows 2000 and its vastly improved support for internationalization. Paradoxically, the single worldwide binary was no longer an option. Because one could no longer rely on SetThreadLocale() to globally select the language for resources, as the docs say:

Windows 2000/XP: Do not use SetThreadLocale to select a UI language. To select the proper resource that is defined with a LANGUAGE statement, use FindResourceEx.

Docs say ‘don’t touch!‘ but they don’t say why. And if you try to look further, you won’t find much info. As always, Michel Kaplan’s blog is a good place to look up, even if it’s to get confirmation that there’s not much to find out.

Well, there are a few lines somewhere: This article briefly explains that when MUI was first introduced back in Windows 2000, the Microsofties had to modify the way resources are loaded (If you know why, please let me know). Actually, they modified the default language selection algorithm used to load resources :

The catch here is that if the thread locale is the same as the currently selected user locale, system’s resource loader will by default use the language ID 0 (neutral). If the desired resource is defined as a neutral language, then this value will be returned. Otherwise, all of the language resources will be enumerated (in language ID order) and the first matching resource ID – regardless of its language – will be returned.

In other words, Windows will not load resources the way you expect if you happen to ask for the same language as the user preference (user default locale)! Yikes! You don’t believe me? Fair enough, me neither! 🙂 Let’s make a test.

The Sample Program

  • The program contains a String Table with a string in German, French (Belgium) and English.
  • The program selects German as its default UI language : SetThreadLocale(German)
  • It then loads a string from the String Table(displayed in the message box title).

(Download source).

You expect the loaded string to be “German string“. Play with you user locale and you’ll see that the docs are unfortunately right.

Here is what I get with User Locale = French (Belgium): The german string is correctly loaded.

Then I modify my user locale and select German:

When I re-run the program, I still expect “German String” but I get something else 🙁

What language does it pick then?

If you look carefully at the screenshots above, you might notice something weird: The docs (quoted above) say that in case of ThreadLocale==UserLocale, the language picked should be the first one in ID order, which for my program is… German! (German=0x407, French-Belgium =0x80C and English=0x409).So in this case, German should have been picked, as a side effect. But it was not: English was picked. How come?

I made further tests and it appears that when UserLocale==ThreadLocale, Windows tries to load the resources in its own UI language (even if it’s different from User/Thread Locale). Anyway, this irrelevant since we just demonstrated that SetThreadLocale() cannot be trust to achieve the Single Worldwide Binary dream.

BTW, why would Find Resource Ex help?

Remember the remark in the docs? Use resource DLLs or use FindResourceEx().

The reason FindResourceEx() would help is simply because it takes an explicit langiuage ID, as opposed to the most usual resource-loading APIs such as …

Choose your Windows UI language

October 15, 2006 By lavieroboies

Ever wanted to know how Windows look like in German, Italian, Japanese, Vietnamese, Arabic, Thai, Greek,… ?

Did you know that you can install the Windows GUI in all these languages (and more) in addition to your default language ?
It’s called MUI (for Multi-Language User Interface). You simply run the MUI setup on your existing Windows 2000 or Windows XP box and choose which language(s) you want to add.

When the installation is completed, your Regional and Languages Options control panel applet has a new combobox where you can choose your Windows UI language (Logoff required to take change into effect).

The nice thing is that it’s a user setting. Just create a few users and assign each one a different language. You can now toggle between different UI languages using FUS (Fast User Switching) !

The MUI CDs are available to MSDN subscribers (Operating Systems+ subscriptions). And of course, they are available as downloads from the MSDN subscribers download area.…

MS Sans Serif: Not a nice international player

January 26, 2006 By lavieroboies

I wanted to translate my app to Polish and I noticed that some of my dialog items were cropped. How come ?

This appTranslator user developed his app in English using Visual C++ 6.0. This version of VC++ uses MS Sans Serif as the default dialog font. The problem is that this font supports the Western European code page only.When one adds an Eastern European language such as Polish, appTranslator realizes that the font will not display correctly in Polish hence replaces the default dialog font by Tahoma.Now Tahoma is a _little_ bit wider than MS Sans Serif, resulting in long source text items being cropped, especially if the controls were really just wide enough to display the text.

Is this a problem ?

Well, not really since as soon as you translate an item, appTranslator resizes it (if it’s not wide enough). The problem kind of auto-fixes itself.

Can one avoid this problem ?

Yes. If you remain concerned, there is something else you can do: Microsoft created a enhanced version of MS Sans Serif : Microsoft Sans Serif (sic!). This font is a Unicode font containing a lot more characters and supporting many more charsets, including Eastern European languages, Arabic, Hebrew, Greek,…

As far as Western European characters are concerned, they are exactly the same in both fonts.
Therefore, you can simply replace occurences of MS Sans Serif by Microsoft Sans Serif in your resource scripts. Or you can set this font as the default font for the intended language in appTranslator.

Of course, using ‘MS Shell Dlg’ is an even better idea.…

Get Number Format () was 25 years late

December 28, 2005 By lavieroboies

Don’t get me wrong: As a self-appointed i18n specialist, I consider locale-aware APIs (such as GetDateFormat()GetNumberFormat() et al) blessings to make your apps world-ready by respecting your users’ culture. It’s not a question of politeness or education. It’s just plain necessary if you want users to understand what your program display.

What d’you mean 9/23 ? There ain’t no 23 months !?

Let’s take dates for example: Take it the way you want but if you tell me 8/9, I’ll understand Sep 8th. Don’t expect me to think Aug 9th because I don’t even know that somebody, somewhere, might read it Aug 9th ! And if you tell me 9/23, I’ll tell you you read too much sci-fi about time machines. That’s why using GetDateFormat() (or any of its higher level wrappers) is so important.

Regarding numbers, GetNumberFormat() and his sister GetCurrencyFormat() helps you make sure ten thousands is written 10.000,00 for most Europeans and 10,000.00 for Americans (and whatever format is used for each other culture).

Computers were babies, and babies don’t study languages

Yes, we Europeans use a comma as a fractional separator. That’s what we learn in elementary school. That’s how we write numbers. We don’t even think of doing it another way !

Errrr… Really ? Well, there is a catch : When the first “pocket” calculators appeared in the late 60’s or early 70’s, and when the grocer around the corner started to use a machine to print price tags, instead of writing them down, we started to set our minds: Printed numbers use a dot to indicate the fractions (we’re not used to commas as thousands separator though) because the calculator was manufactered by an American company and so was the labelling machine used by the grocer… And these machines didn’t have GetNumberFormat(), unfortunately !

The interesting point is that we learned that printed numbers use a dot. But we didn’t change the way we write. And we inconsciously make a difference between handwritten numbers and printed numbers ! Since machines didn’t speak our language, we learned theirs. But it doesn’t mean we forgot ours.

By the time the kid grew up and studied languages, it was too late

Then came GetNumberFormat() and Excel starts using commas for fractions. WTF ! Nobody prints numbers that way ! It’s just plain ununderstable. Pleaaase, get me rid of this comma and replace it by a good old decimal point… Thank you.

OK. Everybody happy again. But still, officially, Belgians use decimal commas. So when our IRS published its web-based tax declaration system 2 or 3 years ago, they followed the official rules and uses. I remember I filled the whole lot of fields in the huge form and clicked Next.

Please fill in with numbers. Beg your pardon ?? It took me 10 minutes and several tries to realize the problem was with my decimal points. The form wanted decimal commas ! Plain unusable !It didn’t last: The next year, one could use decimal points…

The problem is that programs display so many numbers : We, the devs, just can’t use GetNumberFormat() each time. And since people are used to it (people don’t even think of printed numbers looking like written numbers !). If at least the CRT and other major libraries used it (After all, these libraries do use GetDateFormat()…), we would get correct display of numbers for free and the format would become ubiquitous. But for some reason, the CRT doesn’t use locale-awre APIs to format numbers (I guess there are reasons. I’ll ask my good friendMichael).

The net effect is that using GetNumberFormat() can become counter-effective, according to the context. And it’s pretty hard to know if the context is good or bad 🙁

“And Excel ?”, you ask

Well, It looks like the Office team didn’t want to break the whole work done by their colleagues at the i18n team : If I type the dot in the digits pad, Excel writes a comma (!) and considers it a decimal separator. Pretty weird at first, but you know what: We now get used to reading printed numbers with commas… as long as it’s in Excel !…

Why is Windows UI for folder selection so lame ?

August 23, 2005 By lavieroboies

It doesn’t happen often but everytime I have to code it, it always leaves me with the same bad feeling.

Today, I added a feature in a small app I’m developing for a client. The UI of this feature involves a Browse button to let Joe User tell the app in which directory some files can be found.

Is there only one person out of the hundreds of millions of Windows users who likes this dialog ? I seriously doubt. Is there only one who finds it usable ? I’m sure not.
This Browse for Folder dialog is plain unusable. Just go type a path in the edit box: You’d expect the tree selection to follow. No ! You at least expect what you just typed to be saved as your choice when you click OK. Not even !
Wait, there’s more : Setting up this dialog programmatically requires that the programmer holds a PhD in Computer Science.

Besides this, we have a nice, usable, powerful and handy standard file dialog. And that’s where it becomes more frustrating: That one won’t allow you to let user select a directory. If you absolutely want to use it, you’ll have to use dirty tricks such as forcing users to select a file in that dialog, even though you don’t care about that file (hence why would user do ?). Remember old Windows drivers installation, when it prompted you for a location for the driver by forcing you to select a file that it won’t choose anyway ?

So, pleaaaase, Microsoft, tell me why among the ton of flags in the good ol’ open file dialog, there’s not one that allows to select a directory !

Rhaaa ! End of rant. I guess I’ve been sitting in front of that computer for way too long… 🙂…

Painless Localization of Your Visual C++ Applications

October 1, 2001 By lavieroboies

appTranslator is a powerful yet easy-to-use localization solution for your Visual C++ and MFC applications.

Easy and Intuitive User Interface

Get started in minutes thanks to appTranslator wizards and user-friendly localization-oriented resource editors that guide you through the translation process. (Screenshots)

Immediate Tracking of Untranslated Items

Do never again wonder which items are not translated yet. Thanks to the Items to be Translated view mode, you can concentrate on the remaining work items.

Immediate Tracking of New and Modified Items

Did you make changes to your app ? Did you add a resource, modify a bunch of dialogs or menu items ? No problem ! appTranslator takes your changes into account whenever you build the translated files. And thanks to the ‘Update Source’ function, appTranslator detects and incorporates all additions and modifications of your resources (including in the layout of dialogs). Better yet, appTranslator immediately shows you which items were added or modified.

Help Developers and Translators Collaboration

appTranslator lets you easily deploy copies of the project to the different translators and merge translations back into the main project. Developers need not freeze their app’s resources while translators are busy. appTranslator lets team members concentrate on their own work, freeing them from tedious housekeeping tasks.…