Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Windows Phone的语言切换实时本地化

From Wiki
Jump to: navigation, search


Contents

介绍

在Windows Phone的开发中,不可避免的会接触到应用的本地化。按照MSDN中默认的本地化处理的方式,会遇到一个问题,就是在切换语言的时候,当前已经打开的页面不能实时的切换成切换后语言,而只能在重新新建页面的时候才能切换语言。所以,要想实时的切换语言,咱们还需要做一些简单的处理。

下面以Windows Phone 8的一个工程来作为例子,介绍一下如何实现实时的语言切换。

准备工作

这个流程遵循MSDN中默认本地化处理的步骤走即可。

1. 新建一个Windows Phone 8的工程,命名为LocalizationExample。

2. 添加需要支持的语言。

3. 添加一些需要本地化的字段。

更新XAML界面

新建Windows Phone 8的工程会默认生成该文件,Windows Phone 7的工程需要手动添加。

将LocalizedStrings类添加上对接口INotifyPropertyChanged的支持,以通知在XAML界面中实现了本地化的控件更新内容。

    /// <summary>
/// 提供对字符串资源的访问权。
/// </summary>
public class LocalizedStrings : INotifyPropertyChanged
{
private static AppResources _localizedResources = new AppResources();
 
public AppResources LocalizedResources { get { return _localizedResources; } }
 
/// <summary>
/// 通知XAML界面中的控件更新内容
/// </summary>
public void RefreshLanguage()
{
NotifyPropertyChanged("LocalizedResources");
}
 
#region INotifyPropertyChanged Members
 
public event PropertyChangedEventHandler PropertyChanged;
 
// Used to notify Silverlight that a property has changed.
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
 
#endregion
}

这样,只需要在切换语言的时候,调用一下LocalizedStrings类的RefreshLanguage()方法就可以更新界面的语言了。

更新ApplicationBar

ApplicationBar在Windows Phone中是独立于Sliverlight存在的,所以不能实现绑定,用上面的方法来实现本地化,而需要手动去对ApplicationBar的内容去修改。

LocalizationUtil类

在这里,为了能以最简便的方法来实现对语言的切换,实现了下面的类:

    public static class LocalizationUtil
{
private static LocalizedStrings LocalizedStrings = App.Current.Resources["LocalizedStrings"] as LocalizedStrings;
 
/// <summary>
/// 设置语言
/// </summary>
/// <param name="ietfLanguageTag">一个 RFC 3066 语言字符串(如:"zh-cn")或一个空字符串 ("")</param>
public static void SetLanguage(string ietfLanguageTag)
{
try
{
AppResources.Culture = new System.Globalization.CultureInfo(ietfLanguageTag);
 
App.RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
App.RootFrame.FlowDirection = flow;
}
catch
{
// 如果此处导致了异常,则最可能的原因是
// ResourceLangauge 未正确设置为受支持的语言
// 代码或 ResourceFlowDirection 设置为 LeftToRight 以外的值
// 或 RightToLeft。
 
if (Debugger.IsAttached)
{
Debugger.Break();
}
 
throw;
}
 
LocalizedStrings.RefreshLanguage();
foreach (var appBarItem in AppBarItemPropertyNameMappingDictionary.Keys)
{
appBarItem.Text = AppResources.ResourceManager.GetString(AppBarItemPropertyNameMappingDictionary[appBarItem], AppResources.Culture);
}
}
 
private static Dictionary<IApplicationBarMenuItem, string> _appBarItemPropertyNameMappingDictionary;
/// <summary>
/// "应用程序栏 按钮/菜单" 与 "AppResources的属性名" 的对应集合
/// </summary>
public static Dictionary<IApplicationBarMenuItem, string> AppBarItemPropertyNameMappingDictionary
{
get
{
if (_appBarItemPropertyNameMappingDictionary == null)
{
_appBarItemPropertyNameMappingDictionary = new Dictionary<IApplicationBarMenuItem, string>();
}
return _appBarItemPropertyNameMappingDictionary;
}
}
 
/// <summary>
/// 设置应用程序栏 按钮/菜单 支持本地化
/// </summary>
/// <param name="appBarItem">应用程序栏 按钮/菜单</param>
/// <param name="propertyNameInAppResources">文本在AppResources的属性名</param>
public static void AddLocalization(this IApplicationBarMenuItem appBarItem, string propertyNameInAppResources)
{
appBarItem.Text = AppResources.ResourceManager.GetString(propertyNameInAppResources, AppResources.Culture);
 
if (AppBarItemPropertyNameMappingDictionary.ContainsKey(appBarItem))
{
AppBarItemPropertyNameMappingDictionary[appBarItem] = propertyNameInAppResources;
}
else
{
AppBarItemPropertyNameMappingDictionary.Add(appBarItem, propertyNameInAppResources);
}
}
 
/// <summary>
/// 应用程序栏 按钮/菜单 不再需要支持本地化
/// </summary>
/// <param name="appBarItem"></param>
public static void RemoveLocalization(this IApplicationBarMenuItem appBarItem)
{
if (AppBarItemPropertyNameMappingDictionary.ContainsKey(appBarItem))
{
AppBarItemPropertyNameMappingDictionary.Remove(appBarItem);
}
}
 
/// <summary>
/// 程序栏不再需要支持本地化
/// 在Page的OnRemovedFromJournal事件中调用该方法
/// </summary>
/// <param name="appBar"></param>
public static void RemoveLocalization(this IApplicationBar appBar)
{
foreach (var button in appBar.Buttons)
{
(button as IApplicationBarMenuItem).RemoveLocalization();
}
foreach (var item in appBar.MenuItems)
{
(item as IApplicationBarMenuItem).RemoveLocalization();
}
}
}

使用LocalizationUtil 类

1. 新建ApplicationBar时对其按钮和菜单加上对本地化的支持。

    private void BuildLocalizedApplicationBar()
{
// 将页面的 ApplicationBar 设置为 ApplicationBar 的新实例。
ApplicationBar = new ApplicationBar();
 
// 创建新按钮并将文本值设置为 AppResources 中的本地化字符串。
ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative));
appBarButton.AddLocalization("AppBarButtonText");
ApplicationBar.Buttons.Add(appBarButton);
 
// 使用 AppResources 中的本地化字符串创建新菜单项。
ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem();
appBarMenuItem.AddLocalization("AppBarMenuItemText");
ApplicationBar.MenuItems.Add(appBarMenuItem);
}

2. 在页面从堆栈中移除的时候,取消对ApplicationBar本地化的支持。

    protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
{
if (ApplicationBar != null)
{
ApplicationBar.RemoveLocalization();
}
}

3.切换语言

    private void LanguageButton_Click(object sender, RoutedEventArgs e)
{
LocalizationUtil.SetLanguage("zh-cn"); // "zh-hk"; "en-us"; ...
}

示例代码

File:Localization Example.zip

This page was last modified on 26 July 2013, at 10:42.
176 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×