Поскольку в экосистему 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 года в Гааге, когда работал на стенде «Спросите эксперта». Он показал мне, что это можно сделать, но лишь кратко показал мне часть кода и, конечно, не все. Как только я понял, что это можно сделать, я более или менее собрал это воедино в моменты, когда меня не засыпали вопросы от зашедших разработчиков. К сожалению, я не помню имя джентльмена, иначе я бы добавил несколько кредитов.
Повеселись! Я надеюсь, что это поможет вам штурмовать новые торговые площадки! ?
