WPF本地化进阶:大小写和复数形式的指定

在进行WPF项目开发时,本地化是一个不可忽视的重要环节。本篇文章将介绍如何在WPF项目中指定文本的大小写和复数形式,以满足不同语言环境下的显示需求。

在参与一个使用WPF进行开发的项目时,遇到了一个本地化的问题。项目中相同的文本在不同的地方被使用,但有时需要大写,有时不需要。通常情况下,资源的名称是以英文命名的。不幸的是,即使大小写不同,也不能为两个不同的资源使用相同的名称。有趣的是,大小写必须与资源名称匹配。为了解决这个问题,增强了原始代码,使其能够指定大小写作为属性。

后来,考虑将复数形式也加入到项目中。在应用程序中,已经有了一个进行复数形式转换的方法。考虑将这段代码加入,但后来发现了PluralizationServices类,它位于System.Data.Entity.Design命名空间中。尽管这个服务有一些限制,但可能需要使用不同的解决方案。

新代码

为了给现有项目添加这两个功能,只需要添加少量的代码。在派生的MarkupExtensionLocExtension中,需要添加两个属性,并为每个属性创建一个枚举:

public enum CaseEnum { None = 0, Upper, Lower } public enum PluralizationEnum { None = 0, Plural, Singular }

还需要将这两个属性添加到用作不同TargetProperty类型的基类的抽象LocalizedProperty类中。然后在LocExtension类的ProvideValue方法中,只需要将LocalizedProperty类的属性设置为与LocExtension类中的值相匹配即可。

接下来,只需要在LocalizedProperty类的GetValue方法中,根据需要修改生成的字符串,然后返回值(如果类型实际上是字符串):

internal object GetValue() { var localizedValue = GetLocalizedValue(); var converter = Property.Converter; if (converter != null) { localizedValue = converter.Convert(localizedValue, Property.GetValueType(), Property.ConverterParameter, Property.GetCulture()); } return AdjustForCase(AdjustForPluralization(localizedValue)); }

需要注意的是,使用object作为localizedValue的类型,因为该值实际上可能不是字符串。每个用于大写和小写转换的方法首先检查localizedValue是否为字符串,然后再进行处理。

额外的添加

实际上,为这个类添加了一个特性。这可能不是必需的,但确实使用了它。这是一个静态的Loc类,它使用相同的键字符串访问相同的值:

public static class Loc { public static object GetValue(string value) { var resourceManager = LocalizationManager.DefaultResourceManager; if (resourceManager == null) return $"[{value}]"; var uiCulture = Thread.CurrentThread.CurrentCulture; var returnValue = resourceManager.GetObject(value, uiCulture); return returnValue ?? $"[{value}]"; } }

还更新了解决方案到框架版本4.6.1,并用条件运算符替换了很多代码,以及一些新的C# 6.0特性。

使用代码

有关代码的原始特性的信息,可以参考原始文章。本文只涵盖了新增的内容,即指定文本的大写和小写形式。

以下代码片段展示了如何指定文本应该大写和复数化:

<TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource Label}" Text="{Loc Label_CodeBehind_Callback, Case=Upper, Pluralization=Plural}" />

CasePluralization参数都是可选的,如果不需要这个特性,可以省略。这两个都在代码中以枚举的形式指定:

public enum CaseEnum { None = 0, Upper, Lower } public enum PluralizationEnum { None = 0, Plural, Singular }

示例

这个示例与原始代码中的示例相同,但做了一些改动。一个是在XAML中指定了CasePluralization的控件,如上面的TextBlock代码所示。第二个是在Resources.resx文件中,"Callback:"的末尾的冒号(":")已经被移除。这是因为冒号(":")会干扰PluralizationService进行复数形式的处理。PluralizationService不处理冒号,所以为了演示这个功能,必须移除它。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485