10

我正在尝试创建一个 WPF MarkupExtension 类,该类提供来自我的文本翻译类的翻译文本。翻译的东西很好用,但需要一个带有文本键的静态方法调用来返回翻译后的文本。像这样:

ImportLabel.Text = Translator.Translate("import files");
// will be "Dateien importieren" in de or "Import files" in en

它的特点是它接受一个计数值以提供更好的措辞。

ImportLabel.Text = Translator.Translate("import n files", FileCount);
// will be "Import 7 files" or "Import 1 file"

另一个例子:如果某件事还需要 4 分钟,那么它与只需要 1 分钟的词是不同的。如果文本键“minutes”被定义为任何数字的“Minuten”和计数为 1 的“Minute”,则以下方法调用将返回要使用的正确单词:

Translator.Translate("minutes", numberOfMinutes)
// will be "minute" if it's 1, and "minutes" for anything else

现在在 WPF 应用程序中,有很多 XAML 代码,其中包含大量文字文本。为了能够在不发疯的情况下翻译它们,我需要一个标记扩展,我可以传递我的文本键并在运行时返回翻译后的文本。这部分相当容易。创建一个继承自 MarkupExtension 的类,添加一个接受文本键作为参数的构造函数,将其存储在私有字段中,并让其 ProvideValue 方法返回存储键的翻译文本。

我真正的问题是:如何让我的标记扩展接受一个计数值,使其成为数据绑定并且当计数值更改时翻译文本会相应更新?

它应该像这样使用:

<TextBlock Text="{t:Translate 'import files', {Binding FileCount}}"/>

每当 FileCount 的绑定值更改时,TextBlock 必须接收新的文本值以反映更改并仍然提供良好的措辞。

我在那里找到了一个类似的解决方案:http: //blogs.microsoft.co.il/blogs/tomershamam/archive/2007/10/30/wpf-localization-on-the-fly-language-selection。 aspx但是,尽管我尝试遵循它,但我无法理解它的作用或它为什么会起作用。一切似乎都发生在 WPF 内部,提供的代码仅将其推向正确的方向,但尚不清楚如何。我无法适应它来做任何有用的事情。

我不确定让翻译语言在运行时更改是否有用。我想我需要另一个级别的绑定。为了保持较低的复杂性,我不会在基本版本工作之前尝试这样做。

目前没有我可以给你看的代码。它只是处于一种可怕的状态,它唯一做的就是抛出异常,或者不翻译任何东西。任何简单的例子都非常受欢迎(如果这种情况存在的话)。

4

1 回答 1

16

没关系,我终于发现了引用的代码是如何工作的,并且可以想出一个解决方案。这里只是对记录的简短解释。

<TextBlock Text="{t:Translate 'import files', {Binding FileCount}}"/>

这需要一个类 TranslateExtension,继承自 MarkupExtension,构造函数接受两个参数,一个 String 和一个 Binding。将这两个值都存储在实例中。然后类的 ProvideValue 方法使用它获得的绑定,向其中添加自定义转换器实例,并从 binding.ProvideValue 返回结果,这是一个 BindingExpression 实例 IIRC。

public class TranslateExtension : MarkupExtension
{
    public TranslateExtension(string key, Binding countBinding)
    {
        // Save arguments to properties
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        countBinding.Converter = new TranslateConverter(key);
        return countBinding.ProvideValue(serviceProvider);
    }
}

转换器,比如 TranslateConverter 类,有一个构造函数,它接受一个参数,一个字符串。这是我在上面的 TranslateExtension 中的关键论点。它会记住它以备后用。

每当 Count 值更改(它通过绑定)时,WPF 将重新请求其值。它似乎从绑定的源头,通过转换器,到达显示它的表面。通过使用转换器,我们根本不必担心绑定,因为转换器将绑定的当前值作为方法参数获取,并期望返回其他内容。计数值(int)输入,翻译文本(字符串)输出。这是我的代码。

因此,转换器的任务是使数字适应公式化的文本。它为此使用存储的文本密钥。所以发生的事情基本上是一种向后的数据流。与其将文本键作为主要信息并添加计数值,我们需要将计数值视为主要信息,只需将文本键用作辅助参数即可使其完整。这并不完全简单,但绑定需要成为主要触发器。由于密钥不会更改,因此可以将其永久存储在转换器的实例中。翻译文本的每一次出现都会得到它自己的转换器副本,每个都有一个单独的键编程。

这是转换器的样子:

class TranslateConverter : IValueConverter
{
    private string key;
    public TranslateConverter(string key)
    {
        this.key = key;
    }
    public object Convert(object value, ...)
    {
        return Translator.Translate(key, (int) value);
    }
}

这就是魔法。添加错误处理和更多功能以获得解决方案。

于 2013-02-12T18:41:57.780 回答