views:

244

answers:

2

I have to build a GUI application on Windows Mobile, and would like it to be able user to choose the language she wants, or application to choose the language automatically. I consider using multiple dlls containing just required resources.

1) What is the preferred (default?) way to get the application choose the proper resource language automatically, without user intervention? Any samples?

2) What are my options to allow user / application control what language should it display?

3) If possible, how do I create a dll that would contain multiple language resources and then dynamically choose the language?

+3  A: 

For #1, you can use the GetSystemDefaultLangID function to get the language identifier for the machine.

For #2, you could list languages you support and when the user selects one, write the selection into a text file or registry (is there a registry on Windows Mobile?). On startup, use the function in #1 only if there is no selection in the file or registry.

For #3, the way we do it is to have one resource DLL per language, each of which contains the same resource IDs. Once you figure out the language, load the DLL for that language and the rest just works.

Graeme Perrow
+3  A: 

Re 1: The previous GetSystemDefuaultLangID suggestion is a good one.

Re 2: You can ask as a first step in your installation. Or you can package different installers for each language.

Re 3: In theory the DLL method mentioned above sounds great, however in practice it didn't work very well at all for me personally.

A better method is to surround all of the strings in your program with either: Localize or NoLocalize.

MessageBox(Localize("Hello"), Localize("Title"), MB_OK);
RegOpenKey(NoLocalize("\\SOFTWARE\\RegKey"), ...);

Localize is just a function that converts your english text to a the selected language. NoLocalize does nothing.

You want to surround your strings with these values though because you can build a couple of useful scripts in your scripting language of choice.

1) A script that searches for all the Localize(" prefixes and outputs a .ini file with english=otherlangauge name value pairs. If the output .ini file already contains a mapping you don't add it again. You never re-create the ini file completely, your script just adds the missing ones each time you run your script.

2) A script that searches all the strings and makes sure they are surrounded by either Localize(" or NoLocalize(". If not it tells you which strings you still need to localize.

The reason #2 is important is because you need to make sure all of your strings are actually consciously marked as needing localization or not. Otherwise it is absolutely impossible to make sure you have proper localization.

The reason for #1 instead of loading from a DLL is because it takes no work to maintain this solution and you can add new strings that need to be translated on the fly.

You ship the ini files that are output with your program. You also give these ini files to your translators so they can convert the english=otherlanguage pairs. When they send it back to you, you simply replace your checked in .ini file with the one given by your translator. Running your script as mentioned in #1 will re-add any missing translations if any were done while the translator was translating.

Brian R. Bondy
Out of curiosity, why do you say the DLL approach doesn't work very well? That's what our commercial software package has been doing for over 15 years. Each of our language DLLs contains over 6000 strings and we support something like 15 languages.
Graeme Perrow
How many wasted dev hours are spent adding a new string int ID, then associating that ID with an actual string? Also how do you ensure that ALL strings are translated.
Brian R. Bondy
I'm not saying it's not possible with a .dll file, I'm just saying there's a better way. That better way is outlined above.
Brian R. Bondy
We ensure that all strings are translated by simply not adding any strings (that a user might see) into the code, all strings must be loaded from the language DLL. In eleven years, I don't remember any non-localized strings making it into released software. (cont.)
Graeme Perrow
(cont.) Adding a new string ID is a ten-second process and we have perl scripts that make it all easy and ensure no duplicates and such. Having said all that, I do like your approach.
Graeme Perrow
I prefer the approach of being able to say that you can guarantee there no non localized strings that should be localized. It's the obscure error messages that don't show up often that you really have to worry about.
Brian R. Bondy
(cont.) If you have a very strict code review policy though and you can make sure that no programmer will ever add a string the wrong way then your way will work. But again you are taking your mindset away from what you are coding even just for 10 seconds to get a localized string.
Brian R. Bondy
1 more question, do you have duplicates in your RC files? Example 2 strings that say "Hello". In my method these will be matched up and no extra work for the translator.
Brian R. Bondy
We have routines for displaying and logging output (printf simply won't work in our case) and in production code, you can *only* call them with string IDs. We can't miss a case where we print a string directly because there's no way to do it.
Graeme Perrow
You're right about duplicates, but I'd be surprised if there were ten strings in the file that were duplicated. Just for curiosity, I'm going to write a script right now to search for duplicate strings.
Graeme Perrow
One advantage to our method - if there is a string that is displayed in many locations, we can change the English text of the string by modifying one file. You would have to search your entire code base and modify each entry, and then modify the entry (key) in each translated file as well.
Graeme Perrow
My mistake, a little over 100 duplicates out of 6400 messages. But most dups are there for good reason - one might be a menu item, the other a message for a log file. They currently happen to be the same text, but by modifying one file (and no code), we can change the text of one or both.
Graeme Perrow
(cont). Our translators have never complained. :-)
Graeme Perrow
Gentlemen! Why the bloodshed? Both answers are solid. They both seem to be working.
Ignas Limanauskas
No bloodshed, just discussing the relative merits. Personally, I'm quite enjoying this discussion. I even upvoted Brian's answer.
Graeme Perrow
ditto with Graeme Perrow's answer. :) Ya with my suggested method, if you change a string you'd just have a new entry. I.e. everything is immutable. You can have your script remove unused entries from your ini file if you want or keep them in case you use them again.
Brian R. Bondy
Note: This method is very similar to gettext, just maybe you have more control over the scripts.
Brian R. Bondy