语言背水一战 Windows 10 (80) – 本地化

1. 前言

齐同样篇稿子介绍了各种WPF本地化的入门知识,这篇稿子介绍UWP本地化的入门知识。

[源码下载]

2. 使用resw资源文件落实本地化

每当原先的XAML平台,resx资源文件是一模一样栽颇便利之本地化方案,但于UWP中微软又再次推荐x:Uid方案,默认的资源文件也改为resw资源文件。虽然后缀名只差了一个字母,但利用办法了两样。最要的分别是resw资源文件不见面创造对应之Designer.cs类,这就招致本地化的贯彻方案了不同。

语言 1

背水一战 Windows 10 (80) – 本地化

2.1 在XAML中实现本地化

以XAML中实现本地化的长河充分简短。首先在路遭到初修建”strings”文件夹,在”strings”文夹下开创”en-US”和”zh-CN”文件夹,并以简单个公文夹着分头增长”Resources.resw”资源文件。最终目录结构如下:
语言 2

在zh-CN\Resources.resw和en-US\Resources.resw添加区区独新资源,分别是UsernameTextBox.Width和UsernameTextBox.Header:
语言 3

当XAML中上加一个TextBox,设置x:Uid为UsernameTextBox,x:Uid将XAML元素和资源文件被之资源进行关联:

<TextBox x:Uid="UsernameTextBox"/>

运行后即可看出UsernameTextBox的Header设置也”用户名”,Width为100。

在“设置\区域与言语”中将”English”设置为默认语言,再次运行应用可视运行于英语环境下的成效。
语言 4

这么基本的本地化功能就是实现了。这种本地化方式发生如下优点:

  • 简而言之高效,容易达成亲手
  • 语法简单,不待Binding等知识
  • 可指定任意属性进行本地化
  • 支持CLR属性

除,上一样篇稿子提到的ResXManager也支持Resw资源文件,还得使多语言应用工具确保对资源文件进行管制,博客园的这篇稿子页对这个家伙进行了详细介绍:
Win10 UWP
开发系列:使用多语言工具包让应用支撑多语言

还是参考这视频:
Windows 10 Apps Designing for Global
Customers

作者:webabcd

2.2 关联到其它资源文件

UI元素默认与Resources.resw进行关联,如果急需以及其它资源文件涉及,可以长资源文件之路线。如需与/OtherResources.resw中的资源事关,x:Uid的语法如下:

x:Uid="/OtherResources/AddressTextBox"

介绍
背水一战 Windows 10 之 本地化

2.3 附加属性之本地化

本着网提供的增大属性,资源的称号语法如下:

UsernameTextBox.Grid.Row

对自定义附加属性,语法稍微复杂一些:

ShowMessageButton.[using:LocalizationDemoUwp]ButtonEx.Content

奇怪的是,就这么直白运行应用会报错。只有用这资源的UI元素已经来这个附加属性的价才能够正常运作,简单来说就是用随便为这个附加属性设置一个价:

<Button Margin="5" x:Uid="ShowMessageButton"  local:ButtonEx.Content="ssssss"/>
  • Demo
  • 变更语言

2.4 其它资源的本地化

除外字符串资源,其它资源的本地化方式不需设置x:Uid,只需要建立针对许语言的目结构以及命名就好在XAML中直接引用。如项目蒙生出如下两摆放图片:
语言 5

在XAML中得以一直通过Images/Flag.png引用。路径中之”zh-CN”、”en-US”称为资源限定符,用于支持多示比例、UI
语言、高对比度设置等,具体可参看Load images and assets tailored for
scale, theme, high contrast, and
others

示例
1、演示本地化的主导采用
Localization/LocalizationDemo.xaml

2.5 在代码里拜访资源

以代码中走访资源的代码如下:

var resourceLoader = ResourceLoader.GetForCurrentView();
var currentLanguage = resourceLoader.GetString("CurrentLanguage");
resourceLoader = ResourceLoader.GetForCurrentView("OtherResources");
var message = resourceLoader.GetString("Message");

地方的代码中,currentLanguage从默认的资源文件Resources.resw中取得,resourceLoader
无需指定资源文件的名称;而message
则由OtherResources.resw获取,resourceLoader 需要指定资源文件的名号。

如若要运用另外类库中之资源,代码如下:

