VC++ 10 MFC: What is the correct way to do localization - mfc

I am a .NET guy who is having to do some work on an MFC app. The app is a VS2008 MFC executable which I have converted to VS2010. The original developers did localisation by specifying the name of a .txt file with key value pairs in it on the applications command line. Installed shortcuts to the executable specify a different .txt file depending on which country the app is being installed in. This of course does not work if you just run the .exe directly. This seems like a weird way to do things to me.
I want to do this the propper MFC way, but I am having difficulty finding definitive answers on Google. My understanding is that the String Table in the .rc file should be used for this localisation? Is this the current best practice for MFC?
With respect to the String Table I have read that the practice is to create multiple string tables each for a different language. How do MFC applications choose which language to use? Is it based on the machines current language settings or can I control this (it may be that we want the language to be specified by the Wix .msi installer we are also building)?
I have also read that embedding all resource inside an MFC application has fallen out of favor and that now you should compile seperate resource .dlls? Is this is true ill investigate how to do it...
Finally, do I have to do something special to get MFC to support Unicode or is MFC Unicode by default?
Thanks

The idea is that all localizable items should be stored in resources. Standard UI objects such as menus and dialogs are automatically stored in there (resources) for you but items such as string literals (eg: error messages, messagebox prompts,...) should be pulled from source code to the string table. This short codeproject article of mine demonstrates how to easily pull strings from the string table in your code.
Note: You should have only one string table in your resource script (.rc).
From there on, you can translate your resources and create resource DLLs (aka satellite DLLs). The idea is that you keep a different copy of the .rc file(s) for each language. Each translation is compiled into a codeless DLL that acts as a container for the resources.
This other codeproject article of mine lets you easily load resource DLLs according to system settings or user preferences: The code looks among your resource DLLs which available language best matches user settings (based on user's UI language and regional settings). The code also lets you easily build a menu with all available languages. That way, your user can override the default choice.
DISCLAIMER: My ad follows. Feel free to skip :-)
Regarding the translation of resources, the management of translations and the creation of resource DLLs, you may want to check out appTranslator.
END OF AD :-)
Regarding Unicode, MFC ships with ANSI and Unicode versions of the code. It's up to you to choose if you want to build an ANSI or a Unicode app: Just make your pick in the first page of project settings. Of course, if you are startgin from scratch, you should definitely go Unicode. But if legacy reasons force you to stay ANSI/MBCS, don't worry to much: It won't prevent you from localizing your app.

Years ago when I had to work with multiple languages in MFC, we used separate resource DLLs. All you need do is make one call to switch which handle the resource functions would use and all was automatic from that point forward.
You need to do more than just change the strings. Dialogs in particular will have strings inside of them, and you may need to change the layout if those strings become too long after translation.

Related

Application using two (human) languages

I have a fully working code, written for Windows, built with Visual Studio.
What I want to do, is to add another language to that software. My idea is to have two flags (one English and one German) in the window corner, and to have the language change when user clicks on one of the flags.
What is the common, and best way to do this kind of thing?
So far, my idea is to create two files, and to store all the strings that software will use in those files. One file would hold all strings in English, and the other file will hold all strings in German.
Then, I believe that, when a click on a flag icon is detected, software would load all the strings in a list, or vector, or something similar, and then, I would just printout whichever string i need with vector.at(i).
Also, how would I save the currently used language on application exit, so the next time the app is started, that language is used?
The most commonly used way is more or less same as your idea. Also, to store currently used language on exit, you can create a configuration file writing the lang at application exit and read it on app start.

Good way to maintain Qt labels and text on UI

What is the best way/common practice for maintaining all string resources found on a UI in Qt, especially the textual input/text in combo boxes etc. (since these are the once that are frequently used in the code itself)?
I know that Android has this string resources thing such that resources only have to be modified at one position.
Does Qt have something like that too or do I have to initialize string resources in code instead of in the UI's XML itself...
AFAIK, there is no built-in mechanism for string resources in Qt. If you want to maintain strings at build time you can define them in one .h/.cpp file as global variables and reuse them in your code.
Otherwise you can use Qt's translator files (binary) and load them along with your application. If you need to change a string, you simply will need to edit the translation file (xml) and "recompile" it with lrelease utility without building the application again.
There is a mechanism to dynamically translate texts in application, but it works a bit different than Android string resources, but achieves the same goals.
Qt uses i18n system modelled after standard, well known unix gettext. It works in a very similar way to iOS NSLocalizedString, if that rings a bell.
http://doc.qt.io/qt-5/qobject.html#tr
This is worth reading too:
http://en.wikipedia.org/wiki/Gettext
http://doc.qt.io/qt-5/internationalization.html
Android approach is a bit unique and you should not expect it to be a "standard everywhere". It works, it's ok, but it's not a standard way of doing things on desktop.

How to write a shell extension in C++?

