×
Namespaces

Variants
Actions
Revision as of 13:42, 26 July 2013 by Xinx Gong (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

From Nokia Developer 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 13:42.
92 page views in the last 30 days.
×