Xamarin.Forms: как использовать локализацию, не зависящую от языка устройства

Я разрабатываю приложение Xamarin.Forms(проект библиотеки портативных классов) с Visual Studio 2013 CE. Сначала я фокусирую версию iOS.

Теперь я думаю о том, как сделать приложение многоязычным. Я просто прочитал официальную документацию Xamarin об этом, но я понял, что это решение принимает только системный язык целевого устройства.

В переносимой библиотеке классов у меня есть папка Resources с тремя языками: немецкий (по умолчанию), английский и французский.

Resource.resx
Resource.en-US.resx
Resource.fr-FR.resx
Resource.Designer.cs

Теперь я создал класс статических настроек, который выглядит так:

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;
    }
}

Теперь мой вопрос в том, можно ли изменить культуру в приложении во время выполнения при нажатии кнопки. Может быть, что-то вроде

Settings.CurrentCulture = Settings.Languages["English"];
Settings.ChangeCurrentCultureInfo(Settings.CurrentCulture);

Кто-нибудь может сказать мне, как это можно сделать?

Привет

Ответ 1

Наконец, я получил ответ от поддержки Xamarin. Решение я думал о работах. В PCL у меня есть только static Settings class, в котором хранятся разные объекты CultureInfo. Кроме того, я определил метод изменения текущей культуры и языка файла ресурсов.

public static void ChangeCurrentCultureInfo(CultureInfo cultureInfo)
{
    CurrentCulture = cultureInfo;
    Resource.Culture = CurrentCulture;
}

Было важно установить язык по умолчанию в конструкторе App(), прежде чем инициализировать главную страницу. Теперь я получил список со всеми поддерживаемыми языками с одним нажатым событием, которое вызывает метод ChangeCurrentCultureInfo.

Тем не менее, я хочу поблагодарить Энди Хоппера за его решение!

Привет

Ответ 2

Я не думаю, что вы можете сделать это из своего общего проекта PCL. Однако вы можете настроить UICulture из своих проектов, ориентированных на платформу. Чтобы сделать это из полезного места (т.е. Вашего приложения Forms), мы должны раскрывать это как услугу из ваших проектов платформы в качестве зависимости.

Сначала определите интерфейс, который описывает вашу службу управления культурами. Это должно жить в сборке, на которую ссылаются ваши специфичные для платформы проекты (общий проект PCL будет делать):

public interface ICultureInfo
{
    System.Globalization.CultureInfo CurrentCulture { get; set; }
    System.Globalization.CultureInfo CurrentUICulture { get; set; }
}

И в каждом из ваших проектов платформы включите тип, реализующий этот интерфейс:

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
    }
}

Затем в вашем приложении формы вы запрашиваете экземпляр реализации платформы из Xamarin Forms DependencyService. (ПРИМЕЧАНИЕ. Любые вызовы службы DependencyService должны произойти ПОСЛЕ обращения к Forms.Init())

Как только вы его получите, вы можете установить текущую культуру пользовательского интерфейса:

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

Et voila, любые изменения в культуре пользовательского интерфейса будут отражаться при каждом последующем поиске ресурсов. Обратите внимание на использование слова "последующее" - любые формы, использующие поиск ресурсов (например, если вы используете мои удобные расширения разметки XAML для локализации) не отражают культуру изменить, пока они не будут обновлены/перезагружены.

В заключение команда Xamarin сделала отличную работу, дублируя исходную инфраструктуру поиска ресурсов! Это просто требует небольшого толчка, чтобы превратить его в мир Xamarin Forms.