Enum本地化

Quo*_*ter 53 c# localization asp.net-mvc-4

如何ListBoxFor在可能有多个选项的地方枚举枚举?

例如enum,包含角色:

public enum RoleType
{
    [Display(Description = "Administrator", ResourceType = typeof(Resource))]
    Administrator = 1,
    [Display(Description = "Moderator", ResourceType = typeof(Resource))]
    Moderator = 2,
    [Display(Description = "Webmaster", ResourceType = typeof(Resource))]
    Webmaster = 3,
    [Display(Description = "Guest", ResourceType = typeof(Resource))]
    Guest = 4,
    Etc.... = 5,
}
Run Code Online (Sandbox Code Playgroud)

我已经看到用dropdownlist/ 完成了这个selectlists.但是有没有办法为多选列表执行此操作?

[编辑]

这就是我想要使用它的方式,它现在是如何工作的,但不会用其他语言翻译:

var roles = from role r in Enum.GetValues(typeof(RoleType))
            select new
            {
               Id = (int)Enum.Parse(typeof(RoleType), r.ToString()),
               Name = r.ToString()
            };

searchModel.roles = new MultiSelectList(roles, "Id", "Name");
Run Code Online (Sandbox Code Playgroud)

注意:我已将"枚举"从"角色"重命名为"角色类型".

elu*_*xen 67

您可以实现描述属性.

public class LocalizedDescriptionAttribute : DescriptionAttribute
{
     private readonly string _resourceKey;
    private readonly ResourceManager _resource;
    public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
    {
        _resource = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    public override string Description
    {
        get
        {
            string displayName = _resource.GetString(_resourceKey);

            return string.IsNullOrEmpty(displayName)
                ? string.Format("[[{0}]]", _resourceKey)
                : displayName;
        }
    }
}

public static class EnumExtensions
{
    public static string GetDescription(this Enum enumValue) 
    {
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute),
            false);

        if (attributes != null &&
            attributes.Length > 0)
            return attributes[0].Description;
        else
            return enumValue.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样定义:

public enum Roles
{
    [LocalizedDescription("Administrator", typeof(Resource))]
    Administrator,
...
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

var roles = from RoleType role in Enum.GetValues(typeof(RoleType))
                    select new
                    {
                        Id = (int)role,
                        Name = role.GetDescription()
                    };
 searchModel.roles = new MultiSelectList(roles, "Id", "Name");
Run Code Online (Sandbox Code Playgroud)

  • 我收到此错误无法找到适合指定文化或中性文化的任何资源.确保在编译时将"Resources.Admin.resources"正确嵌入或链接到程序集"Auction"中,或者所有所需的附属程序集都是可加载和完全签名的. (3认同)

dis*_*sco 30

我通过创建一个我在视图中使用的EnumExtension解决了这个问题.此扩展名查找名为"EnumResources.resx"的资源文件,并通过以下命名约定{EnumType的名称} _ {传入的枚举值}来查找资源.如果缺少资源键,它将显示封装在双括号[[EnumValue]]中的资源的值.这样很容易在你的视图中找到一个"未翻译的"枚举.这也有助于提醒您是否忘记在重命名后更新资源文件等.

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum e)
    {
        var rm = new ResourceManager(typeof (EnumResources));
        var resourceDisplayName = rm.GetString(e.GetType().Name + "_" + e);

        return string.IsNullOrWhiteSpace(resourceDisplayName) ? string.Format("[[{0}]]", e) : resourceDisplayName;
    }
}
Run Code Online (Sandbox Code Playgroud)

资源文件如下所示: 资源文件

用法:

<div>@ContractStatus.Created.GetDisplayName()</div>
Run Code Online (Sandbox Code Playgroud)


Ber*_* IT 13

2019 年更新

现在它很简单,设置你的枚举:

public enum ContactOptionType
{
    [Display(Description = "ContactOption1", ResourceType = typeof(Globalization.Contact))]
    Demo = 1,

    [Display(Description = "ContactOption2", ResourceType = typeof(Globalization.Contact))]
    Callback = 2,

    [Display(Description = "ContactOption3", ResourceType = typeof(Globalization.Contact))]
    Quotation = 3,

    [Display(Description = "ContactOption4", ResourceType = typeof(Globalization.Contact))]
    Other = 4
}
Run Code Online (Sandbox Code Playgroud)

