Exception messages in English?
This issue can be partially worked around. The Framework exception code loads the error messages from its resources, based on the current thread locale. In the case of some exceptions, this happens at the time the Message property is accessed.
For those exceptions, you can obtain the full US English version of the message by briefly switching the thread locale to en-US while logging it (saving the original user locale beforehand and restoring it immediately afterwards).
Doing this on a separate thread is even better: this ensures there won't be any side effects. For example:
try
{
System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist");
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString()); //Will display localized message
ExceptionLogger el = new ExceptionLogger(ex);
System.Threading.Thread t = new System.Threading.Thread(el.DoLog);
t.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
t.Start();
}
Where the ExceptionLogger class looks something like:
class ExceptionLogger
{
Exception _ex;
public ExceptionLogger(Exception ex)
{
_ex = ex;
}
public void DoLog()
{
Console.WriteLine(_ex.ToString()); //Will display en-US message
}
}
However, as Joe correctly points out in a comment on an earlier revision of this reply, some messages are already (partially) loaded from the language resources at the time the exception is thrown.
This applies to the 'parameter cannot be null' part of the message generated when an ArgumentNullException("foo") exception is thrown, for example. In those cases, the message will still appear (partially) localized, even when using the above code.
Other than by using impractical hacks, such as running all your non-UI code on a thread with en-US locale to begin with, there doesn't seem to be much you can do about that: the .NET Framework exception code has no facilities for overriding the error message locale.
How to handle translation of exception message?
Most exceptions are there for technical purposes, unless your operations and maintenance crew are also located in different countries, those exceptions should simply have messages in the language of the people who write and maintain the application.
The .NET framework contains localized exception messages. For me as a developer, that's very annoying, since the exception messages in my local language (Dutch) don't mean as much as the original English exception messages. However, it seems reasonable for Microsoft to localize those framework exception messages, since their target audience can be located anywhere.
Some types of exceptions however, are explicitly thrown to be displayed to the user. These are your ValidationException
or BusinessLayerException
. Their clear contract is to be displayed to the user. Of course you should localize those exception messages, but instead of translating them, it's often much better and easier to pull the exception message from a localized resource when throwing the exception:
throw new ValidationException(Resources.InvalidUserName);
Force exceptions language in English
Finally a "sharp" solution could be the following:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#if DEBUG
// Add this; Change the Locales(En-US): Done.
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
#endif
Application.Run(new Form1());
}
However I'd like a solution without modifications in the project code.
From MSDN:
The CurrentUICulture property will be
set implicitly if an application does
specify a CurrentUICulture. If
CurrentUICulture is not set explicitly
in an application's code, it is set by
the GetUserDefaultUILanguage function
on Windows 2000 and Windows XP
Multilingual User Interface (MUI)
products where the end user can set
the default language. If the user's UI
language is not set, it will be set by
the system-installed language, which
is the language of the operating
system's resources.If an application is Web-based, the
CurrentUICulture can be set explicitly
in application code to the user's
browser accept language.
Visual Studio returns Dutch exceptions instead of English
Maybe try this out:
https://ifyoudo.net/post/2019/09/07/how-to-uninstall-a-net-language-pack-for-good
- Press Windows key + R
- Type: LPKSETUP
- Hit Enter
- Click Uninstall display languages
- Choose the language then click Next
why exception.message is not in english
The message in the exception is created when it's first thrown and that will be in whatever culture the code is compiled under. You cannot change this.
As this is WebClient
the only solution is to make sure you have the English language version of .NET installed.
How to completely avoid localized .NET exception messages
Remove any .NET language packs. According to this ("The .NET Framework 4.5 Language Pack contains translated error messages and other UI text for languages other than English. If you don't install a language pack, this text is displayed in English"), it should be enough.
Configure NLog to write exception messages in English
I found a solution with some help. See github.com/NLog/NLog/issues/172 thanks to Julian
It is possible to write a custom WrapperLayoutRenderer that switches the culture before the exception is logged.
namespace NLog.LayoutRenderers.Wrappers
{
[LayoutRenderer("InvariantCulture")]
[ThreadAgnostic]
public sealed class InvariantCultureLayoutRendererWrapper : WrapperLayoutRendererBase
{
protected override string Transform(string text)
{
return text;
}
protected override string RenderInner(LogEventInfo logEvent)
{
var currentCulture = Thread.CurrentThread.CurrentUICulture;
try
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
return base.RenderInner(logEvent);
}
finally
{
Thread.CurrentThread.CurrentUICulture = currentCulture;
}
}
}
}
It must be registered before any logger is created
ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("InvariantCulture", typeof(InvariantCultureLayoutRendererWrapper));
And can be used like that in the config
layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${InvariantCulture:${exception:format=tostring}}"
Related Topics
Resolving Instances with ASP.NET Core Di from Within Configureservices
How to Use Moq to Mock an Extension Method
Open Existing File, Append a Single Line
Can't View Designer When Coding a Form in C#
Stataskscheduler and Sta Thread Message Pumping
Httpwebrequest Using Basic Authentication
Setting Httpcontext.Current.Session in a Unit Test
How to Pass a Value from a Child Back to the Parent Form
Entity Framework Async Operation Takes Ten Times as Long to Complete
How to Decompile a .Net Exe into Readable C# Source Code
Using Regex to Balance Match Parenthesis
How to Bind a List to a Combobox
Design - Where Should Objects Be Registered When Using Windsor
How to Create a Dto in C# ASP.NET from a Fairly Complex JSON Response
Where Is the Application.Doevents() in Wpf