Exception Messages


Exceptions present a number of strategy questions in the internationalization story. We start by considering how exceptions gather their messages and then consider what questions you will have to answer.

In the following statement, the text is clearly hard-coded to use English:

 throw new ArgumentException(     "Value does not fall within the expected range."); 


You may or may not want to localize this text. The simplest way to localize this text is to let the .NET Framework do the work for you:

 throw new ArgumentException(); 


In the absence of a supplied message, the .NET Framework gets a message using its own ResourceManager. Consequently, the actual message retrieved is dependent upon CultureInfo.CurrentUICulture and the .NET Framework Language Packs installed on the machine. So if the CurrentUICulture is "de-DE" (German (Germany)) and the German .NET Framework Language Pack is installed, the exception message will be "Der Wert liegt außerhalb des erwarteten Bereichs." Tables 8.5 and 8.6 show some examples of default exception messages for English and German, respectively.

Table 8.5. Examples of Default English Exception Messages

Exception Constructor

Message

ArgumentException()

Value does not fall within the expected range.

ArgumentException(null)

Exception of type System.ArgumentException was thrown.

FileNotFoundException()

Unable to find the specified file.

FileNotFoundException(null)

File or assembly name (null), or one of its dependencies, was not found.

IOException()

I/O error occurred.

IOException(null)

Exception of type System.IO.IOException was thrown.


Table 8.6. Examples of Default German Exception Messages

Exception Constructor

Message

ArgumentException()

Der Wert liegt außerhalb des erwarteten Bereichs.

ArgumentException(null)

Eine Ausnahme vom Typ System.ArgumentException wurde ausgelöst.

FileNotFoundException()

Die angegebene Datei konnte nicht gefunden werden.

FileNotFoundException(null)

Datei- oder Assemblyname '(null)' oder eine Abhänigkeit davon wurde nicht gefunden.

IOException()

E/A-Fehler aufgetreten.

IOException(null)

Eine Ausnahme vom Typ System.IO.IOException wurde ausgelöst.


One problem that this raises is that the localization of exception messages is clearly limited to the availability of .NET Framework Language Packs for the current culture. There is no Arabic .NET Framework 1.1 Language Pack (but there is for the .NET Framework 2.0), for example, so .NET Framework 1.1 exception messages on Arabic Windows are in English because the fallback culture for the .NET Framework is English.

This brings us to the questions you will have to answer. The first is, what language do you want your exception messages to be in? You might feel that if your application is running on a German version of Windows, its exception messages should also be German. This may or may not be true. You might equally feel that if your developers are English, all exception messages should be in English because the exception messages are aimed at the developers, not at the users. The answer is more likely to be a combination of both approaches, where the language of the message is determined by the exception type. Consider an ArgumentException. This is almost certainly a programmer error and represents a fault in the application for which a software fix is required. There is no value in relaying such a message to users because they won't understand it and they won't be able to do anything about it. There is a good argument, therefore, that this message should be in the developer's language (possibly English). Now consider a FileNotFoundException. The English text of this exception is "Unable to find the specified file." This is something that the user might well understand and might also be able to rectify. There is a good argument, therefore, that this message should be in the user's language.

If you choose to make a distinction between exceptions that are destined for developers in one language and exceptions that are destined for users in another language, you need a way of implementing this distinction. To create exceptions with localized messages, you either use the default exception constructor or pass null for the message parameter:

 throw new FileNotFoundException(); throw new FileNotFoundException(null); 


The .NET Framework and the installed Language Pack provide the localized exception message. To create exceptions with English messages, you can still use the default constructor or pass null for the message parameter, but you set the Current UICulture before creating the exception:

 Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US"); throw new IOException(); throw new IOException(null); 


Good practice dictates that you would restore the CurrentUICulture to its former state after the exception was created, so this begs for a class to tidy up this process:

 throw new ExceptionFactory.CreateException(typeof(IOException)); 


The ExceptionFactory class (next) performs this task. Its overloaded Create-Exception method accepts an exception type to create an exception from and, optionally, an array of parameters to pass to the exception constructor. The CurrentUICulture is temporarily changed to the static ExceptionCulture property (which, by default, is "en-US") and restored to its former state after the exception has been created. Here is the complete ExceptionFactory class:

 public class ExceptionFactory {     private static CultureInfo exceptionCulture;     static ExceptionFactory()     {         exceptionCulture = new CultureInfo("en-US");     }     public static CultureInfo ExceptionCulture     {         get {return exceptionCulture;}         set {exceptionCulture = value;}     }     protected static CultureInfo oldCultureInfo;     protected static void SetExceptionCulture()     {         oldCultureInfo = null;         if (Thread.CurrentThread.CurrentUICulture.Name !=             exceptionCulture.Name)         {             // change the culture to the exception culture             oldCultureInfo = Thread.CurrentThread.CurrentUICulture;             Thread.CurrentThread.CurrentUICulture = exceptionCulture;         }     }     protected static void RestoreCulture()     {         if (oldCultureInfo != null)         {             Thread.CurrentThread.CurrentUICulture = oldCultureInfo;             oldCultureInfo = null;         }     }     public static Exception CreateException(Type exceptionType)     {         object exception;         SetExceptionCulture();         try         {             exception = Activator.CreateInstance(exceptionType);             if (! (exception is Exception))                 // do not localize this                 throw new ArgumentException(                     "exceptionType is not an Exception Type");         }         finally         {             RestoreCulture();         }         return (Exception) exception;     }     public static Exception CreateException(         Type exceptionType, object[] args)     {         object exception;         SetExceptionCulture();         try         {             exception =                 Activator.CreateInstance(exceptionType, args);             if (! (exception is Exception))                 // do not localize this                 throw new ArgumentException(                     "exceptionType is not an Exception Type");         }         finally         {             RestoreCulture();         }         return (Exception) exception;     } } 


Whereas this class solves this problem, its scope is limited to exceptions that your code creates. Exceptions that are thrown by the .NET Framework or by third-party code (including COM objects, for example) are outside of your control, and .NET exception messages will be localized regardless of the intended recipient of the message. For this reason, your exception-reporting facility should be sure to record the exception class name in addition to the exception message, to allow your developers to know what exception has occurred without them having to learn another language.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

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