Enum localization

后端 未结 15 592
慢半拍i
慢半拍i 2020-11-30 17:56

How do you localize enums for a ListBoxFor where multiple options are possible?

For example an enum that contains roles:

pu         


        
相关标签:
15条回答
  • You can use your enum value to do what you want.

    public enum Roles
    {
        Administrator = 0,
        Moderator = 1 ,
        Webmaster  = 2,
        Guest = 3 ,
        Etc.... = 4 
    }
    

    When you want to get the selected enum on the listbox, you retrieve the listbox item and then you retrieve the associated enum number.

    Then you will convert that to an enum item like this

    Roles myrol = (Roles) i
    

    (i is associated int vale for this example)

    Converting enum item to Integer and integer value back to enum item

     Enum Item to Integer----- 
        int i =  (int)Roles.Admin ;
        Integer to enum Itenm
        Roles r = (Roles)i ; 
    
         //Getting the name of the enum
         string role =  Role.Admin.ToString() 
    

    IF you are adding to a Hashtable then you can do it this way

    Hashtable h = new Hashtable() ; 
    h.Items.Add((int)Roles.Admin , Roles.Admin.ToStrinng() ) ;
    h.Items.Add((int)Roles.Local , Roles.Local.ToStrinng() ) ; 
    

    when you pick an item from the hashtable , convert it back to Enum item and use it where you want. You can use the same way to populate Datatables / Comboboxes , dropdown lists and so on

    0 讨论(0)
  • 2020-11-30 18:00

    The extension method of bellow it's worked to me.

        public static string GetDisplayValue(this Enum value)
        {
            try
            {
                var fieldInfo = value.GetType().GetField(value.ToString());
                var descriptionAttributes = fieldInfo.GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[];
    
                if (descriptionAttributes == null || descriptionAttributes.Length == 0) return value.ToString();
    
                if (descriptionAttributes[0].ResourceType != null)
                {
                    var resource = descriptionAttributes[0].ResourceType.GetProperty("ResourceManager").GetValue(null) as ResourceManager;
                    return resource.GetString(descriptionAttributes[0].Name);
                }
                else
                {
                    return descriptionAttributes[0].Name;
                }
            }
            catch
            {
                return value.ToString();
            }
        }
    

    I holpe helps.

    0 讨论(0)
  • 2020-11-30 18:01

    You can implement a description attribute.

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

    Define it like this:

    public enum Roles
    {
        [LocalizedDescription("Administrator", typeof(Resource))]
        Administrator,
    ...
    }
    

    And use it like this:

    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");
    
    0 讨论(0)
  • 2020-11-30 18:03

    UPDATE 2019

    Nowadays its just plain easy, setup your enum:

    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
    }
    

    Each enum value gets a Display attribute with a Description value which is an entry in a resource assembly class called Globalization.Contact. This resource assembly (project) contains various translations for the different contact option types (Demo, Callback, Quotation, Other). It contains files like these: contact.nl.resx (for the Netherlands) and contact.resx (The default which is en-US) in which the different enum values have their localized values (translations).

    Now in a static enum helper class we have this method:

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

    This will get the value for the Description property of the Display attribute. Which will be the translated value if and only if the CurrentUICulture is set. This "glues" everything together.

    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
    

    or

    Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl-NL");
    

    Now in a simple Unit Test (XUnit) we can see if it works as expected / desired / designed:

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

    The above will succeed effortlessly ✅

    0 讨论(0)
  • 2020-11-30 18:07

    I solved the issue by creating a EnumExtension which I use in my view. This extension looks for a resource file called "EnumResources.resx" and looks up the resource by the following naming convention {Name of EnumType}_{Value of enum passed in}. If the resource key is missing it will display the value of the resource encapsulated within double brackets [[EnumValue]]. This way its easy to find a "untranslated" Enum in your view. Also this helps reminding you if you forgot to update the resource file after a rename or such.

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

    The resource file looks like this: Resource file

    Usage:

    <div>@ContractStatus.Created.GetDisplayName()</div>
    
    0 讨论(0)
  • 2020-11-30 18:07

    Same answer as accepted answer but without code analysis warnings

     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification ="Resourcetype is only needed to instantiate Resource manager, and ResourceManager is exposed")]
    [AttributeUsage(AttributeTargets.All)]
    public sealed class LocalizedDescriptionAttribute 
        : DescriptionAttribute
    {
        private readonly string _resourceKey;
        private readonly ResourceManager _resourceManager;
    
        public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
        {
            _resourceManager = new ResourceManager(resourceType);
            _resourceKey = resourceKey;
        }
    
        public string ResourceKey
        {
            get { return _resourceKey; }
        }
    
        public ResourceManager ResourceManager
        {
            get { return _resourceManager; }
        }
    
        public override string Description
        {
            get
            {
                string displayName = _resourceManager.GetString(_resourceKey);
                return string.IsNullOrEmpty(displayName)? string.Format(CultureInfo.CurrentUICulture ,"[[{0}]]", _resourceKey) : displayName;
            }
        }
    }
    
    public static class EnumExtensions
    {
        public static string GetDescription(this Enum enumValue)
        {
            if (enumValue == null)
            {
                throw new ArgumentNullException("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();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题