语言背水首次大战 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”设置为暗许语言,再一次运营应用可知到运转在土耳其共和国(The Republic of Turkey)语环境下的作用。
语言 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

示例
① 、演示本地化的为主采取
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

/*
 * 演示本地化的基本应用
 * 
 * 
 * 注:建议使用多语言应用工具包 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);
            }
        }
    }
}

4. 得到完整的宏图视图

在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”。

二 、演示与“改变语言”相关的局地施用
Localization/Language.xaml

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我们族的一员。

<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>

6. 结语

研讨了那样多resw财富文件的方案,结果依旧resx财富文件用得最顺手,终归这些方案小编早已用了重重年(在silverlight中不得不用那些方案)。具体行使哪个方案不一样。

急需强调的是resx并无法完全代替resw方案,很多时候须求混合使用,例如利用的Display
Name能够应用resw轻松实现本地化:
语言 9

本地化的主旨仍有无数剧情,那篇小说只打算介绍入门知识,更透彻的学识能够参见下边给出的链接。

Localization/Language.xaml.cs

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

/*
 * 演示与“改变语言”相关的一些应用
 * 
 * 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;
        }
    }
}

8. 源码

GitHub –
LocalizationDemo

OK
[源码下载]

发表评论

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

网站地图xml地图