我有一个需要本地化的 Silverlight 4 OOB 应用程序。过去我使用的是传统的 resx 路线,但我被要求遵循现有 winforms 应用程序的架构。
所有字符串当前都存储在数据库中——我使用网络服务将它们拉下来并将它们写入本地 Effiproz 隔离存储数据库。在登录时,我加载了一个 Dictionary 对象,其中包含用户语言的语言字符串。这工作正常。
但是,我想自动化 UI 本地化(WinForms 应用程序就是这样做的):遍历页面上的所有控件并查找任何 Textblocks - 如果有文本属性,我将其替换为本地化版本。如果找不到文本,则我将字符串写入数据库以进行本地化。
这适用于简单的表单,但只要您有扩展器/滚动查看器和内容控件,VisualTree 解析器就不会返回控件的子级,因为它们不一定可见(请参阅下面的代码)。这是一个已知问题,阻碍了我的自动化尝试。
我的第一个问题是:有没有办法通过遍历复杂(非可视)元素并在字典中查找值来自动加载页面?
我的第二个问题是:如果不是,那么处理此问题的最佳方法是将字符串加载到应用程序资源字典中并更改我的所有页面以引用它,或者我应该考虑在服务器上生成 resx 文件(和按照正常方式将其与应用程序一起打包)或在客户端上(我有下载的字符串,我可以制作和加载 resx 文件吗?)
感谢您的任何指示。
这是我现有的代码,它不适用于折叠元素和复杂的内容控件:
public void Translate(DependencyObject dependencyObject)
{
//this uses the VisualTreeHelper which only shows controls that are actually visible (so if they are in a collapsed expander they will not be returned). You need to call it OnLoaded to make sure all controls have been added
foreach (var child in dependencyObject.GetAllChildren(true))
{
TranslateTextBlock(child);
}
}
private void TranslateTextBlock(DependencyObject child)
{
var textBlock = child as TextBlock;
if (textBlock == null) return;
var value = (string)child.GetValue(TextBlock.TextProperty);
if (!string.IsNullOrEmpty(value))
{
var newValue = default(string);
if (!_languageMappings.TryGetValue(value, out newValue))
{
//write the value back to the collection so it can be marked for translation
_languageMappings.Add(value, string.Empty);
newValue = "Not Translated";
}
child.SetValue(TextBlock.TextProperty, newValue);
}
}
然后我尝试了两种不同的方法:
1)将字符串存储在普通字典对象中 2)将字符串存储在普通字典对象中并将其作为资源添加到应用程序中,然后您可以将其引用为
TextBlock Text="{Binding Path=[Equipment], Source={StaticResource ResourceHandler}}"
App.GetApp.DictionaryStrings = new AmtDictionaryDAO().GetAmtDictionaryByLanguageID(App.GetApp.CurrentSession.DefaultLanguageId);
Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);