Xamarin.Forms:如何使用独立于设备语言的本地化

shi*_*ahh 12 c# localization ios xamarin xamarin.forms

我正在使用Visual Studio 2013 CE开发一个Xamarin.Forms应用程序(可移植类库项目).首先我关注iOS版本.

现在我正在考虑如何使应用程序多语言.我刚刚阅读了关于它的官方Xamarin文档,但我意识到这个解决方案只采用目标设备的系统语言.

在便携式类库中,我有一个包含三种语言的Resources文件夹:德语(默认),英语和法语.

Resource.resx
Resource.en-US.resx
Resource.fr-FR.resx
Resource.Designer.cs
Run Code Online (Sandbox Code Playgroud)

现在我刚刚创建了一个静态设置类,如下所示:

public static class Settings
{
    public static Dictionary<String, CultureInfo> Languages = new Dictionary<String, CultureInfo> { { "German", new CultureInfo("de-DE") }, { "English", new CultureInfo("en-US") }, { "French", new CultureInfo("fr-FR") } };

    public static CultureInfo CurrentCulture = Languages["German"];
    public static CultureInfo CurrentUiCulture = Languages["German"];

    public static void ChangeCurrentCultureInfo(CultureInfo cultureInfo)
    {
        Resource.Culture = cultureInfo;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是,是否可以通过单击按钮更改应用程序中的文化.也许是这样的

Settings.CurrentCulture = Settings.Languages["English"];
Settings.ChangeCurrentCultureInfo(Settings.CurrentCulture);
Run Code Online (Sandbox Code Playgroud)

有谁能告诉我这是怎么做到的?

问候

And*_*per 13

我不相信你可以在你的共享PCL项目中做到这一点.但是,您可以在特定于平台的项目中设置UICulture.要从有用的位置(即您的Forms应用程序)执行此操作,我们必须将此作为服务从您的平台项目中公开为依赖项.

首先,定义描述文化管理"服务"的界面.这应该存在于特定于平台的项目引用的程序集中(共享PCL项目将执行此操作):

public interface ICultureInfo
{
    System.Globalization.CultureInfo CurrentCulture { get; set; }
    System.Globalization.CultureInfo CurrentUICulture { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在每个平台项目中,包含一个实现该接口的类型:

using System;
using Xamarin.Forms;
using System.Threading;

[assembly:Dependency(typeof(YourNamespaceHere.PlatformCultureInfo))]
namespace YourNamespaceHere
{
    public class PlatformCultureInfo : ICultureInfo
    {
        #region ICultureInfo implementation

        public System.Globalization.CultureInfo CurrentCulture {
            get {
                return Thread.CurrentThread.CurrentCulture;
            }
            set {
                Thread.CurrentThread.CurrentCulture = value;
            }
        }

        public System.Globalization.CultureInfo CurrentUICulture {
            get {
                return Thread.CurrentThread.CurrentUICulture;
            }
            set {
                Thread.CurrentThread.CurrentUICulture = value;
            }
        }

        #endregion
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在表单应用程序中,从Xamarin Forms DependencyService请求平台实现的实例.(注意:对DependencyService的任何调用必须在调用Forms.Init()之后发生)

检索后,您可以设置当前的UI文化:

var cultureInfo = Xamarin.Forms.DependencyService.Get<ICultureInfo>();
cultureInfo.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");
Run Code Online (Sandbox Code Playgroud)

此外,对UI文化的任何更改都将反映在任何后续资源查找中.请注意使用"后续"一词 - 使用资源查找的任何表单(例如,如果您使用我的方便的本地化XAML标记扩展)将不会反映文化更改,直到它们被刷新/重新加载.

最后,Xamarin团队在重复原始资源查找基础架构方面做得非常出色!它需要一点点推动才能进入Xamarin Forms的世界.

  • 最简单的方法是将应用程序的MainPage设置为页面的新实例.如果您正在使用MVVM模式,则可以通过重新使用ViewModel来保留页面的状态. (2认同)

shi*_*ahh 6

最后我得到了Xamarin支持的答案.解决方案我正在考虑工作.在PCL中我只有static Settings class存储不同CultureInfo对象的东西.另外,我定义了一种用于更改当前文化和资源文件语言的方法.

public static void ChangeCurrentCultureInfo(CultureInfo cultureInfo)
{
    CurrentCulture = cultureInfo;
    Resource.Culture = CurrentCulture;
}
Run Code Online (Sandbox Code Playgroud)

App()在初始化主页面之前,必须在构造函数中设置默认语言.现在我得到了一个包含所有支持语言的列表视图,其中有一个调用该ChangeCurrentCultureInfo方法的tapped事件.

不过我要感谢Andy Hopper提供他的解决方案!

问候