resourceLoader = ResourceLoader.GetForCurrentView("LocalizationDemoUwp.ResourceLibrary/Resources");
currentLanguage = resourceLoader.GetString("CurrentLanguage");

尽管如此语法简单,但可以看最深之题目是资源的名没有智能感知和左提示,这样用资源充分易失误。

语言 6

若是达到图所示,对错的资源名称,ReSharper会有误提示,不过这种布局ResourceLoader的道都于记为Deprecated并提醒用GetForCurrentView获取ResourceLoader,而下GetForCurrentView的情下ReSharper又无不当提示。不亮堂ReSharper什么时候才能够支持在GetForCurrentView的不二法门下显得错误提示(我设置的ReSharper已是行的2017.2)。

<Page
    x:Class="Windows10.Localization.LocalizationDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Localization"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <Grid.Resources>
            <ResourceDictionary>
                <local:LocalizedStrings x:Key="Localized"/>
            </ResourceDictionary>
        </Grid.Resources>

        <StackPanel Margin="10 0 10 10">

            <TextBlock>
                <Run>本地化资源文件,以下举例说明:</Run>
                <LineBreak />
                <Run>1、在 en 目录下的是英文资源文件,在 zh-hans 目录下的是简体中文(zh 代表中文,hans 代表简体中文)资源文件(关于限定符的详细说明请参见 /Resource/Qualifiers/)</Run>
                <LineBreak />
                <Run>2、Resources.lang-en.resw 代表英文资源文件,Resources.lang-zh-hans.resw 代表简体中文资源文件(关于限定符的详细说明请参见 /Resource/Qualifiers/)</Run>
                <LineBreak />
                <Run>3、Package.appxmanifest 中引用的字符串也支持本地化,引用方式:ms-resource:Hello 或 ms-resource:///Resources/Hello</Run>
                <LineBreak />
                <Run>4、Tile 和 Toast 中引用的字符串也支持本地化,引用方式:ms-resource:Hello 或 ms-resource:///Resources/Hello</Run>
                <LineBreak />
                <Run>5、当无法找到某语言对应的资源时,系统会自动使用 Package.appxmanifest 中设置的默认语言所对应的资源</Run>
            </TextBlock>

            <!--
                通过 x:Uid 本地化控件的各个属性,请参看资源文件中的 HelloTextBlock.FontSize 和 HelloTextBlock.Text
            -->
            <TextBlock x:Uid="HelloTextBlock" Margin="5" />

            <!--
                图片的本地化
            -->
            <Image Source="/Localization/Logo.png" Width="200" Height="100" Margin="5" HorizontalAlignment="Left" />

            <!--
                code - behind 方式获取本地化资源
            -->
            <TextBlock x:Name="lblMsg1" Margin="5" />

            <!--
                code - behind 方式获取本地化资源
            -->
            <TextBlock x:Name="lblMsg2" Margin="5" />

            <!--
                code - behind 方式获取本地化资源
            -->
            <TextBlock x:Name="lblMsg3" Margin="5" />

            <!--
                code - behind 方式获取本地化资源
            -->
            <TextBlock x:Name="lblMsg4" Margin="5" />

            <!--
                code - behind 方式获取本地化资源
            -->
            <TextBlock x:Name="lblMsg5" Margin="5" />

            <!--
                绑定本地化资源
            -->
            <TextBlock x:Name="lblMsg6" Margin="5" Text="{Binding [Hello], Source={StaticResource Localized}}" />

        </StackPanel>
    </Grid>
</Page>

2.6 存在的题目

夫本地化方案则简易,但自己觉得格外不便用,因为这方案有许多题目。

第一是规划时支持,对本地化来说,设计时支持重点含有3局部:

  • 以编写XAML时方可取资源的智能感知
  • 起完全的规划视图
  • 于不同语言中切换

第一接触,没有,而且写错属性名称还免会见以编译时报错,而是用最严寒的方法呈现:运行时倒。

仲接触,在Fall Creators Update
(16299)以前,没有,设计视图一片空白。也堪管写一些情(如TextBox x:Uid="UsernameTextBox" Header="(here is header)")以辅助设计。但每当XAML中写的其他内容还或吃资源文件覆盖,无论是公事还是大小、对齐方式或外具有属性对XAML的编者来说都是免可控的,不交骨子里运行时从不清楚UI的尾声效果,这便死考验本地化人员及测试人员。在Fall
Creators
Update以后终于得于规划视图看到本地化的效力,这不得不说是巨大的上进。

