Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking enum value with localized string resource

Related: Get enum from enum attribute

I want the most maintainable way of binding an enumeration and it's associated localized string values to something.

If I stick the enum and the class in the same file I feel somewhat safe but I have to assume there is a better way. I've also considered having the enum name be the same as the resource string name, but I'm afraid I can't always be here to enforce that.

using CR = AcmeCorp.Properties.Resources;

public enum SourceFilterOption
{
    LastNumberOccurences,
    LastNumberWeeks,
    DateRange
    // if you add to this you must update FilterOptions.GetString
}

public class FilterOptions
{
    public Dictionary<SourceFilterOption, String> GetEnumWithResourceString()
    {
        var dict = new Dictionary<SourceFilterOption, String>();
        foreach (SourceFilterOption filter in Enum.GetValues(typeof(SourceFilterOption)))
        {
            dict.Add(filter, GetString(filter));
        }
        return dict;
    }

    public String GetString(SourceFilterOption option)
    {
        switch (option)
        {
            case SourceFilterOption.LastNumberOccurences:
                return CR.LAST_NUMBER_OF_OCCURANCES;
            case SourceFilterOption.LastNumberWeeks:
                return CR.LAST_NUMBER_OF_WEEKS;
            case SourceFilterOption.DateRange:
            default:
                return CR.DATE_RANGE;
        }
    }
}
like image 810
JoeB Avatar asked Jul 17 '12 22:07

JoeB


People also ask

Can we assign value to enum?

You cannot create an object of an enum explicitly so, you need to add a parameterized constructor to initialize the value(s). The initialization should be done only once. Therefore, the constructor must be declared private or default. To returns the values of the constants using an instance method(getter).

Can string be used with enum?

As far as I know, you will not be allowed to assign string values to enum. What you can do is create a class with string constants in it.

How do you match a string to an enum?

For comparing String to Enum type you should convert enum to string and then compare them. For that you can use toString() method or name() method. toString()- Returns the name of this enum constant, as contained in the declaration.

How do you localize an enum?

So what we usually do for enums that need to be localized is to write an extension class that provides a method to obtain the translated name. You can just use a switch that returns strings from the usual resources. That way, you provide translated strings for enums via the resources just like you do for other strings.


4 Answers

You can add DescriptionAttribute to each enum value.

public enum SourceFilterOption
{
    [Description("LAST_NUMBER_OF_OCCURANCES")]
    LastNumberOccurences,
    ...
}

Pull out the description (resource key) when you need it.

FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute),     
if (attributes.Length > 0)
{
    return attributes[0].Description;
}
else
{
    return value.ToString();
}

http://geekswithblogs.net/paulwhitblog/archive/2008/03/31/use-the-descriptionattribute-with-an-enum-to-display-status-messages.aspx

Edit: Response to comments (@Tergiver). Using the (existing) DescriptionAttribute in my example is to get the job done quickly. You would be better implementing your own custom attribute instead of using one outside of its purpose. Something like this:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inheritable = false)]
public class EnumResourceKeyAttribute : Attribute
{
 public string ResourceKey { get; set; }
}
like image 63
Paul Fleming Avatar answered Sep 24 '22 17:09

Paul Fleming


You could just crash immediately if someone doesn't update it correctly.

public String GetString(SourceFilterOption option)
{
    switch (option)
    {
        case SourceFilterOption.LastNumberOccurences:
            return CR.LAST_NUMBER_OF_OCCURANCES;
        case SourceFilterOption.LastNumberWeeks:
            return CR.LAST_NUMBER_OF_WEEKS;
        case SourceFilterOption.DateRange:
            return CR.DATE_RANGE;
        default:
            throw new Exception("SourceFilterOption " + option + " was not found");
    }
}
like image 36
Mike Blandford Avatar answered Sep 24 '22 17:09

Mike Blandford


I do mapping to resourse in the following way: 1. Define a class StringDescription with ctor getting 2 parameters (type of resourse and it's name)

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
class StringDescriptionAttribute : Attribute
{
    private string _name;
    public StringDescriptionAttribute(string name)
    {
        _name = name;
    }

    public StringDescriptionAttribute(Type resourseType, string name)
    {
            _name = new ResourceManager(resourseType).GetString(name);

    }
    public string Name { get { return _name; } }
}
  1. Create a resourse file for either culture (for example WebTexts.resx and Webtexts.ru.resx). Let is be colours Red, Green, etc...

  2. Define enum:

    enum Colour{ [StringDescription(typeof(WebTexts),"Red")] Red=1 , [StringDescription(typeof(WebTexts), "Green")] Green = 2, [StringDescription(typeof(WebTexts), "Blue")] Blue = 3, [StringDescription("Antracit with mad dark circles")] AntracitWithMadDarkCircles

    }

  3. Define a static method getting resource description via reflection

    public static string GetStringDescription(Enum en) {

        var enumValueName = Enum.GetName(en.GetType(),en);
    
        FieldInfo fi = en.GetType().GetField(enumValueName);
    
        var attr = (StringDescriptionAttribute)fi.GetCustomAttribute(typeof(StringDescriptionAttribute));
    
        return attr != null ? attr.Name : "";
    }
    
  4. Eat :

    Colour col; col = Colour.Red; Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

        var ListOfColors = typeof(Colour).GetEnumValues().Cast<Colour>().Select(p => new { Id = p, Decr = GetStringDescription(p) }).ToList();
    
        foreach (var listentry in ListOfColors)
            Debug.WriteLine(listentry.Id + " " + listentry.Decr);
    
like image 26
Lapenkov Vladimir Avatar answered Sep 23 '22 17:09

Lapenkov Vladimir


There is the simplest way to getting the enum description value according to culture from resources files

My Enum

  public enum DiagnosisType
    {
        [Description("Nothing")]
        NOTHING = 0,
        [Description("Advice")]
        ADVICE = 1,
        [Description("Prescription")]
        PRESCRIPTION = 2,
        [Description("Referral")]
        REFERRAL = 3

}

i have made resource file and key Same as Enum Description Value

Resoucefile and Enum Key and Value Image, Click to view resouce file image

   public static string GetEnumDisplayNameValue(Enum enumvalue)
    {
        var name = enumvalue.ToString();
        var culture = Thread.CurrentThread.CurrentUICulture;
        var converted = YourProjectNamespace.Resources.Resource.ResourceManager.GetString(name, culture);
        return converted;
    }

Call this method on view

  <label class="custom-control-label" for="othercare">YourNameSpace.Yourextenstionclassname.GetEnumDisplayNameValue(EnumHelperClass.DiagnosisType.NOTHING )</label>

It will return the string accordig to your culture

like image 32
Mahaveer Jangid Avatar answered Sep 21 '22 17:09

Mahaveer Jangid