Comments 22
UFO just landed and posted this here
Налету, к сожалению, невозможно — я, когда нужно менять язык по выбору пользователя, просто сохраняю локаль в User Settings и применяю при запуске. Соот-но, чтобы изменить язык — надо выбрать нужный и перезапустить приложение.
А список доступных — можно взять через System.Globalization.CultureInfo.GetCultures()
А список доступных — можно взять через System.Globalization.CultureInfo.GetCultures()
+1
UFO just landed and posted this here
Ну было бы удобнее, конечно, прямо на лету переключать — но мне показалось, что потраченное на разработку время не окупится от такой мелочи — и в своих проектах просто предлагаю пользователю сделать рестарт.
А список языков… ну как вариант — проще где-то в настройках просто хранить список доступных языков. Опять же — автоматическое построение такого списка можно сделать, но я не вижу чтобы без этого нельзя было бы обойтись.
А список языков… ну как вариант — проще где-то в настройках просто хранить список доступных языков. Опять же — автоматическое построение такого списка можно сделать, но я не вижу чтобы без этого нельзя было бы обойтись.
+1
2. вообщето имелось ввиду — получить список языков, для которых есть «сборки-сателиты»
пробежать по всем DLL-кам в папке и посмотреть «что внутрях» посредством Assembly.LoadFile и Assembly.GetType? а можно не колупаться в потрошках, а сразу принять некие конвенции по именованию DLL-ок и список языков извлекать простым парсингом имен.
не пойдет?
0
Для WinForms в любом случае возможно «на лету» переключать язык, т.е. менять картинки, надписи, их размер и расположение. В своем блоге я приводил пример с исходными кодами как это сделать и автоматизировать при помощи рефлексии.
+1
Немного подробнее: можно создать несколько .resx-файлов, для каждой из культур, и там будут содержаться соответствующие свойства контролов для каждого из языков: Text, Size, Position и т.д. При переключении языка приложения(т.е. когда пользователь инициализирует событие переключения) необходимо выполнить:
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);
но чтобы не указывать каждому из контролов какое свойство ему получить, можно просто вызывать метод, который с помощью рефлексии будет смотреть, что есть на форме и в resx-файле, и сопоставлять. Итак, код метода:
//метод для установки локализации формы «на лету»
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);
}
}
В результате, с помощью небольших затрат можно менять «на лету» язык приложения.
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);
но чтобы не указывать каждому из контролов какое свойство ему получить, можно просто вызывать метод, который с помощью рефлексии будет смотреть, что есть на форме и в resx-файле, и сопоставлять. Итак, код метода:
//метод для установки локализации формы «на лету»
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);
}
}
В результате, с помощью небольших затрат можно менять «на лету» язык приложения.
+1
Для избавления от перезагрузок программы я сделал все очень просто: написал класс-синглтон, который парсит хмл-файл с локализациями. В нем есть событие, которое обозначает смену текущей локалицазии приложения. Все окна подписываются на данное событие если надо. Обработчик данного события представляет собой запрос у класса локализации всех необходимых строк по их имени рессура.
Например:
Сейчас продумываю сделать расширяющий компонент для формы, который автоматизирует данный процесс, но пока руки не доходят.
Например:
OpenFileMenu.Text = Localization.Instance.GetString("MainForm.MainMenu.File.Open"); SaveAsFileMenu.Text = Localization.Instance.GetString("MainForm.MainMenu.File.SaveAs");
Сейчас продумываю сделать расширяющий компонент для формы, который автоматизирует данный процесс, но пока руки не доходят.
0
На лету можно. Достаточно создать свой MarkupExtension, в котором подписываться на изменения культуры. При этом перегружать значения ресурс файлов. «WPF Localization on-the-fly».
0
Можно глягуть пример тут — svn2.assembla.com/svn/DevSamples/WpfLocalizationOnTheFly/trunk/LocalizationBase/LocalizeExtensionBase.cs
К сожалению, не помню ссылку на оригинальный источник
К сожалению, не помню ссылку на оригинальный источник
0
Да, отсутствие переключения налету — это ооочень серьезный минус.
0
Я не вижу в этом серьезного минуса — ну может переключение на лету было бы приятной фичей, но не более. В каких случаях это действительно критично? Как я вижу — переключение интерфейса приложения — это не common-task, т.е. юзер не меняет язык интерфейса раз в 5 мин. В идеале — вообще не меняет, а один раз настраивает язык системы и софт подстраивается под него. В крайнем случае — меняет в настройках, видит сообщение — Язык будет изменен после рестарта приложения — и работает дальше.
+1
Огромное спасибо за статью! Как раз возникла эта задача, а вариант через XAML действительно уж очень громоздкий.
Ещё хорошая новость — у меня получилось сделать переключение «на лету», причём именно используя Binding.
Если интересно — готов поделиться :)
Ещё хорошая новость — у меня получилось сделать переключение «на лету», причём именно используя Binding.
Если интересно — готов поделиться :)
0
Да, конечно интересно. Как вариант — вы можете оформить это небольшой статьей, а либо просто выложить проект куда-нибудь.
0
И когда собираетесь делиться?
+1
Вот, я пользую этот способ. Очень удобно.
www.codeproject.com/KB/WPF/WPF_Resx_Localization.aspx
www.codeproject.com/KB/WPF/WPF_Resx_Localization.aspx
0
Sign up to leave a comment.
Локализация WPF приложений