This seemed like a common question but after doing some searching, I wasn't really able to find my answers. There is an article on this here:
http://www.codeproject.com/KB/shell/shellextguide1.aspx
But it's for a very old version of Visual Studio. I'm using VS 2008, so the instructions and interfaces don't seem to match what I'm seeing.
I want to create a simple shell extension using C++ that creates a context menu for files with extension .GZ. When right clicking on these files, I should be able to click my context menu item and have a callback in code to do some sort of operation on that file.
Other context menu items would do things like spawn modless dialogs to accept user input before executing some action.
From what I've seen, ATL is used for this but I have never used ATL, so all of the object types and interfaces are very confusing to me. It wouldn't be so bad if I had a proper tutorial or documentation to read.
Can anyone help me out? Isn't there some sort of tutorial out there that isn't 10 years old?
I can't tell you exactly how to write a shell extension, but I will provide a number of tips. Writing a Shell Extension offers some significant advantages over the much simpler “registry-only” method:
With a Shell Extension, you can dynamically create a context menu item (or submenu) that is more relevant to the selected file(s). For example, if you are writing a Shell Extension for zip files, it is possible to create a submenu within the context menu that shows the entire contents of the zip.
You can handle multiple files simultaneously, which may be more beneficial not just for performance purposes but also so that you can work out what to do based on the selection as a whole rather than just for each file.
Some of the downfalls to Shell Extensions are:
Substantially increased complexity. Be prepared to spend a lot of effort on this to get it working. Have a home-espresso machine installed next to your computer and/or hire someone to make you coffee.
Substantially increased difficulty in debugging. Ditto about coffee.
It's difficult to write a Shell Extension because they can be very hard to debug.
Shell Extensions are loaded by the explorer.exe process, and without specific configuration of Explorer, you need to force-quit the explorer.exe process so that you can install a newer version of your Shell Extension. There is a way to get Explorer to unload DLLs that it is no longer using, but you should only do this on a development machine and not on a deployment target:
In RegEdit, browse to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
Add a new DWORD key called “AlwaysUnloadDLL” and set its value to 1.
Restart explorer.
This works most of the time, but there may still be times where you need to close Explorer because the Shell Extension was not unloaded.
Keep in mind that your Shell Extension may be loaded by other applications, for example, if you right-click on a file with an applications “open file” dialog, then your Shell Extension will be loaded into that application, and not Explorer.
If your Shell Extension causes a runtime error, quite often the result will simply be that your context menu item does not show, very rarely will you be told that your Shell Extension failed to load or that it caused a runtime error.
Configuration can be hard, even with an installation, registry data needs to be created in several places, and depending where you want your context menu to show, the places in the registry may differ between different versions of Windows.
What you'll need to do:
Visual Studio offers some shortcuts to creating Shell Extensions, but basically you'll need to create a COM DLL. A Shell Extension for context menu items must implement both the IContextMenu interface and the IShellExtInit interface.
In the IShellExtInit::Initialize() method, you can obtain the selected files from the IDataObject parameter. From memory, the data is in “Drag-n-Drop” format, so you need to get an HDROP handle from the IDataObject and query the files from there (this is from memory, it may actually be different than as I described here, so proceed with caution).
Once your DLL is ready to be “installed”, you must copy it somewhere, and then run regsvr32 to make sure it is registered.
Follow this guide to know where to put registry keys.
There may be issues with 64-bit Windows, if you build a 32-bit DLL it may not load in 64-bit Explorer… so keep this in mind if you are having trouble with 64-bit Windows.
Your DLL will actually have two GUIDs associated with it. I can't remember exactly how it works, but one GUID refers to the DLL itself and the other refers to the actual Shell Extension. Make sure you use the GUID of the actual Shell Extension when creating keys in the registry where a GUID is required.
All things considered… (tl;dr)
Weigh up the costs of whether a Shell Extension is worth it. If you want to create menu items dynamically based on the selected files, then a Shell Extension may be the only way. If you want to handle all files simultaneously then you'll probably need a Shell Extension as well.
An alternative to the context menu method, could be to have a drag-n-drop target on the user's desktop or something. Explore other ways that you could have the user submit your files to your application, because a Shell Extension is often far more effort than it is worth. I found this out the hard way and I think everyone else has too.

Embedding multiple, identically named resource (RC) files in a native DLL

For my application (an MMC snap-in) I need to create a single native DLL containing strings that are localized into different languages. In other words, if you were to inspect this DLL with Visual Studio, you would see multiple string tables, each associated with a different locale but containing the same string IDs.
The approach I would like to take is to have various subdirectories under my project directory such as "de", "en", "es", etc (i.e. one for each language). Inside each subdirectory would be a file called "Resources.rc" which would be the RC file containing the strings for that language. Having my resources in this structure would be ideal for the localisation team.
I have managed to create my various RC files and have added them to my Visual C++ project. They all appear correctly in Solution Explorer in Visual Studio (you basically see five instances of an entry called "Resource.rc", but each entry points to a different file).
The problem comes with building my project. It seems that only a single one of the RC files (the one that is specified first in the vcproj file) is compiled into a RES file and included into my DLL. Presumably this is because Visual Studio does not like the fact that the RC files all have the same name.
Is there any way to achieve what I want?
Thanks!
Yes. And No.
If you want multiple RC files you are going to have to leverage off the Operating systems support to have multiple resources in one file. In the resource editor, for each resource, you can set its locale AND the resource editor will allow you to have multiple resources with the same ID, as long as their locale is different.
So, your first step would be to edit each of the RC files to ensure that the resources in one are English/US, another contains French etc.
Next, get the main RC file to #include the others.
Lastly, and this is the problem, you need to rely on the Operating systems logic to load the correct resources. If you are happy to let the locale of the PC determine what UI language is used you have done enough.
If you want to provide a menu option allowing users to change languages: SetThreadLocale used to be an easy way to switch the Locale of loaded resources on the current thread. Since Windows 2000 some unfortunate overloaded usage of the API has caused MS to deprecate its usage in favor of requiring App Developers to always use FindResourceEx - which really doesn't help you if you want, for example, to load a string from a string table.
If you really want an easy way to have a user selectable UI language, then you need to place each of your .rc files into a seperate dll. and then LoadLibrary on the appropriate language resource dll.

