Consider Internationalization

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:

  • All strings that can be seen by the user should be in resources, not in the source code.
  • Error messages created by combining strings should not use functions such as CString::Format or _stprintf. The problem is that the order of the components in the string can change in different locales. For example, in French, many adjectives follow the nouns they modify. In German, verbs are often at the end of a sentence. To solve this problem, use the FormatMessage function instead, which allows you to change the order of the string parameters by changing the format-control string.

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.



Developing User Interfaces for Microsoft Windows
Developing User Interfaces for Microsoft Windows
ISBN: 0735605866
EAN: 2147483647
Year: 2005
Pages: 334

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net