If there is a chance that your program will be distributed in non-English-speaking markets, you should consider internationalizing your error messages. Internationalization is the process of developing a program whose design and code doesn't make assumptions based on a single language or locale and whose source code simplifies the creation of different language editions. Localization is the process of actually adapting and testing a program for a specific market. If you plan to sell in other markets, you need to internationalize your code now, but you can delay the localization to other markets until later.
The last version of the DisplayGenericObjectError function, shown above, is a good example of how not to write internationalized error messages. How many problems can you find? Although the function does use the right data types, function calls, and macros to support Unicode, it has two critical flaws:
Here is an internationalized version of DisplayGenericObjectError written using MFC:
void DisplayGenericObjectError (const CString &action, const CString &object) { CString buffer, objectBuf, actionBuf; if (!object.IsEmpty()) objectBuf = object; else objectBuf.LoadString(IDS_UNKNOWN_OBJECT); if (!action.IsEmpty()) actionBuf = action; else actionBuf.LoadString(IDS_UNKNOWN_ACTION); buffer.FormatMessage(IDS_GENERIC_OBJECT_ERROR, actionBuf, objectBuf); AfxMessageBox(buffer); } |
In this case, if IDS_GENERIC_OBJECT_ERROR is "Can't %1 on %2.", the results will be the same as before. By using FormatMessage, you can now change the order of the text without changing the code. For example, you could set IDS_GENERIC_OBJECT_ERROR to "Can't use %2 to %1." and, if the parameters are empty strings, the error message will be
TIP
For internationalization, always put the error message strings in string resources, and construct strings at run time using FormatMessage.
Using MFC significantly helps writing internationalized code. Not only is the CString::FormatMessage function much easier to use than the ::FormatMessage API function, but CString::LoadString and other resource functions automatically handle resource-only DLLs so that you can localize a program just by changing its resource DLL. Furthermore, using CStrings eliminates having to select fixed sized buffers that are large enough to handle translated text.
The most important observation to make about this example is that internationalizing your error messages doesn't take much additional effort if you do it from the beginning of your project. Do it at the end, and it is a real pain in the neck.