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

06:02:2013 –≥.

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

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

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

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

 

localization_9.jpg
 

 

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.Cast<ToolStripItem>().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, который мы определили. 

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

localization_7.jpeg

“еперь будут выгл€деть как:

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#3Emin2017-05-03 23:10¬ классе:
public static class Settings

все свойства и методы должны быть тоже статическими. » вызывать его потом не:
_settings.SetCulture(newLocalization);

а Settings.SetCulture(newLocalization);
÷итировать
 
 
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

ќблако “егов