那就招致本地化的实现方案完全两样,当先56%WPF程序都未曾大到要求怀念安装包大小澳门皇冠官网app

1. 前言

WPF的当地化是个很布满的功力,作者做过的WPF程序半数以上都贯彻了当地化(不管最后有未有利用)。经常本地化有以下几点须要:

  • 在前后相继运维时依据CultureInfo.CurrentUICulture或配备项展现对应语言的UI。
  • 在程序运维时得以动态切换UI语言(没有必要重启程序)。
  • 创设对应不相同语言的安装包。
  • 由此下载语言包达成种种语言的本地化。

其间唯有首先点是必备的。
其次点最佳也足以实现,相当多时候切换语言只为了看看有个别专门的职业术语在克罗地亚共和国(Republic of Croatia)语中的原著是什么,也许暂且打字与印刷个意国语报表,日常利用恐怕用粤语,顾客不想为了那点重启程序。
其三点和第四点即便很广阔,但本身一贯没达成过,毕竟文字财富(不时还应该有微量图纸)占用的半空中不会太多,抢先54%WPF程序都没有大到须要思考安装包大小,全数语言的财富总体打包进二个安装包就足以了。

WPF本地化才干很干练,也可能有三种方案,微软在MSDN给出了详尽的介绍WPF
整个世界化和本地化概述
.aspx),还会有大器晚成份古老的文书档案WPF
Localization
Guidance
,整整66页,里面详细介绍了种种WPF本地化的编写制定。

本文只介绍二种完毕上述第1、2点要求的方案。

1. 前言

上大器晚成篇小说介绍了各个WPF本地化的入门知识,这篇文章介绍UWP当地化的入门知识。

2. 行使财富词典

2. 施用resw能源文件贯彻本地化

在原先的XAML平台,resx能源文件是大器晚成种很方便的本地化方案,但在UWP中微软又重新推荐x:Uid方案,暗中认可的财富文件也变成resw财富文件。纵然后缀名只差了二个假名,但使用办法完全两样。最根本的分别是resw能源文件不会创设对应的Designer.cs类,那就招致本地化的达成方案完全两样。

澳门皇冠官网app 1

2.1 基本原理

对WPF开辟者来讲,财富词典断定不会素不相识。可是在能源词典里选择string恐怕超少。

<Window x:Class="LocalizationDemoWpf.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LocalizationDemoWpf"
        mc:Ignorable="d" 
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <system:String x:Key="Chinese">中文</system:String>
    </Window.Resources>
    <Grid>
        <TextBlock Text="{DynamicResource Chinese}"/>
    </Grid>
</Window>

如以上代码所示,在XAML中定义string财富必要先引进xmlns:system="clr-namespace:System;assembly=mscorlib"命名空间,之后再利用DynamicResource引用这些财富。不要选择StaticResource,这样无法做到动态切换语言。

要选拔财富词典完毕本地化,须求先成立所需语言的xaml,小编在DEMO中开创了en-us.xaml和zh-cn.xaml八个能源词典,里面包车型地铁带有的能源布局相符(指数量和Key同样):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:system="clr-namespace:System;assembly=mscorlib"
                    xmlns:local="clr-namespace:LocalizationDemoWpf">
    <system:String x:Key="SwitchLanguage">切换语言</system:String>
    <system:String x:Key="Chinese">中文</system:String>
    <system:String x:Key="English">英文</system:String>
    <system:String x:Key="Username">用户名</system:String>
    <system:String x:Key="Sex">性别</system:String>
    <system:String x:Key="Address">地址</system:String>
    <SolidColorBrush x:Key="Background" Color="#88FF0000"/>
</ResourceDictionary>

在前后相继运维时依照CultureInfo.CurrentUICulture或计划项接纳相应的财富词典,使用MergedDictionaries的章程加载到程序的能源聚聚焦:

var culture = ReadCultureFromConfig();
var cultureInfo = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;


