动态本地化 WPF 应用程序与资源文件

17

我试图使我的wpf应用程序本地化,我按照这个CodeProject教程进行了操作。

我创建了我的本地化资源文件(例如Resource.resx、Resource.en-US.resx),并在XAML中将它们绑定到标签元素上。

<Label Foreground="{StaticResource ApplicationForgroundColor}" FontSize="21"
           Content="{x:Static strings:Resources.title}"/> 

在一个本地化服务中,我在某些变更事件上设置了 CultureInfo

class LocalizationService
{
    public static void SetLanguage(string locale)
    {
        if (string.IsNullOrEmpty(locale)) locale = "en-US";
        System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(locale);
    }
}

这个解决方案能够编译并展示出正确的资源值,但由于静态绑定的原因,我无法在运行时更改区域设置。 当我将内容绑定更改为 DynamicResource 如下所示,就不会显示任何资源值。

Content="{DynamicResource strings:Resources.title}"

我如何将文本值绑定到本地化资源文件,并在运行时动态更改它?

1个回答

25

这里还有一种方法是由 Code Infinity 提出的,也使用了一个包装器来动态绑定资源文件。在这种方法中,INotifyPropertyChanged 事件会通知您的 UI 元素当地区发生变化时新的绑定资源文件。

您可以开始实现 BindingExtenstion:

public class LocalizationExtension : Binding
{
    public LocalizationExtension(string name) : base("[" + name + "]")
    {
        this.Mode = BindingMode.OneWay;
        this.Source = TranslationSource.Instance;
    }
}

然后您需要实现ResourceManagerCultureInfo之间的连接,后者作为单例实现以启用同步访问。它定义了绑定元素的源,并在本地化更改时触发INotifyPropertyChanged事件:

public class TranslationSource : INotifyPropertyChanged
{
    private static readonly TranslationSource instance = new TranslationSource();

    public static TranslationSource Instance
    {
        get { return instance; }
    }

    private readonly ResourceManager resManager = Resources.Strings.Resources.ResourceManager;
    private CultureInfo currentCulture = null;

    public string this[string key]
    {
        get { return this.resManager.GetString(key, this.currentCulture); }
    }

    public CultureInfo CurrentCulture
    {
        get { return this.currentCulture; }
        set
        {
            if (this.currentCulture != value)
            {
                this.currentCulture = value;
                var @event = this.PropertyChanged;
                if (@event != null)
                {
                    @event.Invoke(this, new PropertyChangedEventArgs(string.Empty));
                }
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

请注意,您的本地化资源文件(例如Resource.resx、Resource.en-US.resx)在文件夹<Project>/Resources/Strings/Resources/中,否则您需要更新此代码部分。

现在您可以使用这个新绑定:

<Label Foreground="{StaticResource ApplicationForgroundColor}" FontSize="21"
       Content="{util:Localization title}"/>
在运行时更改语言环境,您需要设置:

public static void SetLanguage(string locale)
{
    if (string.IsNullOrEmpty(locale)) locale = "en-US";
    TranslationSource.Instance.CurrentCulture = new System.Globalization.CultureInfo(locale);
}

1
这对我来说是一个完美的解决方案。非常感谢!有没有办法在设计模式下进行翻译呢? - user2675991
1
LocalizationExtension实现在MyTool.Util命名空间中,因此相应的xaml ns表达式看起来像:xmlns:util="clr-namespace:MyTool.Util" - DTeuchert
1
谢谢DTeuchert,单语言运行正常。 但我尝试在按钮点击时更改语言,但无法工作。以下是代码://怀疑这是否为ResourceManager的正确路径 private readonly ResourceManager resManager = WPFLocalizationNew.Resources.hi_IN.ResourceManager; private CultureInfo currentCulture = null; private void Button_Click(object sender, RoutedEventArgs e) { TranslationSource.Instance.CurrentCulture = new System.Globalization.CultureInfo("en-IN"); } 不幸的是,它没有任何效果,我漏掉了什么吗?请建议。 - Tink
资源在更改时没有更新,请帮忙。 - Tink
在btn onclick事件中,您只需要调用SetLanguage("en-IN")。在这里重要的是避免打字错误,因此我定义了一个默认的语言代码(“en-US”)。请检查您的资源文件是否命名为:“Resources.en-IN.resx”。 - DTeuchert
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接