Приложение с поддержкой локализации на C# Windows Forms - часть 3

06:02:2013 Рі.

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

В предыдущей части был рассмотрен простой вариант реализации возможности смены языка интерфейса программы "на лету". Здесь рассматривается более сложный вариант, который является более гибким и предусматривает возможность контроля локализации не только в рамках одной формы, а всей программы в целом.

Первым делом ограгизуем Enum, который будет определять элементы перечисления, которыми мы будем пользоваться в программе, оперируя установками текущей культуры/локализации.

Обычно для реализации интерфейсов классов и энумов в проектах C# реализуем отдельные папки для хранения блоков кода программы данных типров:

 

 

 

AvialableLocalizations выглядит следующим образом:

public enumAvaliableLocalizations
{
    [Description("en-US")]
    English,
    [Description("ru-RU")]
    Russian

Это перечисление с текстовым атрибутом, который его описывает. 

Внимание! Особая роль отводится атрибутам Description. В текстовых атрибутах должны быть заданы подходящие атрибуты, которые служили бы затем корректным параметром для конструктора CultureInfo (см. часть 2 мануала).

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

Реализуем интерфейс ILanguageChangable со следующим содержимым:

namespace Active_Directory_Worker.Interfaces
{
     interfaceILanguageChangable
     {
          void ChangeFormLanguage(Enums.AvaliableLocalizations newLocalization);
     }
}

Из кода, приведенного выше видно, что в наследниках этого интерфейса должны быть реализованы функции ChangeFormLanguage, которые будут менять язык, используя свою внутреннею логику и принимая в качестве параметра переменную типа Enum-а, который мы создали в начале этого мануала.

Соответственно, определения форм, которые могут изменять локализацтю будут подобны нашей основной форме:

 public partial classStartWindow :Form, ILanguageChangable   

Теперь снова вернемся к нашему Enum-у. Каждому элементу его, который обозначает какой-то из языков локализации, соответствует Description со значением, которое мы потом используем в конструкторе CultureInfo. Однако, с помощью стандартных методов извлечь Description нельзя, поэтому для извлечения описаний используем следующий класс (был когда-то взят отсюда и актуален для каждой программы, использующей Enum, если описания нет - возвращается само названия элемента Enum-а): 

public static class EnumDescriptionHelper
{
    public static string GetEnumDescription(Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes =
          (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0)
           return attributes[0].Description;
        else
           return value.ToString();
    }
}

По-сути, три блока кода выше организовывают общий механизм, облегчающий и упрощающий работу с локализациями, позволяя их гибко добавлять/удалять/изменять.

Теперь задействуем этот механизм.

Для централизованного управления механизмом локализации во всей программе проще всего объявить или статический класс настроек или класс, реализующий паттерн Singleton (как удобнее и более обоснованно с точки зрения архитектуры программы). В этом файле реализуем функцию, которая будет доступна из любого места в программе:

public static classSettings
{
          publicAvaliableLocalizations CurrentLocalization;

      internalCultureInfo GetCulture()
      {
          return newCultureInfo(EnumDescriptionHelper.GetEnumDescription(CurrentLocalization));
      }

      internal void SetCulture(AvaliableLocalizations newLocalization)
      {   
          CurrentLocalization = newLocalization;
          Thread.CurrentThread.CurrentUICulture =
                 newCultureInfo(EnumDescriptionHelper.GetEnumDescription(CurrentLocalization));
      }

 Теперь рассмотрим реализацию интерфейса в файле кода нашего окна:

public void ChangeFormLanguage(AvaliableLocalizations newLocalization)
{
    _settings.SetCulture(newLocalization);

    var resources = newComponentResourceManager(typeof(StartWindow));

    CultureInfo newCultureInfo = newCultureInfo(EnumDescriptionHelper.GetEnumDescription(newLocalization));

    foreach (Control c in this.Controls)
    {
        resources.ApplyResources(c, c.Name, newCultureInfo);
    }

    resources.ApplyResources(this, "$this", newCultureInfo);

   foreach (var item in SS_Status.Items.CastToolStripItem>().Where(item => (item isToolStripStatusLabel) != false))
   {
       resources.ApplyResources(item, item.Name, newCultureInfo);
   }

   TSDD_Language.Text = newCultureInfo.NativeName;

   SetCurrenLanguageButtonChecked();
}

private void SetCurrenLanguageButtonChecked()
{
    foreach (ToolStripMenuItem languageButton in TSDD_Language.DropDownItems)
    {
        languageButton.Checked = (languageButton.Text == TSDD_Language.Text);
    }
}

 Приведенная выше функция, реализующая интерфейс ILanguageChangable очень напоминает функцию, которая рассмотрена во 2-й части мануала, однако, вместо того, чтобы принимать "жестко закодированные" строки текста, функция, которая отвечает за изменение языка интерфейса, теперь принимает Enum, который мы определили. 

Соответственно, наши функции обработки нажатия на выбор языка формы, которые изображены на рисунке ниже:

Теперь будут выглядеть как:

private void TSMI_English_Click(object sender, EventArgs e)
{
    ChangeFormLanguage(AvaliableLocalizations.English); 
}

private void TSMI_Russian_Click(object sender, EventArgs e)
{
    ChangeFormLanguage(AvaliableLocalizations.Russian); 
}

Итого: теперь для того чтобы изменить язык во время работы програмы необходимо вызвать одну функцию, передающую Enum, содержащий те значения, которые поддерживет программа, исключая ошибки и обеспечивая большее удобство и гибкость при работе.

Для добавлениия нового языка потребуется только добавить новый файл ресурсов путем установки свойства Language формы и переведя ее на нужный язык. Затем нужно будет лишь добавить в наш Enum новый язык, установив ему Description в значение, которое будет подходящим для конструктора CultureInfo. Функции же установки и получения текущей культуры вынесены в отдельный блок, доступный из любого места программы.

Если же вы захотите одновременно вызвать функции локализации всех активных форм - можно будет воспользоваться функцией общего для всех них интерфейса ILanguageChangable.

 

Комментарии  

 
0#2Алексей2013-07-11 21:38Вам нужно чтобы у Вас был создан интерфейс (см. по тексту "Реализуем интерфейс ILanguageChangable со следующим содержимым:...")

И, соответственно, Вы должны реализовать:

void ChangeFormLanguage(Enums.AvaliableLocalizations newLocalization);

в наследуемом от интерфейса MyProg.StartWindow
Цитировать
 
 
0#1Matt2013-07-02 16:49Я получаю такую ошибку:'MyProg.StartWindow' does not implement interface member 'MyProg.Interfaces.ILanguageChangable.ChangeFormLanguage(MyProg.Enums.AvailableLocalizations)'

В чем может быть дело? все делаю по инструкции
Цитировать
 

Добавить комментарий



Обновить

« Файл настроек C# программы - создание и использование   Мультиязычное приложение на C# Windows Forms - Часть 2 »
← Раньше

Фотоальбом

fotic.jpg

Облако Тегов