我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
当前回答
英文异常消息
try
{
......
}
catch (Exception ex)
{
throw new UserFriendlyException(L("ExceptionmessagesinEnglish"));
}
然后进入本地化文件夹,把它放在projectName.xml中,然后添加
<text name="ExceptionmessagesinEnglish">Exception Message in English</text>
其他回答
这个问题可以部分解决。框架异常代码根据当前线程区域设置从其资源加载错误消息。在某些异常的情况下,这将在访问Message属性时发生。
对于这些例外情况,您可以通过在记录消息的同时将线程语言环境简单地切换为en-US来获得消息的完整的美国英语版本(预先保存原始用户语言环境,然后立即恢复它)。
在一个单独的线程上执行这个操作会更好:这样可以确保不会有任何副作用。例如:
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();
}
其中ExceptionLogger类看起来像这样:
class ExceptionLogger
{
Exception _ex;
public ExceptionLogger(Exception ex)
{
_ex = ex;
}
public void DoLog()
{
Console.WriteLine(_ex.ToString()); //Will display en-US message
}
}
然而,正如Joe在对该回复的早期修订的评论中正确指出的那样,在抛出异常时,一些消息已经(部分)从语言资源加载了。
例如,这适用于抛出ArgumentNullException("foo")异常时生成的消息中的'parameter cannot be null'部分。在这些情况下,即使在使用上述代码时,消息仍将出现(部分)本地化。
除了使用一些不切实际的技巧,比如在一个带有en-US语言环境的线程上运行所有的非ui代码之外,似乎没有什么可以做的:. net Framework异常代码没有覆盖错误消息语言环境的工具。
我知道这是一个古老的话题,但我认为我的解决方案可能与任何在网络搜索中偶然发现它的人非常相关:
在异常记录器中,您可以记录ex.GetType。ToString,它将保存异常类的名称。我希望类的名称应该是独立于语言的,因此总是用英语表示(例如。“system . filenotfoundexception”),尽管目前我还没有一个外语系统来测试这个想法。
如果您真的想要错误消息文本,您可以创建一个字典,其中包含所有可能的异常类名称及其等效消息,无论您喜欢哪种语言,但对于英语,我认为类名已经足够了。
基于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;
}
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)
}
我可以想象其中一种方法:
异常只会被你读取,也就是说,它们不是客户端特性,所以你可以使用硬连线的非本地化字符串,当你在土耳其模式下运行时不会改变。 每个错误都包含一个错误代码,例如0x00000001,这样你就可以很容易地在英文表中查找它。