Comments 24
Я в своё время тоже задумывался о динамической локализации WPF-приложений, но пришёл к выводу, что игра не стоит свеч. По-моему, смена системной локали происходит крайне редко. Даже если пользователь и поменяет системный язык во время работы приложения, его всё-равно попросят перегрузиться. А возможность выбора языка прямо из приложения — это, по-моему, рудимент из нулевых годов. Не думаю, что пользователь, у которого стоит английская локаль, вдруг захочет использовать ваше приложение на русском. Возможно, я не прав. Если не сложно, расскажите про ваш кейс.
Код не особо смотрел, но заметил использование деструктора для отписки от событий. Использование деструкторов для действий, не связанных с освобождением неуправляемых ресурсов, — плохая практика. Возможно, стоит посмотреть в сторону Weak Event Patterns.
Код не особо смотрел, но заметил использование деструктора для отписки от событий. Использование деструкторов для действий, не связанных с освобождением неуправляемых ресурсов, — плохая практика. Возможно, стоит посмотреть в сторону Weak Event Patterns.
Не думаю, что пользователь, у которого стоит английская локаль, вдруг захочет использовать ваше приложение на русском.
Зато вполне может быть наоборот: пользователь, например, с русской локалью вполне может захотеть англоязычный интерфейс. Я сам так делаю, т.к. иногда не понимаю некоторых формулировок.
Спрос рождает предложение, как говорится. Даже на хабрахабре находил посты про локализацию в wpf, где в комментариях люди как раз писали о том, что хотели бы менять локализацию на лету.
Мой кейс такой же, какой написал scumware. Некоторые трудно-переводимые предложения намного легче читаются на английском языке, нежели на русском. + бывает, что английский интерфейс выглядит лаконичнее. К тому же, я считаю, что заставлять пользователя перезапускать приложение — это как раз так и рудимент. Изменение локализации на лету более userfriendly.
Я посмотрю Weak Event Patterns, спасибо за совет =)
Мой кейс такой же, какой написал scumware. Некоторые трудно-переводимые предложения намного легче читаются на английском языке, нежели на русском. + бывает, что английский интерфейс выглядит лаконичнее. К тому же, я считаю, что заставлять пользователя перезапускать приложение — это как раз так и рудимент. Изменение локализации на лету более userfriendly.
Я посмотрю Weak Event Patterns, спасибо за совет =)
А есть ли спрос? Если вы пишете приложение для себя, то делаете как удобнее себе, конечно. Если же приложение коммерческое, то становится интересно, скольким пользователям нужна эта фича, и находится ли она в топе хотелок. У меня в этом большие сомнения.
Не думаю, что проводился опрос. Скорее это хотелка руководителя, чем пользователей.
А в комментарии я говорил про этот пост Локализация WPF приложений
А в комментарии я говорил про этот пост Локализация WPF приложений
Может я еще не проснулся, но отписыватся от события в деструкторе вообще не имеет смысла…
Подписка на LocalizationManager.Instance.CultureChanged означает, что в объекте LocalizationManager.Instance появится ссылка на ваш объект BindingLocalizationListener. Соответственно сборщик мусора соберет его только когда ОБА объекта (LocalizationManager.Instance и BindingLocalizationListener) станут недоступны. Т.е. кажется никогда до окончания работы всего приложения.
Так что не пишите так, это дает иллюзию защищенности… Возьмите какой-нибудь профилировщик памяти и посмотрите на ваше приложение через часок работы… На правах рекламы могу посоветовать dotmemory…
Подписка на LocalizationManager.Instance.CultureChanged означает, что в объекте LocalizationManager.Instance появится ссылка на ваш объект BindingLocalizationListener. Соответственно сборщик мусора соберет его только когда ОБА объекта (LocalizationManager.Instance и BindingLocalizationListener) станут недоступны. Т.е. кажется никогда до окончания работы всего приложения.
Так что не пишите так, это дает иллюзию защищенности… Возьмите какой-нибудь профилировщик памяти и посмотрите на ваше приложение через часок работы… На правах рекламы могу посоветовать dotmemory…
А возможность выбора языка прямо из приложения — это, по-моему, рудимент из нулевых годов. Не думаю, что пользователь, у которого стоит английская локаль, вдруг захочет использовать ваше приложение на русском.
Я переходил на английскую локаль постепенно. В школьные годы, когда я только начинал пользоваться компьютером, у меня всё было по-русски, а где-то по окончанию универа всё уже было по-английски, но переход не был моментальным: сначала английскими стали профессиональные инструменты, потом постепенно всё остальное и только в самом конце сама ось.
Вы предлагаете оставить только одну системную настройку и не давать переключать локаль на уровне приложения? Странная затея. Если честно, не помню серьёзных приложений, которые так делают. Даже модные метрошные приложения типа ВК дают переключать язык в приложении. Office, VS — везде настройка в приложениях. Причём в Офисе можно по отдельности настраивать язык справки и язык подсказок, например. В куче игр по отдельности настраиваются язык звука и язык субтитров. Я бы сказал, в современном мире языковые настройки наоборот стали более мощными.
Есть несколько сценариев, когда переключение языка на лету очень удобно. Мы вот разрабатываем приложения для промышленной автоматики, которые работают неделями без перезагрузки, и там зачастую рестарт приложения вызовет, скажем, останов конвейера. Это не смертельно — поломки не будет, но ошибку надо подтвердить, конвейер перезапустить, и т.п. Иногда пользователи обращаются в техподдержку, тогда оператор логигинится в систему и видит экран — а там всё на китайском. И вот тогда он переключает язык на лету, показывает что к чему, после чего язык переключается обратно, и всё это без рестарта приложения. Ну ещё при локализации бывает, что локализованные строки сильно длиннее английских (несмотря на то, что дазаном это предусмотрено), и тогда удобно переключаться туда-сюда и корректировать перевод без рестарта. Ну и когда я работаю на техподдержке, то отправляю пользователю скриншоты с пояснениями на его родном языке — и мне тоже неудобно переключать язык с перезагрузкой (особенно если пользователь висит на телефоне и ждёт).
В общем я за то, что если есть возможность делать переключение языка на лету — то это хорошо и правильно и повышает удобство. Это особенно приятно, если структура приложения модульная, тогда имеет смысл реализовать локализацию в ядре, так что новые модули будут переключаться на лету автоматически.
Обычно тут рассуждают о том, что конечный пользователь будет редко переключать язык, и это в общем-то так, но есть ведь ещё тестирование, техподдержка, сервис, пусконаладка, обучение персонала, и т.д., и вот тут переключение языка используется довольно часто.
В общем я за то, что если есть возможность делать переключение языка на лету — то это хорошо и правильно и повышает удобство. Это особенно приятно, если структура приложения модульная, тогда имеет смысл реализовать локализацию в ядре, так что новые модули будут переключаться на лету автоматически.
Обычно тут рассуждают о том, что конечный пользователь будет редко переключать язык, и это в общем-то так, но есть ведь ещё тестирование, техподдержка, сервис, пусконаладка, обучение персонала, и т.д., и вот тут переключение языка используется довольно часто.
Хм. Интересно. Эта необходимость в основном является следствием того, что одни техподдержка и сервис работают сразу на несколько стран, или такая же проблема, скажем, есть у Microsoft, где техподдержка наверняка разделена? Никогда не звонил им в саппорт, но в принципе любопытно: я могу попросить их объяснять мне последовательность нажатий кнопок на разных языках? Скажем, говорить мне удобнее по-русски, а винда у меня на английском…
вы зря ставите выбранную культуру одновременно и в CurrentCulture и CurrentUICulture. Для смены языка строк из ресурсов нужна только CurrentUICulture, которая отвечает за взятие даннных из ресурсов. А CurrentCulture переключит форматирование дат и всего прочего, что в готовом софте вызовет крайне нелестные эмоции от пользователей вроде меня, у которых например русская локаль но английский интерфейс.
Спасибо за совет, буду иметь в виду.
К слову, я обычно не использую стандартный вывод дат, а форматирую с помощью конвертеров, т.к. пользователи просят формат yyyy-MM-dd.
К слову, я обычно не использую стандартный вывод дат, а форматирую с помощью конвертеров, т.к. пользователи просят формат yyyy-MM-dd.
Количество приложений, которое понимает разницу между CurrentCulture и CurrentUICulture, примерно равно нулю. :( Я пробовал использовать связку «русская локаль + английский интерфейс», но все программы норовят выставить русский интерфейс из-за русской локали. В конце концов плюнул, поставил локалью «English (UK)» и настроил вручную все форматы.
Про культуры уже сказали, повторяться не буду.
А в стиле работать будет?
Это задокументированное поведение ToString, которое гарантированно не сломается в следующей версии?
if (target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty)
А в стиле работать будет?
target.TargetProperty.ToString() == «System.Object Source»
Это задокументированное поведение ToString, которое гарантированно не сломается в следующей версии?
В стилях, к сожалению, не работает смена культуры, т.к. Setter не является DependencyObject, а Value не является DependencyProperty. Если получится решить эту проблему, я напишу в комментариях или в статье.
Думаю, что проверку «System.Object Source» можно вообще убрать, т.к. нет других свойств, в которые можно было бы навесить локализацию в привязке. Т.к. System.Reflection.RuntimePropertyInfo является internal классом, то я не нашел другого выхода. Выглядит костыльно, согласен =)
Думаю, что проверку «System.Object Source» можно вообще убрать, т.к. нет других свойств, в которые можно было бы навесить локализацию в привязке. Т.к. System.Reflection.RuntimePropertyInfo является internal классом, то я не нашел другого выхода. Выглядит костыльно, согласен =)
Вспомнил, что стили тоже умеют принимать привязки, поэтому нужно лишь добавить еще одну проверку
if ((target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty) || target.TargetObject is Setter)
Менять значения «на лету» при смене языка с использованием ресурсов Resx не так уж сложно, я это описал в своей статье на хабре ещё в апреле в Локализация WPF приложений на лету.
Да, я читал вашу статью. Мне требовалось использовать биндинг в качестве ключа ресурса, а вашим способом это невозможно сделать.
И описанный в этой статье способ позволяет использовать не только ресурсы, но и любые другие источники (например, база данных).
И описанный в этой статье способ позволяет использовать не только ресурсы, но и любые другие источники (например, база данных).
Кстати, интересно, какие другие источники данных вы реально используете. Потому что «например, база данных» звучит ну очень странно, не могу придумать причину так делать.
Sign up to leave a comment.
Локализация WPF-приложения и мгновенная смена культуры