我有一个需要本地化的Silverlight 4 OOB应用程序。在过去,我使用了传统的resx路线,但我被要求遵循现有winforms应用程序的架构。
所有字符串当前都存储在数据库中 - 我使用Web服务将它们拉下来并将它们写入本地Effiproz Isolated Storage数据库。在登录时,我加载一个Dictionary对象,其中包含用户语言的语言字符串。这很好。
但是,我想自动化UI本地化(WinForms应用就像这样): 遍历页面上的所有控件并查找任何Textblocks - 如果有文本属性,我将其替换为本地化版本。如果找不到文本,那么我将字符串写入数据库进行本地化。
这在简单表单上工作正常但是只要你有扩展器/滚动查看器和内容控件,那么VisualTree解析器就不会返回控件的子节点,因为它们不一定是可见的(参见下面的代码)。 This is a known issue并阻止我的自动化尝试。
我的第一个问题是:是否有办法通过循环复杂(非可视)元素并在字典中查找值来自动加载页面?
我的第二个问题是:如果没有,那么处理此问题的最佳方法是将字符串加载到应用程序资源字典中并更改我的所有页面以引用它,或者我应该查看生成resx文件,在服务器上(并按照正常情况用app打包)或在客户端上(我有下载的字符串,我可以制作和加载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);
答案 0 :(得分:1)
好的,所以没有人回答这个问题,我想出了一个解决方案。
基本上,您似乎可以使用
将语言字典加载到全局资源中Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);
<TextBlock Text="{Binding [Equipment], Source={StaticResource ResourceHandler}}" />
然后像普通的StaticResource一样访问它。我们要求将所有缺少的字符串记录到数据库中进行转换 - 因此我选择使用一个调用Localize扩展方法的Converter(因此可以在后面的代码中的任何字符串上完成),然后查找字典中的字符串(不是资源),如果它不存在,可以对它做一些事情(将其写入本地数据库)。
Text="{Binding Source='Logged on User', Converter={StaticResource LocalizationConverter}}"/>
这种方法适合我们。