老三碰,目前来拘禁开不至。

除此以外,资源管理吗是单非常麻烦的题目。同一个字符串,如果如对应TextBlock.Text、ContentControl.Content、TextBox.Header,这样便用三个资源,造成了冗余,而大气之冗余最终见面促成错误。

如上所述,这个本地化方案来广大题目,虽然是方案是微软援引的。既然是微软引进的,应该是支撑太好的,也许是自之用法不对?

属下去当这方案的根底及召开来改动,希望可以为本地化更好用。

Localization/LocalizationDemo.xaml.cs

3. 动态切换语言

勿是自我顶执着动态切换语言,是测试员真的好这意义,因为不用还开应用就是可测试到所有语言的UI。

UWP提供了ApplicationLanguages.PrimaryLanguageOverride性能用于转移语言首选项,即好转使用之言语,用法如下:

Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "zh-CN";

是变更是永久的,但不见面指向当前UI及一些网组件生效,只见面影响以后创立的UI元素。更改ApplicationLanguages.PrimaryLanguageOverride,会异步地接触ResourceContext.QualifierValues的MapChanged事件,可以监听者波并更新UI。这样尽管足以实现简单的动态切换语言功能。

DynamicResources.cs

public class DynamicResources : INotifyPropertyChanged
{
    public DynamicResources()
    {
        _defaultContextForCurrentView = ResourceContext.GetForCurrentView();

        _defaultContextForCurrentView.QualifierValues.MapChanged += async (s, m) =>
        {
            await MainPage.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                OnPropertyChanged("");
            });
        };
    }

    private ResourceContext _defaultContextForCurrentView;

    public string Main
    {
        get { return ResourceManager.Current.MainResourceMap.GetValue("DynamicResources/Main", _defaultContextForCurrentView).ValueAsString; }
    }

    public string Settings
    {

        get { return ResourceManager.Current.MainResourceMap.GetValue("DynamicResources/Settings", _defaultContextForCurrentView).ValueAsString; }
    }

    public string RestartNote
    {
        get { return ResourceManager.Current.MainResourceMap.GetValue("DynamicResources/RestartNote", _defaultContextForCurrentView).ValueAsString; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

SettingView.xaml

<Page.Resources>
    <local:DynamicResources x:Key="DynamicResources"/>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <ListView x:Name="LanguageListView" Margin="10">
            <ListViewItem Tag="zh-Hans-CN" Content="中文"/>
            <ListViewItem Tag="en-US" Content="English"/>
        </ListView>
        <TextBlock x:Name="NoteElement" Foreground="#FFF99F00" Margin="20,10" Visibility="Collapsed"
                   Text="{Binding RestartNote,Source={StaticResource DynamicResources}}"
                   />
    </StackPanel>
</Grid>

SettingView.xaml.cs

private async void OnLanguageListViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var item = LanguageListView.SelectedItem as ListViewItem;
    if (item == null)
        return;

    ApplicationLanguages.PrimaryLanguageOverride = item.Tag as string;
    _hasChangedLanguage = true;
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, ShowNoteElement);
}

private void ShowNoteElement()
{
    NoteElement.Visibility = Visibility.Visible;
    var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
    appView.Title = (LanguageListView.SelectedItem as ListViewItem)?.Content as string;
}

语言 7

惟有在安装页面和菜单这些当切换语言时无会见另行加载的UI上利用Binding,其它地方不换,这样概括的动态切换语言就是实现了。运行结果使齐,可以看出TextBox右键菜单随不切换语言,需要还开动。

