Multilanguage applications with MFC - workflow? - c++

We have an English-only Windows C++ application based on MFC. It is still being developed, with updates being periodically sent to customers.
We now have a reseller who wants the ability to translate our application into other languages as needed. I understand the standard way of translating MFC applications is by using language-specific resource DLLs.
However, this presents a problem with updating the application. When updating the functionality, we sometimes add/change/delete GUI elements and text messages. How do we "push" these changes to people who would translate the resource DLL without them having to translate the whole DLL every time? What is the best workflow for this? Are there any tools that make developing and MAINTAINING multilanguage applications easier?
Are there any frameworks that could help? The reseller would prefer to have a simple text file with all text strings in it, so dealing with a resource DLL is already an unwanted compromise for them.
Are there any good books/articles on managing multilanguage application development/maintenance?
I never worked in a multilanguage project, so I am not sure what to look for. Thanks for any suggestions :)

Surely, you would keep your content, no matter how it is eventually deployed, in a source code control system. So you can see the adds, changes, and deletes.
Only send the translater the changes that need to be translated. Then they send the translations back to you. Then you package the translation into a deployable object (e.g. DLL).

Are there any tools that make developing and MAINTAINING multilanguage
applications easier?
Our product utilizes a large contingent of worldwide resellers, so, the product is typically translated into many languages. We do not translate the resources directly. We have established a relationship with each reseller. Those that want to translate are given an English dll and a list of what has changed from release to release. Most use a tool called VisualLocalize to localize the resources. The tool produces a localized resource dll from our English dll. That dll is then returned to us, or, packaged separately. They use this type of tool because it allows them to not only localize strings, but, also resize dialog controls if needed. Control size can be an issue depending on the language translation. For example, the size of a text string may be large enough to hold an English word, but, too small for some translated languages. While it may seem “dangerous” allowing a translator to change control sizes, we’ve had enough requests to do this that it’s now standard practice. And, if memory serves me, this particular tool can import and export other files types which would potentially be of use in your particular case.

Related

Looking for a way to translate an application

I'm starting to design an application and I'd like it to support several languages from the beginning to avoid having to change big amounts of code later on to enable multiple languages.
I've written early a C application for which the messages were in a struct so I'd have several header files with the translated strings which would be integrated into the application itself, so to add a new language I'd have to recompile.
What I'd like is to be able to have a localization system that allows me to translate the application and add new languages easily without having to recompile the application. Ideally with a pretty straightforward way of translating and testing the translation (like editing a text file and seeing the results back in the app), without having to depend on 3rd party tools for the translation.
I'm thinking about writing my own system for it, maybe based on XML for the files containing the translations for example, but I wonder if anybody has experience with this and would recommend a lightweight library that provides that I'd like (even if the translation is not so direct as editing a text file). I emphasize lightweight because I think the application itself is not going to weight more than a couple of megabytes.
It's going to be a Windows application, if that's relevant for the matter. As of now I still haven't decided on the graphic toolkit I use but it's probably that I'll use the default Windows offers without using a cross platform one (like wxWidgets, Qt, GTK+, ...). But it's not set in stone, if one offered significant advantages it'd consider it.
I am not sure how lightweight is, but qt has a good support for internationalization.
Then you can use QtLinguist to simply translate your text.
Don't invent your own system. Internationalization (i18n) and localization (l10n) are almost always covered in some existing library.
If you develop for Windows, this link, Globalizing and Localizing .NET Framework Applications, might prove useful.

Look for ways to enable printing from my C++/MFC application

