我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
当前回答
Windows需要安装你想要使用的UI语言。如果没有,它没有办法神奇地知道翻译后的信息是什么。
在安装了pt-PT的en-US windows 7 ultimate中,以下代码:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT");
string msg1 = new DirectoryNotFoundException().Message;
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
string msg2 = new FileNotFoundException().Message;
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
string msg3 = new FileNotFoundException().Message;
生成pt-PT, en-US和en-US格式的消息。由于没有安装法语文化文件,它默认为windows默认(已安装?)语言。
其他回答
Setting Thread.CurrentThread.CurrentUICulture will be used to localize the exceptions. If you need two kinds of exceptions (one for the user, one for you) you can use the following function to translate the exception-message. It's searching in the .NET-Libraries resources for the original text to get the resource-key and then return the translated value. But there's one weakness I didn't find a good solution yet: Messages, that contains {0} in resources will not be found. If anyone has a good solution I would be grateful.
public static string TranslateExceptionMessage(Exception ex, CultureInfo targetCulture)
{
try
{
Assembly assembly = ex.GetType().Assembly;
ResourceManager resourceManager = new ResourceManager(assembly.GetName().Name, assembly);
ResourceSet originalResources = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, createIfNotExists: true, tryParents: true);
ResourceSet targetResources = resourceManager.GetResourceSet(targetCulture, createIfNotExists: true, tryParents: true);
foreach (DictionaryEntry originalResource in originalResources)
if (originalResource.Value.ToString().Equals(ex.Message.ToString(), StringComparison.Ordinal))
return targetResources.GetString(originalResource.Key.ToString(), ignoreCase: false); // success
}
catch { }
return ex.Message; // failed (error or cause it's not smart enough to find texts with '{0}'-patterns)
}
这招对我很管用:
//Exception Class Extensions
public static class ExceptionExtensions
{
public static string EnMessage(this Exception ex)
{
CultureInfo oldCI = Thread.CurrentThread.CurrentCulture;
string englishExceptionMessage = ex.Message;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
try
{
var objectType = Type.GetType(ex.GetType().FullName);
var instantiatedObject = Activator.CreateInstance(objectType);
throw (Exception)instantiatedObject;
}
catch (Exception e)
{
englishExceptionMessage = e.Message;
}
Thread.CurrentThread.CurrentCulture = oldCI;
Thread.CurrentThread.CurrentUICulture = oldCI;
return englishExceptionMessage;
}
}
然后你可以通过调用新方法ex.EnMessage()来使用它;
基于Undercover1989答案,但考虑参数以及当消息由多个资源字符串组成时(如参数异常)。
public static string TranslateExceptionMessage(Exception exception, CultureInfo targetCulture)
{
Assembly a = exception.GetType().Assembly;
ResourceManager rm = new ResourceManager(a.GetName().Name, a);
ResourceSet rsOriginal = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true);
ResourceSet rsTranslated = rm.GetResourceSet(targetCulture, true, true);
var result = exception.Message;
foreach (DictionaryEntry item in rsOriginal)
{
if (!(item.Value is string message))
continue;
string translated = rsTranslated.GetString(item.Key.ToString(), false);
if (!message.Contains("{"))
{
result = result.Replace(message, translated);
}
else
{
var pattern = $"{Regex.Escape(message)}";
pattern = Regex.Replace(pattern, @"\\{([0-9]+)\}", "(?<group$1>.*)");
var regex = new Regex(pattern);
var replacePattern = translated;
replacePattern = Regex.Replace(replacePattern, @"{([0-9]+)}", @"${group$1}");
replacePattern = replacePattern.Replace("\\$", "$");
result = regex.Replace(result, replacePattern);
}
}
return result;
}
我可以想象其中一种方法:
异常只会被你读取,也就是说,它们不是客户端特性,所以你可以使用硬连线的非本地化字符串,当你在土耳其模式下运行时不会改变。 每个错误都包含一个错误代码,例如0x00000001,这样你就可以很容易地在英文表中查找它。
出于日志记录的目的,某些应用程序可能需要获取英文异常消息(除了在通常客户机的UICulture中显示它之外)。
为此,使用以下代码
changes the current UICulture recreates the thrown Exception object using "GetType()" & "Activator.CreateInstance(t)" displays the new Exception object's Message in the new UICuture and then finally changes the current UICulture back to earlier UICulture. try { int[] a = { 3, 6 }; Console.WriteLine(a[3]); //Throws index out of bounds exception System.IO.StreamReader sr = new System.IO.StreamReader(@"c:\does-not-exist"); // throws file not found exception throw new System.IO.IOException(); } catch (Exception ex) { Console.WriteLine(ex.Message); Type t = ex.GetType(); CultureInfo CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); object o = Activator.CreateInstance(t); System.Threading.Thread.CurrentThread.CurrentUICulture = CurrentUICulture; // Changing the UICulture back to earlier culture Console.WriteLine(((Exception)o).Message.ToString()); Console.ReadLine(); }