ResourceDictionary dictionary = new ResourceDictionary { Source = new Uri($@"Resources\{culture}.xaml", UriKind.RelativeOrAbsolute) };
Application.Current.Resources.MergedDictionaries[0] = dictionary;

那样板地化的功效就到位了。

2.1 在XAML中贯彻当地化

在XAML中落到实处当地化的经过很简短。首先在品种中新建”strings”文件夹,在”strings”文夹下开创”en-US”和”zh-CN”文件夹,并在三个文本夹中分头增进”Resources.resw”资源文件。最后目录结构如下:
澳门皇冠官网app 2

在zh-CN\Resources.resw和en-US\Resources.resw增添多少个新能源,分别是UsernameTextBox.Width和UsernameTextBox.Header:
澳门皇冠官网app 3

在XAML中增添一个TextBox,设置x:Uid为UsernameTextBox,x:Uid将XAML成分和能源文件中的能源拓宽关联:

<TextBox x:Uid="UsernameTextBox"/>

运作后就可以看出UsernameTextBox的Header设置为”客商名”,Width为100。

在“设置\区域和语言”中校”English”设置为暗许语言,再度运营应用可看出运维在斯洛伐克(Slovak)语遭受下的作用。
澳门皇冠官网app 4

那般主旨的本地化成效就兑现了。这种当地化情势犹如下优点:

  • 简简单单高效,轻便上手
  • 语法轻易,无需Binding等知识
  • 能够钦点任意属性进行业地化
  • 支持CLR属性

除了,上豆蔻梢头篇作品提到的ResXManager也支撑Resw财富文件,仍可以运用多语言应用工具包对能源文件进行拘系,天涯论坛的那篇著作页对那几个工具实行了详尽介绍:
Win10 UWP
开荒体系:使用多语言工具包让应用支撑多语言

抑或参谋那个摄像:
Windows 10 Apps Designing for Global
Customers

2.2 动态切换语言

实际上上述方案已兑现了动态切换语言。
XAML能源的引用原则是就近原则,那个周边不止指VisualTree上的左右,还指时间上的前后。后加多进财富词典的财富将替换从前的同名财富。使用DynamicResource实际不是StaticResource,正是为了在资源被沟通时能实时退换UI的来得。

2.2 关联到其余财富文件

UI成分暗许与Resources.resw进行关联,如若急需和其余能源文件涉及,能够增加能源文件的路子。如须要与/OtherResources.resw中的财富事关,x:Uid的语法如下:

x:Uid="/OtherResources/AddressTextBox"

2.3 设计时援助

VisualStudio的XAML设计时扶植对开拓WPF程序至关心重视要,对本地化来讲,设计时协理至关心爱戴要含有3有的:

  • 在编写XAML时能够获得能源的智能感知
  • 有全体的筹算视图
  • 在分裂语言之间切换

使用能源词典实现本地化,只需在App.xaml中集合对应的能源词典就能够获取完全的安排时帮忙。

<Application x:Class="LocalizationDemoWpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:LocalizationDemoWpf"
             xmlns:resource="clr-namespace:LocalizationDemoWpf.Resource;assembly=LocalizationDemoWpf.Resource"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/zh-cn.xaml"/>
                <!--<ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/en-us.xaml"/>-->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

澳门皇冠官网app 5

这段XAML只是为着升高规划时体验,未有也能因此编写翻译。

2.3 附加属性的本地化

对系统提供的叠合属性,财富的称谓语法如下:

UsernameTextBox.Grid.Row

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

ShowMessageButton.[using:LocalizationDemoUwp]ButtonEx.Content

离奇的是,就像此直白运维应用会报错。唯有利用这些财富的UI成分已经有这几个附加属性的值技巧健康运行,轻便的话就是要求随意为这么些附加属性设置四个值:

<Button Margin="5" x:Uid="ShowMessageButton"  local:ButtonEx.Content="ssssss"/>

2.4 在代码里拜候财富