Since time immemorial I've been trying to avoid printing from my Windows-based applications due to the lack of native support for it. Whenever absolutely necessary I was resorting to dynamically making a simple HTML layout and then opening it in a web browser with a short Java Script in it to pop up a printing dialog for a user. Now I need to find something more substantial.
Let me explain. I have a project that deals with medical charts and it has to be able to print into those charts (at specific locations) as well as print on to a Letter/A4 size page in general. It also has to provide a preview of what is being printed in a paged-view environment.
In light of that I was wondering what is available from MFC/C++ environment (not C#) in regarding to printing?
PS. I was thinking to look into the RTF format but that seems like quite a daunting task, so I was also wondering, is there any libraries/already written code that can allow to compose/view/print RTFs? If not, what else is out there that can provide printing support like I explained above?
"lack of native support"? It's been covered by Petzold since forever, and it's integrated straight into GDI. Compared to UNIX, it's a complete breeze. And MFC makes it even easier.
Anyway, here's how you do print preview with MFC, and here's how you subsequently print. Lots of links from there, and it's all straightforward. Printers are just another Device Context on which you can draw.
I always found it very convenient to generate PDF files from my MFC/C++ application, There are many libraries out there which enable easy creation of PDF files, preview functionality and so on (also open source). I'm using this (also handles RTF):
PDF Library
There is no support like you call a framework method with some parameters and the framework prints a document or the content of a window for you. You need to manually draw everything on the printing device context. So as already said, you might find it more convenient to use a PDF generator, but of course that depends on your application requirements.
Please try www.oxetta.com , it's a free report builder solution that easily integrates into a C/C++ application.

Internationalization in MFC

It's finally (after years of postponing) the time to localize my app in a few other languages other than English.
The first challenge is to design the integration into my C++ / MFC application that has dozens of dialogs and countless strings. I came across two possible alternative implementations:
Compile and deploy localized resource files as DLLs
Extract and replace all strings with the localized version. For each
language there will be an XML (or simple text) file.
Personally I opt for the second alternative since it seems to me more flexible. The changes are many but not hard to make, and very importantly the XML files will be very easy to modify for the translators.
Any advise is greatly appreciated.
Regards,
Cosmin Unguru
http://www.batchphoto.com/
I did some long-living MFC projects with different languages.
I strongly recommend the first approach with resource-only DLLs.
The reasons:
(1) If the user does a XCOPY install, he always has the default language (English) in the main executables.
(2) If you don't translate everything (e.g. you're late with your release or forget some strings), the Windows resource functions if properly used return the resource in the default language automatically - you don't have to implement it on your own.
(3) My very person opinion: (a) Line breaks, tabs, whitespaces in XML files are a pain in your a**. (b) Merging XML files is even worse...
(4) Don't forget the encoding. It's okay in XML but your translators might use an unsuitable editor and damage the file.
And now for the main reason:
(5) You will have to rearrange many of your dialogs, because many strings are longer in e.g. French or German than in English. And making all statics, buttons, ... larger "just in case" looks crappy.
Another hint: Spend some bucks and buy one of the translation tools which import your projects / binaries and build up a translation database. This will be amortized after the first release.
Another hint (2): If possible make a release which doesn't contain any changes but only the multi-language feature. Also in future, if possible: Release your product in English. Then do the translation in one single step (per language) and release the other languages.
My good and friendly suggestion from somebody who worked a lot with localization:
Grab GNU Gettext,
Mark all your strings as _("English").
Extract all strings using gettext tool xgettext and compile dictionalries
Translate string using great tools like poedit.
Use gettext in your project and make your localization life simpler!
You can also use boost::locale for same purpose - it uses GNU Gettext dictionaries and approach but provides different and more powerful runtime and for windows developer it has very good addon - it supports wide strings that MFC requires to use for normal Unicode support.
Don't use resources and other "translation" tools that are total crap from linguistic point of view (and developer's point of view as well).
Further reading: http://cppcms.sourceforge.net/boost_locale/html/tutorial.html
Using a DLL resource library is a relatively straightforward operation, and allows you to manage not only strings, but other resources as well. And this is its main advantage, because i18n is not only about string translation.
However, depending on your needs, a text-based solution may be a better decision, because of its easier handling - resource scripts being more complex than xml files, especially for the average translator.
I would suggest creating your own abstraction layer, something like "LoadLocalizedString", etc.; in this way, you can start implementing it just with text files, and then change to something more complex when and if required in a transparent way - all the effort for making your software i18n aware would still be valid.
In our case we had diffrent dialogues per Language. The resource file was the same as the multiple laguages were implemented at development time. You could basically append on existing resource files the diferent languages. I hope it helps to find your way.
The DLL option is commonly used for this since the resource loading procedure (e.g. LoadLibrary) is already written - meaning you don't have to write any parsing/loading code. While XML is easier to edit, DLLs have a bit more security (users won't be able to easily edit them) and will allow the developer (meaning you) more time to work on application logic instead of writing a language loading system.
HMODULE hLangDLL = LoadLibrary("text_en.dll");
// more stuff
TCHAR mybuffer[1024] = {0};
LoadString(hLangDLL, IDS_MYSTRING, mybuffer, 1023);
If it is just the strings that are changing then I agree that XML is the way forward here for the exact reasons you outline. Easy for other people to edit, easy to change language at runtime, etc.
The only reason (in my eyes) that you'd choose option 1 is if things other than strings are being localized such as needing different icons.
If it's just text? I say go with the XML.

