Поскольку в экосистему Windows Phone добавляется все больше и больше торговых площадок, глобализация вашего приложения становится все более важной. Я рад, что в наши дни многие приложения поддерживают несколько языков. Я обычно использую решение, описанное в моей статье Выбор языка на основе MVVMLight для Windows Phone 7 — оно автоматически выбирает язык с телефона и по умолчанию выбирает английский / американский, если приложение по умолчанию не поддерживает язык. Но я также хотел бы дать пользователю возможность переопределить автоматически выбранный язык. Я, например, запускаю телефонную ОС на английском / американском языках, но я бы хотел, чтобы определенные голландские приложения работали на голландском, спасибо. Если вы следуете примеру глобализации, как описано в MSDNиспользуя мой код, который, к сожалению, требует перезапуска приложения после применения изменения языка. Ну не надо больше!
Пример, предоставленный MSDN, предоставляет помощника локализованной строки, который выглядит примерно так:
namespace InstantLanguage.Resources { public class LocalizedStrings { public LocalizedStrings() { } private static AppResources localizedResources = new AppResources(); public AppResources LocalizedResources { get { return localizedResources; } } } }
Я использовал его с момента своего первого локализованного приложения и обычно помещал его в тот же каталог, что и мои файлы ресурсов. Вы объявляете это в своем App.xaml следующим образом:
<Application.Resources> <!-- More resources --> <Resources:LocalizedStrings x:Key="LocalizedStrings"/> </Application.Resources>
Конечно, сначала нужно объявить пространство имен для LocalizedResources, поэтому в верхней части вы добавите что-то вроде
xmlns:Resources="clr-namespace:InstantLanguage.Resources"
И теперь вы можете использовать его для отображения локализованных строк, привязавшись к нему следующим образом:
<TextBlock x:Name="ApplicationTitle" Text="{Binding LocalizedResources.AppTitle, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextNormalStyle}"/>
Но, к сожалению, как я уже сказал, если вы меняете язык, например, вызывая этот код, ничего не происходит.
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE"); Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;
Причина этого довольно проста: приложение не может информировать GUI , так как LocalizedStrings не поддерживает INotifyPropertyChanged . Но это легко исправить, взяв MVVMLight и реализуя LocalizedStrings как дочерний класс ViewModelBase:
using System.Windows; namespace InstantLanguage.Resources { using GalaSoft.MvvmLight; public class LocalizedStrings : ViewModelBase { private static AppResources localizedresources = new AppResources(); public AppResources LocalizedResources { get { return localizedresources; } } public void UpdateLanguage() { localizedresources = new AppResources(); RaisePropertyChanged(() => LocalizedResources); } public static LocalizedStrings LocalizedStringsResource { get { return Application.Current.Resources["LocalizedStrings"] as LocalizedStrings; } } } }
и затем есть другой вопрос: у приложения должен быть способ запустить событие RaisePropertyChanged для класса, используемого в качестве StaticResource . Вот для чего нужны UpdateLanguage и статический LocalizedStringsResource. Обратите внимание, что для этого вам нужно определить ресурс с ключом LocalizedStrings:
<Resources:LocalizedStrings x:Key="LocalizedStrings"/>
Ключи, которые должны совпадать, отмечены красным в обеих частях кода. В любом случае, после того, как вы изменили язык, позвоните:
LocalizedStrings.LocalizedStringsResource.UpdateLanguage();
И бум — все ваши тексты, поступающие из файла ресурсов, будут обновляться мгновенно.
Здесь вы можете найти пример решения, демонстрирующего этот принцип, используя новейшую версию моей библиотеки # wp7nl для codeplex и технику, о которой я упоминал ранее . Существует простая подклассификация модели представления LanguageSettingsViewModel, и вы можете увидеть вызов UpdateLanguage непосредственно после изменения языкового параметра:
using System.ComponentModel; using InstantLanguage.Resources; using Wp7nl.Globalization; namespace InstantLanguage.ViewModel { /// <summary> /// Main view model. By subclassing LanguageSettingsViewModel we get properties /// "SupportedLanguages" and "CurrentLanguage" for free. /// </summary> public class MainViewModel : LanguageSettingsViewModel { public MainViewModel() { // Note: en-US is added by default AddLanguages(new Language { Description = "Deutsch", Locale = "de-DE" }); AddLanguages(new Language { Description = "Nederlands", Locale = "nl-NL" }); PropertyChanged += MainViewModelPropertyChanged; } void MainViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "CurrentLanguage") { SetLanguageFromCurrentLocale(); LocalizedStrings.LocalizedStringsResource.UpdateLanguage(); } } } }
В конце концов, это всегда довольно просто.
Обратите внимание, что для того, чтобы эта глобализация и код работали правильно, вам необходимо принять во внимание следующее:
- Вам нужно будет изменить свойство «Custom Tool» для каждого файла ресурсов на «PublicResXFileCodeGenerator» (по умолчанию ResXFileCodeGenerator)
- Вам потребуется файл .resx для каждого языка, который вы поддерживаете. Для языка по умолчанию я называю мой обычно AppResources.resx, для немецкого я тогда должен определить AppResources.de-DE.resx и т. Д.
- Вам также нужно будет добавить поддерживаемые дополнительные языки в тег SupportedCultures в вашем основном проекте. Это нужно сделать вручную , открыв файл проекта, например, в блокноте. Почему это не может быть сделано из Visual Studio — не спрашивайте меня, я просто посланник здесь ;-). Например, для поддержки голландского и немецкого языков вы меняете содержимое тега на:
<SupportedCultures>nl-NL;de-DE</SupportedCultures>
Примечание: я получил идею от джентльмена, которого я встретил на выпуске Microsoft Techdays 2012 года в Гааге, когда работал на стенде «Спросите эксперта». Он показал мне, что это можно сделать, но лишь кратко показал мне часть кода и, конечно, не все. Как только я понял, что это можно сделать, я более или менее собрал это воедино в моменты, когда меня не засыпали вопросы от зашедших разработчиков. К сожалению, я не помню имя джентльмена, иначе я бы добавил несколько кредитов.
Повеселись! Я надеюсь, что это поможет вам штурмовать новые торговые площадки! ?