在代码中访谈财富相比繁重,需求驾驭财富的名号,何况尚未智能感知,要是财富词典由第三方类库提供就能够更麻烦。

var message = TryFindResource("SwitchLanguage") as string;
if (string.IsNullOrWhiteSpace(message) == false)
    MessageBox.Show(message);

2.4 此外财富的本地化

除去字符串财富,别的财富的当地化情势无需设置x:Uid,只需求树立对应语言的目录结构及命名就足以在XAML中央职能部门接引用。如项目中好似下两张图片:
澳门皇冠官网app 6

在XAML中得以直接通过Images/Flag.png引用。路线中的”zh-CN”、”en-US”称为财富约束符,用于帮忙两种显得比例、UI
语言、高比较度设置等,具体可参看Load images and assets tailored for
scale, theme, high contrast, and
others

2.5 在代码里替换财富

private void OnReplaceString(object sender, RoutedEventArgs e)
{
    _totalReplace++;
    string content = "Replace " + _totalReplace;
    Resources["StringToReplace"] = content;
}

如上所示,在代码中替换能源拾叁分轻易易行,可是这种简易也拉动了能源不可控的难题。

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");

虽说语法轻松,但能够看出最大的主题素材是财富的称呼未有智能感知和谬误提醒,那样使用财富比较轻松出错。

澳门皇冠官网app 7

如上海体育地方所示,对错误的财富名称,ReSharper会有荒诞提醒,可是这种结构ResourceLoader的法子已经被标识为Deprecated并提示使用GetForCurrentView获取ResourceLoader,而利用GetForCurrentView的图景下Re夏普er又还对的误提醒。不明了ReSharper曾几何时才具援救在GetForCurrentView的章程下显得错误提醒(小编设置的Re夏普er已经是最新的2017.2)。

2.6 在程序集以内共享能源

下边有提过,在收获第三方类库中有个别能源充足劳动,不仅仅如此,连获得第三方类库中的财富词典名称都拾分麻烦。作者提议在类库中定义如下的类,能够给开辟者提供部分便利:

public static class Resources
{
    public static Uri EnglishResourceUri { get; } =
        new Uri("/LocalizationDemoWpf.Resource;component/Resource.en-us.xaml", UriKind.RelativeOrAbsolute);

    public static Uri ChineseResourceUri { get; } =
        new Uri("/LocalizationDemoWpf.Resource;component/Resource.zh-cn.xaml", UriKind.RelativeOrAbsolute);
}

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,那样就要求两个财富,变成了冗余,而大气的冗余最后会招致错误。

如上所述,那个本地化方案有许多标题,即使这几个方案是微软引入的。既然是微软推举的,应该是支撑最棒的,只怕是自个儿的用法不对?

接下去在此个方案的底子上做些改变,希望得以让本地化更加好用。

2.7 总结

财富词典是促花费地化的大器晚成种很布满的办法,它犹如下优点:

  • 简短易用,并且便于精通。
  • XAML语法简单。
  • 能源得以是除string以外的等级次序,如SolidColorBrush。

但这种方式的症结也不菲:

  • 麻烦管理,大器晚成旦能源过多,重名、互相覆盖、智能感知列表过长等题材将十分的大地震慑开采,就连有限支撑分裂语言间资源词典里的财富数量相近都很麻烦。
  • 在前后相继集以内难以分享,引用异常粗略,但出于并未有智能感知将很难使用,而且不一样程序集以内的财富同名更难以追踪。

除此以外,在动态切换语言上还留存有的标题。上边这段XAML就无法达成动态切换语言:

<DataGrid Grid.Row="1" Margin="5">
    <DataGrid.Columns>
        <DataGridTextColumn Header="{DynamicResource Username}"/>
        <DataGridTextColumn Header="{DynamicResource Sex}"/>
        <DataGridTextColumn Header="{DynamicResource Address}" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

在DataGridColumn的Header上做动态切换语言,需求写成DataTemplate的艺术:

