Localize Errormessages in VAB

Topics: Validation Application Block
Mar 10, 2007 at 9:19 AM
Edited Mar 10, 2007 at 9:19 AM
Hallo everybody,

the VAB ist really cool, but i have a problem with the error messages. The world speaks not only english or german. I dont know at design time, wich language the webuser speaks. How can I change the error messages in dependency on the language of the Clientbrowser?

Thanks

Jan
Mar 10, 2007 at 10:58 PM
Hi Jan -

When defining validators using configuration or attributes, you have the option to specify a MessageTemplateResourceName and MessageTemplateResourceType pair instead of a literal message template string. If the validation fails, the resource will be loaded using the thread's culture setting. If you define multiple resources for different cultures it should be possible to do what you want.

HTH
Tom
Feb 20, 2008 at 5:47 PM
Any idea on how to specify something other than a RESX file for a resource provider? We're using a database for our backend localization, but I'm having difficulty getting the attributes in the VAB working with our resource provider. Currently we can use the $ Resources: Login, Register in our front-end code, and that hits our database. When I try to specify the MessageTemplateResourceType and point it to our custom resource provider, it doesn't appear to hit our code at all.

I've also attempted to change the generated code in the Resources.Designer.cs file, but that doesn't get hit either.

Any examples of how to get this working?

Thanks,
Travis
May 20, 2008 at 7:25 AM
Hi

I can't get localized ProperyProxyValidator (Entlib 4.0) error message. Instead of getting error message in russian I got abracadabra. I got it even when I've written a literal message in LogValidationResult. The thread's culture is right - "ru". Validators from System.Web namespace return correct localized error messages. Please help.

Thanks.
May 20, 2008 at 5:34 PM
This is really strange. The string you get is not present in any source file for EntLib.

Find all "abracadabra", Match case, Subfolders, Find Results 1, "D:\EntLib4Src", "*.*"

Matching lines: 0 Matching files: 0 Total files searched: 3075

Is it possible the string is hardcoded in your app?

In any case, do you want to localize the default messages or your own?

Fernando



sergeimaslennikov wrote:
Hi

I can't get localized ProperyProxyValidator (Entlib 4.0) error message. Instead of getting error message in russian I got abracadabra. I got it even when I've written a literal message in LogValidationResult. The thread's culture is right - "ru". Validators from System.Web namespace return correct localized error messages. Please help.

Thanks.



May 20, 2008 at 8:17 PM
Of course, you can only provide localized versions of the validators' default messages if you build and use your own binaries; you won't be able to create satellite assemblies for the binaries signed by Microsoft.

Fernando
May 21, 2008 at 1:19 AM
Edited May 21, 2008 at 1:23 AM
Hi

Not exactly what I had in mind. I had in mind that I got message which encoding is wrong (not readable for human). Of course I want to get my own message from resource.
For example:
== control ==
<ccl:PropertyProxyValidator ID="LoginPropertyProxyValidator" Display="Dynamic" ControlToValidate="Login" ValidationGroup="NewUser" runat="server"  PropertyName="Username" SourceTypeName="...something type..." Text="<%$ Resources: Strings, newaccount_val_userexists %>" />
== validator code ==
protected override void DoValidate(string objectToValidate, object currentTarget, string key, ValidationResults validationResults) {
bool exists = false;
if (string.IsNullOrEmpty(objectToValidate) == false) {
    
exists =
SystemUser.IsUserExists(objectToValidate);
}

if
(exists) {
    
PropertyProxyValidator validator = (PropertyProxyValidator)currentTarget;
    
base.LogValidationResult(validationResults, validator.Text, currentTarget, key);
}
}
Instead of message in russian I got unreadable message like this:
пользователь с таким именем уже зарегистрирован. введите другое имя пользователя
 
May 21, 2008 at 7:55 AM

I have also faced problems with error message localization. As another poster has replied, you can use resources to solve this issue. But this is not alwyas optimal - as yet another poster wrote, he uses a database backend for localization tasks, and I for example usually write web-applications which use a content-management-system and utilize the localization functions from those systems.

This does not appear easy to achieve with the current version of VAB.

