|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn today's world, localization and translation of software has become an important feature since it dramatically helps in boosting sales. As far as Win32/MFC applications are concerned, managing different languages for your app requires the use of satellite DLLs. This article describes an easy-to-use method to support multiple languages in your C++/MFC applications. It shows how to add support for satellite DLLs (also known as resource DLLs) in your app by simply adding a few of lines of code. This includes:
It also explains how to create satellite/resource DLLs, although this is already covered in many other articles. By the way, I am a developer of appTranslator, a localization tool that (among other things) creates resource DLLs for you, freeing you from the hassle of managing Visual Studio projects for all these resource DLLs. BackgroundThere are quite a few articles on CodeProject that deal with localization and resource DLLs. (This one is a very good introduction to localization of MFC apps.) This article was published after I started writing mine! However I decided to go on and publish mine because I believe the topic of language selection menu was not covered in any of the articles on CodeProject. Also, other articles don't cover MFC7. A few words on resource DLLsIt is commonly accepted that the most flexible method to support multiple languages in your app is to use the so-called resource DLLs (also known as satellite DLLs). The idea is to create one DLL per language. The DLL contains a copy of all your application resources translated into one given language. Therefore, if your app's original version is English and you translate it to French, German and Japanese, you'll end up with three resource DLLs: The English resources stay in the .exe and there is one DLL for French, one for German and one for Japanese. Whenever you make a new translation of your app, you simply need to add one more DLL to your installer. At start-up, the application decides which language it should use (according to user preferences) and accordingly loads the resource DLL. Resource DLLs can be created using a dedicated Visual Studio project. Or they can be created by using the localization tools such as appTranslator. One nice thing about appTranslator is that the developer need not worry about the creation and maintenance of resource DLLs: Just hit the Build button and it creates them for you! By the way, packing all the languages into a single EXE is theoretically possible. But it just doesn't work :-( The reason is that most high level APIs that load resources (such as The step-by-step method to support resource DLLsHere are the steps required to add support for resource DLLs (and language menu) in your main application:
How to create the resource DLLsFirst of all, the The easiest way to create the DLL is to use the appTranslator, since the tool creates the dialog for you (you simply have to check 'Satellite DLL' in the properties). But of course, I won't assume that every one uses my tool ;-), so here's the manual way of doing it:
You can now compile the DLL. I suggest you to edit the output settings of the DLL project to copy the file side-by-side with your main EXE (i.e. in the same directory). You now have a resource DLL. Of course, it's not translated yet but that's the job of the translator. Start your app; open the Tools menu (or the menu where you created the Language item). The submenu should contain English and German. Follow the same procedure to create DLLs for the other translations you need. Once your DLL is available, the only thing you need to do is copy it side by side with your app (.exe) and it will automatically be taken into account for language selection. FAQDoes CLanguageSupport work with Unicode? And with ANSI?Yes! Does it support on-the-fly language switch?Yes! But this requires some work on your side that void CMainFrame::OnToolsLanguage(UINT nID) { // Loads the language selected by user theApp.m_LanguageSupport.OnSwitchLanguage(nID, true); // TODO: Update/reload your UI to reflect the language change } In addition, you must add the code that updates the current display of your app as (menus, views,...). This article tells you a little more about this part of the job but be aware there is going to be some custom work based on your app architecture and contents. The sample applicationIt consists of a simple MFC AppWizard-generated project in which I have followed the step-by-step method described above to add a Language submenu. I have also created two resource DLLs (French and German) whose translation is more or less complete. (The French one is pretty much completed. The German one is about half done.) In order to test the app, you should first compile the three projects (the EXE + the 2 DLLs). Start the project and see in which language the app starts. If you have either French or German Windows, the app will start in French or German. Otherwise it will start in English. The Language menu is located under Tools. The zip file contains the project files (and workspace/solution) for both VC6 and VS.NET. I have also included a copy of the executable files (the EXE and the resource DLLs - ANSI Release build). Credits: The sample app's About dialog uses Paul DiLascia's How does CLanguageSupport work?LoadLanguage(): What does that imply?The Identifying the language to load : If the user had earlier selected a language in the language menu, we load it (we know it by looking up in the registry). If he has never made a selection before, we look for a few possible languages that fit into the user's preferences. As soon as we find a resource DLL for our app that matches that language, we load it. If we don't find a match, we eventually fall back on the original version of the app: The language stored in the EXE itself. Loading the DLL is rather a simple task: We load the DLL using CreateMenu(): Creation of the languages submenuThis function looks for the DLLs available in the directory of the EXE whose name matches the pattern MyAppXXX.dll. It then looks for its language in the DLL's version info resource. (It doesn't identify it by the three letter DLL because... there's no simple way to find the language given the acronym. Brute enumeration of the languages supported by Windows would be the only solution, which according to me is a horrible method). It then builds the menu according to the list of languages found. Note: This detection is not 100% perfect: The fact that a language (actually the charset) is supported by Windows doesn't necessarily mean that the fonts for that language are installed. In such a case, the menu may display garbage. Now, this is probably not a major issue since your app wouldn't display well in that language anyway. OnLanguageSwitch(): Take user's language choice into accountThis one is the simplest function. All it does is store the user's choice into the registry (HKCU\MyCompany\MyApp\Settings : Language = (DWORD) LangId). It also asks the user to restart the app to load the new language. If caller wants to switch languages on the fly, the DLL for the new language is loaded right away. Why a custom class? Doesn't MFC handle all that?MFC7.1 (Visual Studio 2003) does some part of that work: It does the same kind of work at start-up (in It's a pity because there are many scenarios where the user could make a better choice than what MFC does for him. Imagine for example an app available in English and French. On an Italian or Spaniard's computer, MFC would choose English. But many Italians and Spaniards understand French better than English. It would be a shame to prevent them from selecting a language they understand better. That is why it's important to have a language selection menu in addition to automated language detection. Things are even worse: You'd think we could re-use the MFC code and simply tweak it to take user selection into account. Bad luck: Part of this code is in ConclusionThanks to Creating the DLLs (and managing the corresponding projects) is not difficult at all but it's certainly a boring task. If you are serious about localization, I recommend you to give a look into the tools such as appTranslator that not only helps you manage the translation of your apps but also creates the resource DLLs for you. One last note: I hope you don't mind the ads ;-) | ||||||||||||||||||||