Author: lavieroboies

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.…

Misconception: It’s a better idea to translate a .rc file than a .exe file

March 1, 2006 By lavieroboies

Developers often think that using the executable file (EXE) as the source file for the translations is not a good idea. They would rather have their source file translated: The resource script (in other words the .rc files). That’s what we first thought, too. But even though it’s counter-intuitive, IT IS WRONG !

This article points out a few of reasons why using the EXE as the source file makes developers’ life much easier. It also covers several major misconceptions about EXE-based translations.

With EXE-based translations, I can’t modify my code anymore…

WRONG!!! appTranslator will happily and instantly build updated translations of your program whenever you modify your code. It needs not touch your code. It simply makes a copy of your new exe, extract its resources and replace them by their translated version. There is really no difference in this regard between using a .exe file or a .rc file. Oh yes… there is one: It’s much easier and faster to build a translated exe by updating its resources than to link the program again, using an alternate, translated rc file.

What if I modify the resources of my application ?

No problem ! Again, there is really no difference in this regard between using a .exe file or a .rc file. appTranslator compares its version of your resources and the resources in the .exe. Using advanced algorithms, it finds the new and modified item (even in dialog layouts!) and updates the translations accordingly. And you can fine-tune some advanced aspects (such as dialog controls layout) as easily

EXE-based translations help isolate development and translation

Translating the .rc files means the developers must handle the compilation of the translated .rc files. Therefore, there must be one project file for each translation of each translated module. Do you want developers to spend time managing translation-related projects ? Or be bothered by bloated projects list ?

EXE-based translations do not require any intrusion in the regular development process: Translated EXEs are built directly from appTranslator. No more intrusions in the developer’s work !

By using the .exe file as the source for translations, we basically use the endpoint of the developer’s work (the exe file is the developer’s output, right?) as our starting point for the translation work. In other words, we add a new link to the development process rather than hook unrelated work items in the middle of the developer’s work.

Allow translators to test their work

Very often, translations are performed by support staff of your foreign distributors. These people may not be the best translators but they know your app and they know your business, hence they probably have a better grasp about the terminology used in your apps than most professional translators.
Let them test their translations. If they are translating .exe files, the localization tool can generate translated exe on-demand.
On the other hand, if they are translating .rc files, they can’t compile the EXEs in order to test them. The developer must be involved and do the job for them, which means that developers must spend time doing a job that could otherwise be done by a computer. Not very cost-effective !

Make sure everything is translated

There can be lots of rc files buried in toolkits and libraries, including one another. Keeping track of all of them is often painful. By using the exe file instead of the rc files as a source, you ensure that all the resources are available to the translators.

One might argue that on the other hand, the resources from a library used in different executables are duplicated and need to be translated several times. There is an easy workaround: Create a dummy exe whose sole resources are the toolkit or library’s resources and import. Use this dummy EXE to maintain translations of the toolkit’s resources. Import these translations into each real exe that uses the toolkit.

I don’t want to be locked into appTranslator

Developers think that having a translated version of their .rc file is important to help them keep in control: If they have translated .rc files, they can start using another localization tool at any time.
Having translated EXEs give them the exact same …

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 !…

Store

October 26, 2005 By lavieroboies

Pricing

ProductEURUSDSecured Ordering
appTranslator Professional Edition
Share*it Ref: #300026107
479.00629.00 Buy
appTranslator Professional Edition + 1 year Priority Support and Updates
Share*it Ref: #300026459
589.00769.00 Buy
appTranslator Standard Edition
Share*it Ref: #300025922
349.00459.00 Buy
appTranslator Standard Edition + 1 year Priority Support and Updates
Share*it Ref: #300026489
429.00559.00 Buy

Professional and Standard Editions are compared here.

Support Contracts

Products purchased with a support contract are entitled to unlimited priority e-mail support and product updates (including major updates) during one year.

Hint: We’ve got lots of ideas to make appTranslator even better. Way enough ideas to release significant updates in a foreseeable future!

Products purchased without a support contract include 30 days of free e-mail support.

The Support and Updates contract can be renewed every year (in case of interruption, renewal are counted as of the expiration date of the previous contract. The contract can be renewed only for the amount of licenses initially purchased).

Support Contract RenewalEURUSDSecured Ordering
Professional Edition: 1 year Priority Support and Updates
Share*it Ref: #300084613
110.00139.00 Buy
Standard Edition: 1 year Priority Support and Updates
Share*it Ref: #300084612
79.0099.00 Buy

Ordering Process

Our Secured Ordering process is performed by Share*it, worldwide leader in secured payments.

Fax Orders

Please click the Buy button in front of the item you want to purchase. A fax order form and instructions are available in the bottom of the first page of the online ordering process.

Phone Orders

Credit card orders by telephone are handled by Share*it. Please make sure to have the your product’s Share*it reference ready (See price list above).

US customers please call: (800) 406-4966 9am-5:30pm Eastern Time.

Other customers please call: +49-221-3108830 (Germany)

IMPORTANT: These phone numbers belong to Share*it, an independent registration service, and cannot be used to obtain technical support or order status ! Please contact us for any inquiries.…

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.…