One suggestion I received was to alter the VAB code itself, and recompile, so it reads your localization from where you want. I didn't really want to do this, so I ended up writing a "custom validator" which dynamically instantiates a configured "message provider" class which provides the localized error message (by reading from my CMS for example). This was relatively easy when it was only a "string length validator" I required, but has proved rather troublesome as I have needed more complex validators (like the "or" validator for example). I have ended up "copying" the functionality of several of the existing validators, and this is not so easy, as many classes and functions in VAB are "internal" or "private", neccessitating copying large pieces of extraneous classes. Maybe editing and recompiling the actual VAB code itself would have been easier.

I hope the VAB team considers this "wish" for other ways to localize messages than resources - so they can come up with a consistent, easy to use, and stable method of localizing texts.

/Peter

  


janbaer wrote:
Hallo everybody,

the VAB ist really cool, but i have a problem with the error messages. The world speaks not only english or german. I dont know at design time, wich language the webuser speaks. How can I change the error messages in dependency on the language of the Clientbrowser?

Thanks

Jan



May 21, 2008 at 2:28 PM
Edited May 21, 2008 at 4:26 PM

Hi Sergei,

I'm a bit confused here. This problem is not directly related to the original post but to a specific implementation, and you seem to have left several important details out of your post. If I understand correctly, by "abracadabra" you mean gibberish, not the actual "abracadabra" literal; please confirm this. Also, you seem to be defining a custom validator that assumes the object being validated is a proxy validator; that's not a good design IMO. You should instead define the message in when you specify the validator on the source type's property, potentially using a resource for this. This should be equivalent to what you're doing unless you want different messages on different uses of a property proxy validator on the same domain class property.

Keep in mind that the purpose of the PropertyProxyValidator is to proxy to the validation block based on the validation definitions on a domain model, and different validators with different messages may have been applied.

As for the gibberish that gets generated, it's strange since the standard string management methods are used to build the output message. If you debug your app, can you verify that what you get in your validator's call to validator.Text is correct?

Fernando


sergeimaslennikov wrote:
Hi

Not exactly what I had in mind. I had in mind that I got message which encoding is wrong (not readable for human). Of course I want to get my own message from resource.
For example:
== control ==
<ccl:PropertyProxyValidator ID="LoginPropertyProxyValidator" Display="Dynamic" ControlToValidate="Login" ValidationGroup="NewUser" runat="server"  PropertyName="Username" SourceTypeName="...something type..." Text="<%$ Resources: Strings, newaccount_val_userexists %>" />
== validator code ==
protected override void DoValidate(string objectToValidate, object currentTarget, string key, ValidationResults validationResults) {
bool exists = false;
if (string.IsNullOrEmpty(objectToValidate) == false) {
    
exists =
SystemUser.IsUserExists(objectToValidate);
}

if
(exists) {
    
PropertyProxyValidator validator = (PropertyProxyValidator)currentTarget;
    
base.LogValidationResult(validationResults, validator.Text, currentTarget, key);
}
}
Instead of message in russian I got unreadable message like this:
пользователь с таким именем уже зарегистрирован. введите другое имя пользователя
 


May 21, 2008 at 4:25 PM
Sergei,

I tried your approach, with a custom validator casting the currentTarget to a property proxy validator and I still didn't get gibberish. One thing I noticed though is that you should configure and retrieve the ErrorMessage property, not the Text property.

Fernando
May 22, 2008 at 6:21 AM
Edited May 22, 2008 at 8:16 AM
Hi Fernando

Yes I mean gibberish when I said "abracadabra". :-) In result of debugging I see that PropertyProxyValidator transmits a correct message to ServerSideValidatorExtender. Maybe the cause of my problem is implementation of ServerSideValidatorExtender's GetCallbackResult() method of AjaxControlToolkit.WCSExtensions assembly (runtime v2.0.2.0). The mthod code is:
===
public string GetCallbackResult()
{
    if (this.callbackEventException != null)
    {
        throw this.callbackEventException;
    }
    this.validator.Validate();
    ServerValidationResults results = new ServerValidationResults(this.valueToValidate, this.validator.IsValid, this.validator.ErrorMessage);
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ServerValidationResults));
    MemoryStream ms = new MemoryStream();
    ser.WriteObject(ms, results);
    string serialized = Encoding.Default.GetString(ms.ToArray());
    ms.Close();
    return serialized;
}
===
As you can see the method to serialize message uses Default encoding. ANSI code page for russia is 1251 or 866 but I use utf8 in my webpage due to my message become unreadable.
May 22, 2008 at 4:22 PM
Edited May 23, 2008 at 7:30 AM
Hi Sergei,

Now that's what I call a missing piece ;)