每个枚举值都有一个值,Display attributeDescription值是名为 的资源程序集类中的一个条目Globalization.Contact。此资源程序集(项目)包含不同联系选项类型(演示、回调、报价、其他)的各种翻译。它包含如下文件:(contact.nl.resx对于荷兰)和contact.resx(默认为 en-US),其中不同的枚举值具有其本地化值(翻译)。

现在在一个静态枚举助手类中,我们有这个方法:

public static string GetDisplayDescription(this Enum enumValue)
{
    return enumValue.GetType().GetMember(enumValue.ToString())
        .FirstOrDefault()?
        .GetCustomAttribute<DisplayAttribute>()
        .GetDescription() ?? "unknown";
}
Run Code Online (Sandbox Code Playgroud)

这将获得Description属性的Display属性值。当且仅当CurrentUICulture被设置时,这将是翻译后的值。这将所有东西“粘合”在一起。

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Run Code Online (Sandbox Code Playgroud)

或者

Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl-NL");
Run Code Online (Sandbox Code Playgroud)

现在在一个简单的单元测试 (XUnit) 中,我们可以查看它是否按预期/期望/设计工作:

[Theory]
[InlineData("nl-NL", "Terugbelverzoek")]
[InlineData("en-US", "Callback")]
public void TestTranslationOfDescriptionAttribute(string culture, string expectedValue)
{
    // Arrange
    CultureInfo cultureInfo = new CultureInfo(culture);
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;

    ContactOptionType contactOptionType = ContactOptionType.Callback;

    // Act
    string description = contactOptionType.GetDisplayDescription();

    // Assert
    Assert.Equal(expectedValue, description);
}
Run Code Online (Sandbox Code Playgroud)

以上会毫不费力地成功???

因此,此解决方案不再使用“复杂” LocalizedAttribute,仅使用一个简单的帮助器来获取 Display 属性的 Description 属性的(翻译)值。ResourceTypeDisplay 属性中存在一个值并结合设置 可以解决CurrentUICulture问题。


Mat*_*son 8

有一种方法可以在显示时使用属性来指定用于枚举的字符串,但是当您必须处理本地化时,我们发现它太过于繁琐.

因此,我们通常为需要本地化的枚举做的是编写一个扩展类,它提供了获取翻译名称的方法.您可以使用从常用资源返回字符串的开关.这样,您可以通过资源为枚举提供翻译的字符串,就像您对其他字符串一样.

例如:

public enum Role
{
    Administrator,
    Moderator,
    Webmaster,
    Guest
}

public static class RoleExt
{
    public static string AsDisplayString(this Role role)
    {
        switch (role)
        {
            case Role.Administrator: return Resources.RoleAdministrator;
            case Role.Moderator:     return Resources.RoleModerator;
            case Role.Webmaster:     return Resources.RoleWebmaster;
            case Role.Guest:         return Resources.RoleGuest;

            default: throw new ArgumentOutOfRangeException("role");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用:

var role = Role.Administrator;
Console.WriteLine(role.AsDisplayString());
Run Code Online (Sandbox Code Playgroud)

如果将RoleExt类实现保留在实现旁边,enum Role它将有效地成为接口的一部分Role.当然,您还可以为此类添加任何其他有用的枚举.

[编辑]

如果您想处理多个标志设置("管理员和主持人和网站管理员"),那么您需要做一些不同的事情:

[Flags]
public enum Roles
{
    None          = 0,
    Administrator = 1,
    Moderator     = 2,
    Webmaster     = 4,
    Guest         = 8
}

public static class RolesExt
{
    public static string AsDisplayString(this Roles roles)
    {
        if (roles == 0)
            return Resources.RoleNone;

        var result = new StringBuilder();

        if ((roles & Roles.Administrator) != 0)
            result.Append(Resources.RoleAdministrator + " ");

        if ((roles & Roles.Moderator) != 0)
            result.Append(Resources.RoleModerator + " ");

        if ((roles & Roles.Webmaster) != 0)
            result.Append(Resources.RoleWebmaster + " ");

        if ((roles & Roles.Guest) != 0)
            result.Append(Resources.RoleGuest + " ");

        return result.ToString().TrimEnd();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能会这样使用:

Roles roles = Roles.Administrator | Roles.Guest | Roles.Moderator;
Console.WriteLine(roles.AsDisplayString());
Run Code Online (Sandbox Code Playgroud)

资源文件

资源文件是您使字符串国际化的方式.有关如何使用它们的更多信息,请参见此处:

http://msdn.microsoft.com/en-us/library/vstudio/aa992030%28v=vs.100%29.aspx http://msdn.microsoft.com/en-us/library/vstudio/756hydy4%28v = VS.100%29.aspx