views:

170

answers:

2

In C#, attribute parameters require to be a constant expression, typeof or array creation expression.

Various libraries, like for example Castle validator, allow specifying passing what seems like localized error messages to attribute constructor:

//this works
[ValidateNonEmpty("Can not be empty")]

//this does not compile
[ValidateNonEmpty(Resources.NonEmptyValidationMessage)]

Is there any way how to approach this problem and localize these arguments?

In case there is no workaround for this when using Castle Validator, is there a validation library similar to Castle Validator that allows localization of validation messages?

EDIT: I found how Data Annotations validation library approaches this problem. Very elegant solution: http://haacked.com/archive/2009/12/07/localizing-aspnetmvc-validation.aspx

+3  A: 

We had a similar issue, although not with Castle. The solution we used was simply to define a new attribute which was derived from the other one, and which used the constant string as a lookup to the resources manager, and fell back to the key string itself if none was found.

[AttributeUsage(AttributeTargets.Class
  | AttributeTargets.Method
  | AttributeTargets.Property
  | AttributeTargets.Event)]
public class LocalizedIdentifierAttribute : ... {
  public LocalizedIdentifierAttribute(Type provider, string key)
    : base(...) {
    foreach (PropertyInfo p in provider.GetProperties(
      BindingFlags.Static | BindingFlags.NonPublic)) {
      if (p.PropertyType == typeof(System.Resources.ResourceManager)) {
        ResourceManager m = (ResourceManager) p.GetValue(null, null);

        // We found the key; use the value.
        return m.GetString(key);
      }
    }

    // We didn't find the key; use the key as the value.
    return key;
  }
}

Usage is something like:

[LocalizedIdentifierAttribute(typeof(Resource), "Entities.FruitBasket")]
class FruitBasket {
  // ...
}

Then each locale-specific resource file can define its own Entities.FruitBasket entry, as needed.

John Feminella
Thanks, that is one very elegant solution how to wrap an existing library to allow this behavior.
Marek
A: 

It works out of the box:

    [ValidateNonEmpty(
        FriendlyNameKey = "CorrectlyLocalized.Description",
        ErrorMessageKey = "CorrectlyLocalized.DescriptionValidateNonEmpty",
        ResourceType = typeof (Messages)
        )]
    public string Description { get; set; }
Krzysztof Koźmic
Thanks, that would be wonderful, but the version of Castle Validator's ValidateNonEmptyAttribute that I am using does not have these properties. I see only errorMessage, RunWhen, ExecutionOrder and FriendlyName.
Marek
Which version of Castle validator has these properties? Could you please post a download link?
Marek
A little tricky to find, but the SVN version has it. https://svn.castleproject.org/svn/castle/Components/Validator/trunk/ Thanks for pointing this out!
Marek