UWP默认只安装计算机对应之言语,这样可以节约安装空间,但影响至动态切换语言的效果,要缓解者题材可以参见以下内容(我从没说明了):[localization

  • How to always install all localized resources in Windows Store UWP app
  • Stack
    Overflow](https://stackoverflow.com/questions/40957295/how-to-always-install-all-localized-resources-in-windows-store-uwp-app)

  • 得到完全的设计视图


在Fall Creators
Update以前为了赢得设计时视图可以运用索引器。很少生机遇以C#备受之所以到索引器,XAML中也酷少用到Binding到字符串索引的语法,就是立片只功能在本地化中援了异常忙。

public class ResourcesStrings
{
    public string this[string key]
    {
        get
        {
            return ResourceLoader.GetForViewIndependentUse().GetString(key);
        }
    }
}

<Page.Resources>
    <local:ResourcesStrings x:Key="S"/>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="{Binding Source={StaticResource S},Path=[MainTitle]}" />
</Grid>

语言 8

只需要这样勾画就可以得到完全的筹划时拟,可是还是没有解决智能感知与左提示这有限单问题。

以是方案及也可是略地落实动态切换语言。

public class ApplicationResources : INotifyPropertyChanged
{
    public ApplicationResources()
    {
        DynamicResources = new DynamicResourcesStrings();
        Resources = new ResourcesStrings();
        Current = this;
    }

    public static ApplicationResources Current { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public DynamicResourcesStrings DynamicResources { get; }

    public ResourcesStrings Resources { get; }

    public string Language
    {
        get
        {
            return ApplicationLanguages.PrimaryLanguageOverride;
        }
        set
        {

            if (ApplicationLanguages.PrimaryLanguageOverride == value)
                return;

            ApplicationLanguages.PrimaryLanguageOverride = value;
            if (MainPage.Current != null )
                MainPage.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { OnPropertyChanged(""); });
        }
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

<ListViewItem Content="{Binding Source={StaticResource R},Path=DynamicResources[Main]}"/>

非理解为什么,在VisualStudio上间或没有办法取设计时视图,所有文字都展示为”Item”。

/*
 * 演示本地化的基本应用
 * 
 * 
 * 注:建议使用多语言应用工具包 https://developer.microsoft.com/zh-cn/windows/develop/multilingual-app-toolkit
 */

using System;
using System.Resources;
using Windows.ApplicationModel.Resources;
using Windows.ApplicationModel.Resources.Core;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Windows10.Localization
{
    public sealed partial class LocalizationDemo : Page
    {
        public LocalizationDemo()
        {
            this.InitializeComponent(); 
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            /*
             * ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse(); - 获取默认的 ResourceLoader(Resources.resw 中的资源)
             * ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse("MyResources"); - 获取指定的 ResourceLoader(MyResources.resw 中的资源)
             * ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse("ClassLibrary/MyResources"); - 获取指定类库的指定的 ResourceLoader(ClassLibrary 类库中的 MyResources.resw 中的资源)
             * resourceLoader.GetString(), resourceLoader.GetStringForUri() - 通过资源标识,获取当前语言环境的指定的资源
             * 
             * GetForCurrentView() 和 GetForViewIndependentUse() 的区别如下:
             * 1、GetForCurrentView() - 在 UI 线程上执行
             * 2、GetForViewIndependentUse() - 在非 UI 线程上执行(注:Independent 这个词在 uwp 中就时非 UI 线程的意思,比如 Independent Animation 就是不依赖 UI 线程的)
             */

            // 获取默认的 ResourceLoader(即 Resources.resw 中的资源)
            ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse();

            // 通过资源标识,获取当前语言环境的指定的资源(资源名:Hello)
            lblMsg1.Text = resourceLoader.GetString("Hello");

            // 通过资源标识,获取当前语言环境的指定的资源(资源名:HelloTextBlock.Text)
            lblMsg2.Text = resourceLoader.GetString("HelloTextBlock/Text");

            // 通过资源标识,获取当前语言环境的指定的资源(资源名:Hello)
            lblMsg3.Text = resourceLoader.GetStringForUri(new Uri("ms-resource:///Resources/Hello"));

            // 通过资源标识,获取当前语言环境的指定的资源(资源名:HelloTextBlock.Text)
            lblMsg4.Text = resourceLoader.GetStringForUri(new Uri("ms-resource:///Resources/HelloTextBlock/Text"));

            // 获取当前语言环境的指定的资源的另一种方式
            lblMsg5.Text = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap.GetValue("Resources/Hello", ResourceContext.GetForCurrentView()).ValueAsString;
        }
    }

    // 用于演示如何绑定本地化资源
    public class LocalizedStrings
    {
        public string this[string key]
        {
            get
            {
                return ResourceLoader.GetForCurrentView().GetString(key);
            }
        }
    }
}

5. 施用resx资源文件

既然UWP是XAML大家族的一份子,那么该为得以应用resx资源文件贯彻本地化,毕竟生成resx对许代码的是PublicResXFileCodeGenerator,而休是UWP本身。

  1. 开辟“添加新项”对话框,选中“资源文件(.resw)”,在“名称”文本框中将文件名称改吗“Labels.resx”,点击“添加”。
  2. 于“解决方案资源管理器”选中“Labels.resx”,邮件打开“属性”视图,“生成操作”选择“嵌入的资源”。
  3. 拿“Labels.resx”复制为“Labels.zh-CN.resx”,打开“Labels.zh-CN.resx”,“访问修饰符”改吗“无代码生成”。
  4. 以“AssemblyInfo.cs”添加如下代码:

    [assembly: NeutralResourcesLanguage("en-US")]
    

然虽可以以UWP中动用resx资源文件了。实现本地化的代码和达到同样首文章被介绍的WPF本地化方案差不多。

public class ApplicationResources : INotifyPropertyChanged
{
    public static ApplicationResources Current { get; private set; }

    public ApplicationResources()
    {
        Labels = new Labels();
        if (string.IsNullOrWhiteSpace(ApplicationLanguages.PrimaryLanguageOverride) == false)
            Language = ApplicationLanguages.PrimaryLanguageOverride;
        else
            Language = Windows.System.UserProfile.GlobalizationPreferences.Languages.FirstOrDefault();

        Current = this;
    }

    public Labels Labels { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }

    private string _language;

    /// <summary>
    /// 获取或设置 Language 的值
    /// </summary>
    public string Language
    {
        get { return _language; }
        set
        {
            if (_language == value)
                return;

            _language = value;
            Labels.Culture = new System.Globalization.CultureInfo(_language);
            ApplicationLanguages.PrimaryLanguageOverride = _language;
            OnPropertyChanged("");
        }
    }
}

动体验以及WPF中之resx本地化方案差不多,设计时支持几乎无所不包,包括智能感知与错提示,不过还是没有办法化解系统组件中之本地化问题(如TextBox右键菜单)。另外,编译时会报错:带有输出类型“appcontainerexe”的类型未支持生成操作“EmbeddedResource”。解决方案是休以UWP应用类遭到补充加resx资源文件,而在类库中上加resx资源文件,这样并错还无报了。

不理解Xamarin.Forms是未是吧堪这么实现,毕竟她吧是XAML大家族的如出一辙各类。

2、演示与“改变语言”相关的有些运用
Localization/Language.xaml

6. 结语

研讨了这般多resw资源文件之方案,结果或者resx资源文件用得无比顺手,毕竟这方案我曾为此了不少年(在silverlight中不得不用是方案)。具体应用谁方案不同。

得强调的凡resx并无克全代表resw方案,很多时分用混合使用,例如使用之Display
Name可以使resw轻松实现本地化:
语言 9

本地化的主题仍发生好多内容,这首稿子就打算介绍入门知识,更深切的学识可以参考下面给出的链接。

<Page
    x:Class="Windows10.Localization.Language"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Localization"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Name="root" Margin="10 0 10 10">

            <!--
                通过此种方式获取本地化资源时,如果在页面加载后修改了语言首选项的话是不会立即有效果的,需要重新加载页面才行(懒的写了,要看效果的话就先返回,然后再进来就好)
            -->
            <TextBlock x:Uid="HelloTextBlock" Margin="5" />

            <ComboBox Name="cmbLanguage" Width="800" HorizontalAlignment="Left" Margin="5" />

            <Button Name="btnGetEnglish" Content="获取英文资源" Margin="5" Click="btnGetEnglish_Click" />
            <Button Name="btnGetChinese" Content="获取简体中文资源" Margin="5" Click="btnGetChinese_Click" />

            <TextBlock Name="lblMsg" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

7. 参考

Guidelines for globalization – UWP app developer Microsoft
Docs
Localize strings in your UI and app package manifest – UWP app
developer Microsoft
Docs
Load images and assets tailored for scale, theme, high contrast, and
others – UWP app developer Microsoft
Docs
迅速入门:翻译 UI 资源
(XAML)
c# – UWP Resource file for languages is not deployed correctly – Stack
Overflow
localization – How to always install all localized resources in Windows
Store UWP app – Stack
Overflow
Win10 UWP 开发系列:使用多语言工具包让应用支撑多语言 – yan_xiaodi –
博客园
Windows 10 Apps Designing for Global
Customers

Localization/Language.xaml.cs

8. 源码

GitHub –
LocalizationDemo

/*
 * 演示与“改变语言”相关的一些应用
 * 
 * 1、演示如何改变当前的语言环境
 * 2、演示如何监测当前语言环境发生的变化
 * 3、演示如何获取指定语言环境下的资源
 */

using System;
using System.Collections.Generic;
using System.Text;
using Windows.ApplicationModel.Resources;
using Windows.ApplicationModel.Resources.Core;
using Windows.Globalization;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows10.Localization
{
    public sealed partial class Language : Page
    {
        public Language()
        {
            this.InitializeComponent();

            this.Loaded += Language_Loaded;
        }

        void Language_Loaded(object sender, RoutedEventArgs e)
        {
            // 获取当前的语言
            string currentLanguage;
            ResourceContext.GetForCurrentView().QualifierValues.TryGetValue("Language", out currentLanguage);
            lblMsg.Text = "current language: " + currentLanguage;
            lblMsg.Text += Environment.NewLine;


            // ApplicationLanguages.ManifestLanguages - 遍历 Package.appxmanifest 中的语言列表
            foreach (string strLang in ApplicationLanguages.ManifestLanguages)
            {
                // 关于 Language 的说明详见 GlobalizationDemo.xaml
                var lang = new Windows.Globalization.Language(strLang);
                cmbLanguage.Items.Add(string.Format("DisplayName:{0}, NativeName:{1}, LanguageTag:{2}, Script:{3}",
                    lang.DisplayName, lang.NativeName, lang.LanguageTag, lang.Script));
            }
            cmbLanguage.SelectionChanged += cmbLanguage_SelectionChanged;


            // 获取当前语言环境的指定资源(更多用法请参见 LocalizationDemo.xaml)
            lblMsg.Text += ResourceLoader.GetForViewIndependentUse().GetString("Hello");


            // 当前语言环境发生改变时所触发的事件(通过 API 更改或者通过“电脑设置 -> 常规 -> 语言首选项”更改都会触发此事件)
            // 注:当通过 API(ApplicationLanguages.PrimaryLanguageOverride)修改语言环境时,如果监听了 MapChanged 事件的话,则有很大的几率会导致崩溃,本例就是这样,原因未知
            ResourceContext.GetForCurrentView().QualifierValues.MapChanged += async (s, m) =>
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += ResourceLoader.GetForViewIndependentUse().GetString("Hello");
                });
            };
        }

        private void cmbLanguage_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // ApplicationLanguages.PrimaryLanguageOverride - 设置或获取首选语言(BCP-47 语言标记)
            if (cmbLanguage.SelectedValue.ToString().ToLower().Contains("en-us"))
                ApplicationLanguages.PrimaryLanguageOverride = "en-US";
            else if (cmbLanguage.SelectedValue.ToString().ToLower().Contains("zh-hans"))
                ApplicationLanguages.PrimaryLanguageOverride = "zh-Hans-CN";

            StringBuilder sb = new StringBuilder();
            // ApplicationLanguages.Languages - 按语言级别排序,获取语言列表
            foreach (string item in ApplicationLanguages.Languages)
            {
                sb.Append(item);
                sb.Append(",");
            }

            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "ApplicationLanguages.Languages: " + sb.ToString();
        }

        private void btnGetEnglish_Click(object sender, RoutedEventArgs e)
        {
            // 指定 ResourceContext 为 en-US 语言环境
            ResourceContext resourceContext = new ResourceContext();
            resourceContext.Languages = new List<string>() { "en-US" };

            // 获取 en-US 语言环境下的 Resources 映射
            ResourceMap resourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
            lblMsg.Text += Environment.NewLine;
            // 获取指定的语言环境下的指定标识的资源
            lblMsg.Text += "英语的 Hello: " + resourceMap.GetValue("Hello", resourceContext).ValueAsString;
        }

        private void btnGetChinese_Click(object sender, RoutedEventArgs e)
        {
            // 指定 ResourceContext 为 zh-Hans-CN 语言环境
            ResourceContext resourceContext = new ResourceContext();
            resourceContext.Languages = new List<string>() { "zh-Hans-CN" };

            // 获取 zh-Hans 语言环境下的 Resources 映射
            ResourceMap resourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
            lblMsg.Text += Environment.NewLine;
            // 获取指定的语言环境下的指定标识的资源
            lblMsg.Text += "简体中文的 Hello: " + resourceMap.GetValue("Hello", resourceContext).ValueAsString;
        }
    }
}

OK
[源码下载]

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图