<DataGrid Grid.Row="2" Margin="5">
    <DataGrid.Columns>
        <DataGridTextColumn >
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Username}"/
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        <DataGridTextColumn >
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Sex}"/>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        <DataGridTextColumn Width="*">
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Address}"/>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

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

澳门皇冠官网app 8

只在设置页面及菜单这一个在切换语言时不会再也加载的UI上采纳Binding,此外地方不改变,那样轻巧的动态切换语言就兑现了。运营结果如上,能够见到TextBox右键菜单仍未切换语言,须要重新启航。

UWP暗许只安装Computer对应的言语,那样能够省去安装空间,但耳闻则诵到动态切换语言的遵守,要消除那么些难题得以参见以下内容(小编从不认证过):[localization

3. 行使Resx能源文件

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>

澳门皇冠官网app 9

只需求这样写就能够博得完整的统筹时策动,不过照旧尚未消除智能感知和错误提醒那八个难题。

在这里个方案上也可归纳地落到实处动态切换语言。

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

3.1 基本原理

比起财富词典,笔者更爱好使用Resx能源文件,但是这种办德语法复杂一些,并且也会有众多小意思。
在VisualStudio中开创后缀名叫resx的能源文件并张开,可在以下UI编辑财富文件的值(将探望修饰符改为public用起来方便些):
澳门皇冠官网app 10

在更正财富文件的值后PublicResXFileCodeGenerator将电动成立对应的类并为每贰个键值加多如下代码:

/// <summary>
///   查找类似 Address 的本地化字符串。
/// </summary>
public static string Address {
    get {
        return ResourceManager.GetString("Address", resourceCulture);
    }
}

接下来将以此财富文件复制粘贴大器晚成份,将名称改为“原名+.+对应的语言+.resx”的格式,并且将中间的值翻译成对应语言如下:
澳门皇冠官网app 11

在UI上使用x:Static绑定到相应的财富:

<DataGridTextColumn Header="{x:Static local:Labels.Username}"/>

那般主旨的本地化就产生了。超级多控件库都以应用这种艺术做本地化。除了字符串,resx能源文件还支持除字符串以外的能源,如图片、音频等。
澳门皇冠官网app 12

唯独那么些方案只兑现了最宗旨的当地化,并且最大的主题素材是只扶助直接行使字符串,不扶助TypeConverter,以至也不帮衬除字符串以外的别的XAML内置类型.aspx)(即Boolea,Char,Decimal,Single,Double,Int16,Int32,Int64,提姆eSpan,Uri,Byte,Array等品种)。比如利用Label.resx中名称为Background值为
#880000FF 的字符串为Grid.Background达成本地化:

Labels.designer.resx

/// <summary>
///   查找类似 #880000FF 的本地化字符串。
/// </summary>
public static string Background {
    get {
        return ResourceManager.GetString("Background", resourceCulture);
    }
}

MainWindow.xaml

<Grid  Background="{x:Static local:Labels.Background}"/>

运作时报错:ArgumentException:
“#88FF0000”不是性质“Background”的有效值。

那般财富文件的实用性大巨惠扣。当然,那个方案也不协理动态切换语言。

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我们族的黄金年代员。

3.2 动态切换语言

Silverlight.aspx)中已没有了x:Static的绑定情势,改为使用Binding达成本地化,那样即便语法复杂一些,但进一步实用。WPF当然也能够采取这种措施。

率先, 成立三个类包装能源文件生成的类(在这里个德姆o中是Labels):

public class ApplicationResources
{
    public ApplicationResources()
    {
        Labels = new Labels();
    }

    public Labels Labels { get; set; }
}

下一场在App.xaml旅长以此类作为能源丰盛到财富会集中,为了将来接收的语法轻松些,小编平日将Key获得相当的粗略:

<Application x:Class="LocalizationDemoWpfUsingResource.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:LocalizationDemoWpfUsingResource"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:ApplicationResources x:Key="R"  />
    </Application.Resources>
</Application>

最终在XAML中如此绑定:

