更改文档查看器的默认本地化错误消息

本文关键字:默认 本地化 错误 消息 文档 | 更新日期: 2023-09-27 18:19:45

DocumentViewer WPF contorol 正在使用内部方法System.Windows.SR.Get(string)在搜索期间向用户显示消息。即使我pl-PL设置为CurrentCultureCurrentUICulture,这些也没有本地化。

我已经调查了一些,System.Windows.SR.Get(string)使用PresentationFramework程序集中的new ResourceManager("ExceptionStringTable", typeof (System.Windows.SR).Assembly),这反过来又加载了带有这些消息的 ExceptionStringTable.resources 文件。据我了解,这是整个框架的标准本地化技术。

我的问题是:如何使 WPF 显示我的自定义本地化消息?我尝试使用黑客反射,并能够访问SR类的内部ResourceManager。 我应该将其包装在我的自定义ResourceManager实现中,还是有更简单的方法?

更改文档查看器的默认本地化错误消息

我决定使用反射黑客。您必须在应用程序启动中使用此代码来交换内部 .NET 类SR中使用的ResourceDictionary

var assembly = typeof(DocumentViewer).Assembly;
var sr = assembly.GetType("System.Windows.SR");
var field = sr.GetField("_resourceManager", BindingFlags.NonPublic | BindingFlags.Static);

var resourceManager = (ResourceManager)field.GetValue(null);
var wrapper = new ResourceManagerWrapper(resourceManager);

wrapper.SetString("DocumentViewerSearchUpCompleteLabel", "test");
wrapper.SetString("DocumentViewerSearchDownCompleteLabel", "test");
wrapper.SetString("DocumentViewerSearchCompleteTitle", "test");
//And so on... you can find all those messages with dotPeek or similar tool in `DocumentViewer` implementation
field.SetValue(null, wrapper);

将资源查找转发到资源管理器的包装类非常简单:

public class ResourceManagerWrapper : ResourceManager
{
    private Dictionary<string, string> local_ = new Dictionary<string,string>();
    private ResourceManager manager_;
    public ResourceManagerWrapper(ResourceManager manager)
    {
        this.manager_ = manager;
    }
    public override string GetString(string name)
    {
        string value;
        if(local_.TryGetValue(name, out value))
        {
            return value;
        }
        else
        {
            return manager_.GetString(name);
        }
    }
    public void SetString(string key, string value)
    {
        local_[key] = value;
    }
}