Do you know of a good program for editing/translating resource (.rc) files?

I'm building a C++/MFC program in a multilingual environment. I have one main (national) language and three international languages. Every time I add a feature to the program I have to keep the international languages up-to-date with the national one. The resource editor in Visual Studio is not very helpful because I frequently end up leaving a string, dialog box, etc., untranslated.
I wonder if you guys know of a program that can edit resource (.rc) files and
Build a file that includes only the strings to be translated and their respective IDs and accepts the same (or similar) file in another language (this would be helpful since usually the translation is done by someone else), or
Handle the translations itself, allowing to view the same string in different languages at the same time.
In my experience, internationalization requires a little more than translating strings. Many strings when translated, require more space on a dialog. Because of this it's useful to be able to customize the dialogs for each language. Otherwise you have to create dialogs with extra space for the translated strings which then looks less than optimal when displayed in English.
Quite a while back I was using a translation tool for an MFC application but the company that produced the software stopped selling it. When I tried to find a reasonably priced replacement I did not find one.
Check out Lingobit Localizer. Expensive, but well worth it.
Here's a script I use to generate resource files for testing in different languages. It just parses a response from babelfish so clearly the translation will be about as high quality as that done by a drunken monkey, but it's useful for testing and such
for i in $trfile
do
key=`echo $i | sed 's/^\(.*\)=\(.*\)$/\1/g'`
value=`echo $i | sed 's/^\(.*\)=\(.*\)$/\2/g'`
url="http://babelfish.altavista.com/tr?doit=done&intl=1&tt=urltext&lp=$langs&btnTrTxt=Translate&trtext=$value"
wget -O foo.html -A "$agent" "$url" *&> /dev/null
tx=`grep "<td bgcolor=white class=s><div style=padding:10px;>" foo.html`
tx=`echo $tx | iconv -f latin1 -t utf-8 | sed 's/<td bgcolor=white class=s><div style=padding:10px;>\(.*\)<\/div><\/td>/\1/g'`
echo $key=$tx
done
rm foo.html
Check out appTranslator, its relatively cheap and works rather well. The guy developing it is really responsive to enhancement requests and bug report, so you get really good support.
You might take a look at Sisulizer http://www.sisulizer.com. Expensive though. We're evaluating it for use at my company to manage the headache of ongoing translation. I read on their About page that the company was founded by people who left Multilizer and other similar companies.
If there isn't one, it would be pretty easy to loop through all the strings in a resource a compare them to the international resources. You could probably do this with a simple grid.
In the end we have ended up building our own external tools to manage this. Our devs work in the english string table and every automated build sends our strings that have been added/changed and deleted to translation manager. He can also run a report at anytime from an old build to determine what is required for translation.
Check out RC-WinTrans. Its a commercial tool that my company uses. It basically imports our .RC files (or .resx files) into a database which we send to a different office for translation. The tool can then export a translated .RC file (or .resx file) for each language from the database. It even has a basic dialog box editor so the translator can adjust the size of various controls in the dialog box to be sure the translated text fits.
It also accepts a number of command line arguments and has a COM automation interface so you can integrate it into a build process more easily. It works quite well for us and we literally have thousands and thousands of strings and dialog boxes, etc.
(We currently have version 7 so what I've said might be a little bit different than their latest version 8.)
Also try AppTranslator: http://www.apptranslator.com/. It has a build-in resource editor so that translators can, for example, enlargen a text box when need bo. It has separate versions for developers and translators and much more.
We are using Multilizer (http://www.multilizer.com/) and although sometimes it's a bit tricky to use, at the end with a bit of patient it works pretty well.
We even have a translation web site where translators can download our projects and then upload the translations using Multilizer command-line features.
Managing localization and translations using .rc files and Visual Studio is not a good idea. It's much smarter (though counter-intuitive) to start localization through the exe. Read here why: http://www.apptranslator.com/misconceptions.html
I've written this recently, which integrates into VS:
https://github.com/ekkis/Powershell/blob/master/MT.ps1
largely because I was unsatisfied with the solutions out there. you'll need to get a client id from M$ (but they give you 2M words/month translation free - not bad)
ResxCrunch will be out soon, it will edit multiple resource files in multiple languages in one single table.