I tried using localized resources on one of the non-EntLib validators that had an extender attached (a plain ASP.NET custom validator) and got the same results. It certainly looks like using the default encoding could be causing this problem; I changed the encoding line to Encoding.UTF8.GetString(ms.ToArray()) and got the expected result. I'll bring this to the WCSF team's attention.

Fernando

[edited to update encoding to UTF8 instead of the response's content encoding]




sergeimaslennikov wrote:
Hi Fernando

Yes I mean gibberish when I said "abracadabra". :-) In result of debugging I see that PropertyProxyValidator transmits a correct message to ServerSideValidatorExtender. Maybe the cause of my problem is implementation of ServerSideValidatorExtender's GetCallbackResult() method of AjaxControlToolkit.WCSExtensions assembly (runtime v2.0.2.0). The mthod code is:
===
public string GetCallbackResult()
{
    if (this.callbackEventException != null)
    {
        throw this.callbackEventException;
    }
    this.validator.Validate();
    ServerValidationResults results = new ServerValidationResults(this.valueToValidate, this.validator.IsValid, this.validator.ErrorMessage);
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ServerValidationResults));
    MemoryStream ms = new MemoryStream();
    ser.WriteObject(ms, results);
    string serialized = Encoding.Default.GetString(ms.ToArray());
    ms.Close();
    return serialized;
}
===
As you can see the method to serialize message uses Default encoding. ANSI code page for russia is 1251 or 866 but I use utf8 in my webpage due to my message become unreadable.


May 26, 2008 at 1:56 PM
You can get the source code for the WCSF from http://www.microsoft.com/downloads/details.aspx?FamilyId=47755838-049B-4291-AFEA-A379AE28D7B3&displaylang=en.

Cheers,
Fernando
Jul 11, 2008 at 10:30 AM
Hello Everybody,

Concerning the first post, i have the same problem.
I also try to localize my error message with the VAB according to language of the client browser.

But the language of the message is always the one of the first browser who launched the application.

Exemple:
In my Web project :
<cc1:PropertyProxyValidator ID="PPVCode" runat="server" ControlToValidate="TextCode"
                PropertyName="Code" SourceTypeName="BusinessEntities.myClass"
                DisplayMode="List" SpecificationSource="Attributes" Display="Dynamic">

In my Library Project :
namespace BusinessEntities
{
         pulic class myClass
        {
                [StringLengthValidator(13, 13,
                    MessageTemplateResourceName="CodeLenght",
                    MessageTemplateResourceType=typeof(ValidationMessages))]
                public string Code
                {
                    get { return _code; }
                    set { _code= value; }
                }
        }
With "CodeLenght" defined in "ValidationMessages" resources with multi-languages.

Is it possible to localize the resources of classes which are not in the Web project ?
If yes, what I have to add ?
Default language for my Lirbrary ? [Localizable(true)] ?

Thanks !
Jul 11, 2008 at 2:19 PM
Hi,

That's unfortunately a known issue (see http://www.codeplex.com/entlib/WorkItem/View.aspx?WorkItemId=16451 and http://www.codeplex.com/entlib/WorkItem/View.aspx?WorkItemId=11504).
There's currently no solution but to update the source code to remove the caching code in the PropertyValidatorFactory.GetPropertyValidator*() methods; fixing the cache to include a culture info in the key won't work because type validators used to build the property validator may have been cached too.

Fernando


c4medable wrote:
Hello Everybody,

Concerning the first post, i have the same problem.
I also try to localize my error message with the VAB according to language of the client browser.

But the language of the message is always the one of the first browser who launched the application.

Exemple:
In my Web project :
<cc1:PropertyProxyValidator ID="PPVCode" runat="server" ControlToValidate="TextCode"
                PropertyName="Code" SourceTypeName="BusinessEntities.myClass"
                DisplayMode="List" SpecificationSource="Attributes" Display="Dynamic">

In my Library Project :
namespace BusinessEntities
{
         pulic class myClass
        {
                [StringLengthValidator(13, 13,
                    MessageTemplateResourceName="CodeLenght",
                    MessageTemplateResourceType=typeof(ValidationMessages))]
                public string Code
                {
                    get { return _code; }
                    set { _code= value; }
                }
        }
With "CodeLenght" defined in "ValidationMessages" resources with multi-languages.

Is it possible to localize the resources of classes which are not in the Web project ?
If yes, what I have to add ?
Default language for my Lirbrary ? [Localizable(true)] ?

Thanks !