<DataGridTextColumn Header="{Binding Labels.Username, Source={StaticResource R}}"/>

如此那般语法复杂一些,但也可以有过Dolly益:

  • 帮忙TypeConverter,那样就足以使用除String以外的其余项目。
  • 支撑Binding的别样功能,如IValueConverter。

麻烦的是,WPF就像不是很心爱这种措施,VisualStudio会提示这种不当,终归财富文件中的属性都以static属性,不是实例成员。幸运的是编写翻译一回这种不当提醒就能够秋风落叶。
澳门皇冠官网app 13

将调用方式改为Binding将来就能够达成动态切换语言了。由于UI通过Binding获取能源文件的剧情,能够由此INotifyPropertyChanged通告UI更新。将ApplicationResources
改造一下:

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

    public ApplicationResources()
    {
        Current = this;
        Labels = new Labels();
    }

    public Labels Labels { get; set; }



    public event PropertyChangedEventHandler PropertyChanged;

    public  void ChangeCulture(System.Globalization.CultureInfo cultureInfo)
    {
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Labels.Culture = cultureInfo;

        if (Current != null)
            Current.RaiseProoertyChanged();
    }

    public void RaiseProoertyChanged()
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
    }
}

今日得以轻易地切换语言了。

var culture = ReadCultureFromConfig();
var cultureInfo = new System.Globalization.CultureInfo(culture);
ApplicationResources.Current.ChangeCulture(cultureInfo);

6. 结语

研讨了这么多resw财富文件的方案,结果要么resx财富文件用得最顺手,毕竟那一个方案作者曾经用了成都百货成百上千年(在silverlight中只可以用这么些方案)。具体行使哪个方案不相同。

亟需强调的是resx并不能够一心代表resw方案,超多时候供给混合使用,比如利用的Display
Name能够动用resw轻便完成当地化:
澳门皇冠官网app 14

本地化的宗旨依然有数不清剧情,那篇小说只希图介绍入门知识,更通透到底的知识能够参照上面给出的链接。

3.3 设计时帮忙

兑现本地化的三个很麻烦的政工是什么样在两全视图见到各个语言下的功力。在选取能源词典的方案中是通过在App.xaml中联合对应的资源词典:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/zh-cn.xaml"/>
    <!--<ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/en-us.xaml"/>-->
</ResourceDictionary.MergedDictionaries>

在财富文件的方案中,须要在ApplicationResources中增加四日个性:

private string _language;

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

        _language = value;
        var cultureInfo = new CultureInfo(value);
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Labels.Culture = cultureInfo;

        RaiseProoertyChanged();
    }
}

其后在App.xaml中就能够通过更改那些天性来改换安马上的UI的言语,在VS2017中连编写翻译都无需就足以变动规划视图的语言。

<local:ApplicationResources x:Key="R"  Language="zh-CN"/>

澳门皇冠官网app 15

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

3.4 在代码里拜会财富

在代码里拜望财富文件的能源特别简单:

MessageBox.Show(Labels.SwitchLanguage);

8. 源码

GitHub –
LocalizationDemo

3.5 在代码里替换财富

财富文件要完成这一个需求就一些都欠风趣了,最少本人未以往在事实上中国人民解放军海军事工业程大学业作中做过。最大的难点是财富文件生成的类中的属性是静态属性,况且独有getter方法:

public static string StringToReplace {
    get {
        return ResourceManager.GetString("StringToReplace", resourceCulture);
    }
}

咱俩也能够创制贰个派生类,强行替换对应的性质:

public class ExtendLabels : Labels
{
    /// <summary>
    /// 获取或设置 StringToReplace 的值
    /// </summary>
    public new string StringToReplace { get; set; }
}

然后替换ApplicationResources中的Labels,并且触发PropertyChanged。也才那样会刷新全数UI上的字符串等财富,只为了替换一个字符能源代价有一点点大,幸好日常的话并不会太花费质量。