File preview component (C++/MFC)

Is anyone aware of a good, general purpose file preview component for MFC/C++ desktop applications?
Specifically, I'm looking for a component that I could embed in my application that would allow a broad range of file types (text files, multimedia, etc.) to be previewed without the need for original applications (such as MS Word, etc.) to be installed.
I could only find one, via Google:
http://www.file-viewer-sdk.com/
Unfortunately, these folks want $60k for unlimited redistribution, which is outside of our budget.
Anyone have any recommendations? If not a component, is anyone using another general-purpose strategy that works well for them?
You can write your own shell preview host once you know the interfaces.
You might want to check out Autovue, originally made by Cimmetry since acquired by Oracle
.
Our product makes limited use of their SDK to do some document conversions (Mostly RTF->PS) and that works well enough for us.

Unit testing MFC UI applications?

How do you unit test a large MFC UI application?
We have a few large MFC applications that have been in development for many years, we use some standard automated QA tools to run basic scripts to check fundamentals, file open etc. These are run by the QA group post the daily build.
But we would like to introduce procedures such that individual developers can build and run tests against dialogs, menus, and other visual elements of the application before submitting code to the daily build.
I have heard of such techniques as hidden test buttons on dialogs that only appear in debug builds, are there any standard toolkits for this.
Environment is C++/C/FORTRAN, MSVC 2005, Intel FORTRAN 9.1, Windows XP/Vista x86 & x64.
It depends on how the App is structured. If logic and GUI code is separated (MVC) then testing the logic is easy. Take a look at Michael Feathers "Humble Dialog Box" (PDF).
EDIT: If you think about it: You should very carefully refactor if the App is not structured that way. There is no other technique for testing the logic. Scripts which simulate clicks are just scratching the surface.
It is actually pretty easy:
Assume your control/window/whatever changes the contents of a listbox when the user clicks a button and you want to make sure the listbox contains the right stuff after the click.
Refactor so that there is a separate list with the items for the listbox to show. The items are stored in the list and are not extracted from whereever your data comes from. The code that makes the listbox list things knows only about the new list.
Then you create a new controller object which will contain the logic code. The method that handles the button click only calls mycontroller->ButtonWasClicked(). It does not know about the listbox or anythings else.
MyController::ButtonWasClicked() does whats need to be done for the intended logic, prepares the item list and tells the control to update. For that to work you need to decouple the controller and the control by creating a interface (pure virtual class) for the control. The controller knows only an object of that type, not the control.
Thats it. The controller contains the logic code and knows the control only via the interface. Now you can write regular unit test for MyController::ButtonWasClicked() by mocking the control. If you have no idea what I am talking about, read Michaels article. Twice. And again after that.
(Note to self: must learn not to blather that much)
Since you mentioned MFC, I assumed you have an application that would be hard to get under an automated test harness. You'll observe best benefits of unit testing frameworks when you build tests as you write the code.. But trying to add a new feature in a test-driven manner to an application which is not designed to be testable.. can be hard work and well frustrating.
Now what I am going to propose is definitely hard work.. but with some discipline and perseverance you'll see the benefit soon enough.
First you'll need some management backing for new fixes to take a bit longer. Make sure everyone understands why.
Next buy a copy of the WELC book. Read it cover to cover if you have the time OR if you're hard pressed, scan the index to find the symptom your app is exhibiting. This book contains a lot of good advice and is just what you need when trying to get existing code testable.
Then for every new fix/change, spend some time and understand the area you're going to work on. Write some tests in a xUnit variant of your choice (freely available) to exercise current behavior.
Make sure all tests pass. Write a new test which exercises needed behavior or the bug.
Write code to make this last test pass.
Refactor mercilessly within the area under tests to improve design.
Repeat for every new change that you have to make to the system from here on. No exceptions to this rule.
Now the promised land: Soon ever growing islands of well tested code will begin to surface. More and more code would fall under the automated test suite and changes will become progressively easier to make. And that is because slowly and surely the underlying design becomes more testable.
The easy way out was my previous answer. This is the difficult but right way out.
I realize this is a dated question, but for those of us who still work with MFC, the Microsoft C++ Unit Testing Framework in VS2012 works well.
The General Procedure:
Compile your MFC Project as a static library
Add a new Native Unit Test Project to your solution.
In the Test Project, add your MFC Project as a Reference.
In the Test Project's Configuration Properties, add the Include directories for your header files.
In the Linker, input options add your MFC.lib;nafxcwd.lib;libcmtd.lib;
Under 'Ignore Specific Default Libraries' add nafxcwd.lib;libcmtd.lib;
Under General add the location of your MFC exported lib file.
The https://stackoverflow.com/questions/1146338/error-lnk2005-new-and-delete-already-defined-in-libcmtd-libnew-obj has a good description of why you need the nafxcwd.lib and libcmtd.lib.
The other important thing to check for in legacy projects. In General Configuration Properties, make sure both projects are using the same 'Character Set'. If your MFC is using a Multi-Byte Character Set you'll need the MS Test to do so as well.
Though not perfect, the best I have found for this is AutoIt http://www.autoitscript.com/autoit3
"AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required!"
This works well when you have access to the source code of the application being driven, because you can use the resource ID number of the controls you want to drive. In this way you do not have to worry about simulated mouse clicks on particular pixels. Unfortunately, in a legacy application, you may well find that the resource ID are not unique, which may cause problems. However. it is very straightforward to change the IDs to be unique and rebuild.
The other issue is that you will encounter timing problems. I do not have a tried and true solution for these. Trial and error is what I have used, but this is clearly not scalable. The problem is that the AutoIT script must wait for the test application to respond to a command before the script issues the next command or check for the correct response. Sometimes it is not easy to find a convenient event to wait and watch for.
My feeling is that, in developing a new application, I would insist on a consistent way to signal "READY". This would be helpful to the human users as well as test scripts! This may be a challenge for a legacy application, but perhaps you can introduce it in problematical points and slowly spread it to the entire application as maintenance continues.
Although it cannot handle the UI side, I unit test MFC code using the Boost Test library. There is a Code Project article on getting started:
Designing Robust Objects with Boost
Well we have one of these humongous MFC Apps at the workplace. Its a gigantic pain to maintain or extend... its a huge ball of mud now but it rakes in the moolah.Anyways
We use Rational Robot for doing smoke tests and the like.
Another approach that has had some success is to create a small product-specific language and script tests that use VBScript and some Control handle spying magic. Turn common actions into commands.. e.g. OpenDatabase would be a command that in turn will inject the required script blocks to click on Main Menu > File > "Open...". You then create excel sheets which are a series of such commands. These commands can take parameters too. Something like a FIT Test.. but more work. Once you have most of the common commands identified and scripts ready. It's pick and assemble scripts (tagged by CommandIDs) to write new tests. A test-runner parses these Excel sheets, combines all the little script blocks into a test script and runs it.
OpenDatabase "C:\tests\MyDB"
OpenDialog "Add Model"
AddModel "M0001", "MyModel", 2.5, 100
PressOK
SaveDatabase
HTH
Actually we have been using Rational Team Test, then Robot, but in recent discussions with Rational we discovered they have no plans to support Native x64 applications focusing more on .NET, so we decided to switch Automated QA tools. This is great but licensing costs don't allow us to enable it for all developers.
All our applications support a COM API for scripting, which we regression test via VB, but this tests the API no the application as such.
Ideally I would be interested on how people integrate cppunit and similar unit testing frameworks into the application at a developer level.