Некоторое время назад возникла необходимость создать приложение WinForms, способное «на лету» изменять язык интерфейса. Что же, придумывать свои «велосипеды» на мой взгляд является крайне непродуктивным занятием(хотя достаточно интересным и обучающим), поэтому я решил воспользоваться встроенной поддержкой локализации в Visual Studio, но несколько автоматизировать процесс с помощью отражения(reflection).
Вменяемой статьи по этому поводу в рунете я не нашел, поэтому решил поделиться собранными сведениями в своем блоге. Там же выложено тестовое solution с поддержкой переключения между русским, английским и украинским языками.
Так что данную статью прошу не считать плагиатом моего же блога)))
Итак, несколько слов о концепции локализации в .NET и о возможностях, предоставляемых Visual Studio для работы с файлами ресурсов. У каждой формы есть свойства Localizable и Language. Первое нужно выставить в true, а во втором выбрать один из языков, поддержку которого необходимо осуществлять. Потом изменяем объектов на форме(текст, картинки, размеры, расположение на форме и т.п.), и всё сохраняем. В результате получаем файл ресурсов, который содержит локализацию для определенного языка.
Для каждого языка локализации создается свой файл ресурсов, который содержит параметры для какого-либо языка интерфейса приложения(например, файл параметров может называтся «Form1.ru-RU.resx»).
Далее, во время выполнения приложения в момент переключения на другой язык необходимо сменить текущую локализацию сборки. Например:
и после этого извлечь из соответствующего файла ресурсов значения необходимых свойств для объектов на форме. Например таким образом:
и так для всех объектов, которые есть на форме. А это достаточно утомительно, так как после добавления/удаления объектов с формы необходимо вносить изменения в код. И вот здесь на помощь приходит отражение, с помощью которого можно получить все поля, определенные в классе формы, и назначить им значения из файла ресурсов. Для этого необходимо использовать метод на подобии следующего:
Несколько слов о структуре проекта примера. Есть главная форма, и есть форма параметров, которая содержит объект ComboBox с перечнем поддерживаемых языков интерфейсов. Эта форма также содержит событие, которое срабатывает при выборе другого языка. В главной форме назначен обработчик этого события, который и вызывает метод localizeForm(Form someForm, CultureInfo cultureInfo).
Вменяемой статьи по этому поводу в рунете я не нашел, поэтому решил поделиться собранными сведениями в своем блоге. Там же выложено тестовое solution с поддержкой переключения между русским, английским и украинским языками.
Так что данную статью прошу не считать плагиатом моего же блога)))
Итак, несколько слов о концепции локализации в .NET и о возможностях, предоставляемых Visual Studio для работы с файлами ресурсов. У каждой формы есть свойства Localizable и Language. Первое нужно выставить в true, а во втором выбрать один из языков, поддержку которого необходимо осуществлять. Потом изменяем объектов на форме(текст, картинки, размеры, расположение на форме и т.п.), и всё сохраняем. В результате получаем файл ресурсов, который содержит локализацию для определенного языка.
Для каждого языка локализации создается свой файл ресурсов, который содержит параметры для какого-либо языка интерфейса приложения(например, файл параметров может называтся «Form1.ru-RU.resx»).
Далее, во время выполнения приложения в момент переключения на другой язык необходимо сменить текущую локализацию сборки. Например:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU"); и после этого извлечь из соответствующего файла ресурсов значения необходимых свойств для объектов на форме. Например таким образом:
ResourceManager LocRM = new ResourceManager("WindowsApplication1.WinFormStrings",typeof(Form1).Assembly);
Label1.Text = LocRM.GetString("Label1.Text"), Thread.CurrentThread.CurrentUICulture);
Label2.Text = LocRM.GetString("Label2.Text"), Thread.CurrentThread.CurrentUICulture);
............... и так для всех объектов, которые есть на форме. А это достаточно утомительно, так как после добавления/удаления объектов с формы необходимо вносить изменения в код. И вот здесь на помощь приходит отражение, с помощью которого можно получить все поля, определенные в классе формы, и назначить им значения из файла ресурсов. Для этого необходимо использовать метод на подобии следующего:
//метод для установки локализации формы "на лету"
public void localizeForm(Form someForm, CultureInfo cultureInfo)
{
Type someFormType = someForm.GetType();
ResourceManager res = new ResourceManager(someFormType);
//зададим список свойств объектов, которые будем извлекать из файла ресурсов
string[] properties = { "Text", "Location" };
foreach (string propertyName in properties)
{
//выбор всех свойств класса формы, извлечение из файла ресурсов значения, и их установка
foreach (FieldInfo fieldInfo in someFormType.GetFields(BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance))
{
PropertyInfo propertyInfo = fieldInfo.FieldType.GetProperty(propertyName);
if (propertyInfo == null)
continue;
object objProperty = res.GetObject(fieldInfo.Name + '.' + propertyInfo.Name, cultureInfo);
if (objProperty == null) continue;
object field = fieldInfo.GetValue(someForm);
if (field != null)
propertyInfo.SetValue(field, objProperty, null);
}
//код для установки свойств самих форм
PropertyInfo propertyInfo1 = someFormType.GetProperty(propertyName);
if (propertyInfo1 == null)
continue;
object objProperty1 = res.GetObject("$this." + propertyInfo1.Name, cultureInfo);
if (objProperty1 == null) continue;
propertyInfo1.SetValue(someForm, objProperty1, null);
}
} Несколько слов о структуре проекта примера. Есть главная форма, и есть форма параметров, которая содержит объект ComboBox с перечнем поддерживаемых языков интерфейсов. Эта форма также содержит событие, которое срабатывает при выборе другого языка. В главной форме назначен обработчик этого события, который и вызывает метод localizeForm(Form someForm, CultureInfo cultureInfo).