private void OnReplaceString(object sender, RoutedEventArgs e)
{
    _totalReplace++;
    string content = Labels.StringToReplace + " " + _totalReplace;
    if (_extendLabels == null)
        _extendLabels = new ExtendLabels();

    _extendLabels.StringToReplace = content;
    ApplicationResources.Current.Labels = _extendLabels;
    ApplicationResources.Current.RaiseProoertyChanged();
}

3.6 在程序集以内分享财富

只供给将财富文件的访谈修饰符改为public,没有必要任何操作就可以事半功倍地在前后相继集以内分享财富。
澳门皇冠官网app 16

3.7 管理能源文件

比起财富词典,能源文件还应该有两个超大的优势正是轻巧管理。德姆o中唯有二个名字Labels的财富文件,实际项目中可以按作用或模块分别创造相应的财富文件,解决了财富词典重名、互相覆盖、智能感知列表过长等难题。其余小编推荐使用VS的恢弘程序ResXManager管理全部能源文件。
澳门皇冠官网app 17

它能够在贰个UI里管理全数语言的能源文件,相当的大地方便人民群众了财富文件的施用。
澳门皇冠官网app 18

3.8 ReSharper支持

对Resx能源文件,ReSharper也提供了优良的扶助。

当要求为有些能源改进Key时,能够按“能源文件名称”+”.”+”Key”来全局替换,常常那样已经丰盛放心。ReSharper更上一层楼,它提供了重命名成效。假使要将Labels的财富English重名叫为Englishs,能够先在Labels.Designer.cs重命名,然后利用“Apply
rename refactoring”选项:
澳门皇冠官网app 19

那时候全数援引,满含XAML都已经选拔新的称号:
澳门皇冠官网app 20

可是最后仍需和睦出手在财富文件编辑器中期维改过Key。

除开,假使在XAML中接受了错误的Key,ReSharper也可能有荒谬提醒:
澳门皇冠官网app 21

在一些场面,ReShaper还可接纳“Move To Resource”效用:
澳门皇冠官网app 22
澳门皇冠官网app 23

3.9 总结

接受Resx能源文件贯彻本地化犹如下优点:

  • 能源管理有助于。
  • 轻巧在代码中运用。
  • 轻易在程序集以内分享。
  • 支撑TypeConverter,那样就足以动用除String以外的别的门类。
  • 支撑Binding的别样效用,如IValueConverter。
  • 包容性好,Silverlight及之后的XAML技能都能够应用。
  • 其三方工具支持。
  • 支撑图片、音频等财富。

症结如下:

  • XAML语法相对复杂。
  • 不能一贯动用于TypeConverter不支持的品种,举个例子LinearGradientBrush。

固然不可能直接辅助LinearGradientBrush,但亦非截然没有章程,只是复杂了成都百货上千,如分别对LinearGradientBrush的GradientStop做本地化:

<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="Black" Offset="0"/>
    <GradientStop Color="{Binding Source={StaticResource R},Path=Labels.Background}" Offset="1"/>
</LinearGradientBrush>

4. 结语

那篇小说只介绍了本地化的入门知识,其余还也许有好些个本地化的中央,如验证新闻中的本地化未有涉及。其它,当地化还是能够使用x:Uid情势或WPFLocalizeExtension等措施实现,这里就不详细介绍。
WPF
满世界化和本地化概述
.aspx)里有介绍一些本地化的最好做法,如UI上应该选取相对布局而非相对布局、字体选拔等,这里不再累赘。

内需注意的是上述二种方案都不适用于CL安德拉属性,这也是干什么本人一贯重申UIElement的性子最佳是依赖属性的原因之生机勃勃。

如有错漏请提议。

5. 参考

WPF
环球化和本地化概述
.aspx)
Silverlight
计划和本地化
澳门皇冠官网app,.aspx)
WPFLocalizationExtension
WPF Localization Guidance
XAML
Resources

CultureInfo
.aspx)
Supported
languages

6. 源码

LocalizationDemo

相关文章