Search code examples
c#.netwpflocalizationcultureinfo

Localize dataannotation error messages as per culture


In my WPF appliation, I have property defined as following

[Required(AllowEmptyStrings =false, ErrorMessageResourceName ="Msg1", ErrorMessageResourceType =typeof(*<AssemblyName>*.Resources.*<ResourceFileName>*))]
public string Name
{
    get
    {
        return _name;
    }

    set
    {
        if (_name == value)
        {
            return;
        }
        _name = value;
    }
}

I have my error messages defined in separate assembly which has resource file for different cultures e.g. Resources.resx, Resources.en-GB.Resx, Resources.fr-FR.Resx, Resources.en-US.Resx, etc.

With above code in place, I'm able to retrieve the error message from default resource file in my satellite assembly but I don't see any provision to find the string resource from culture specific resource file. What I mean is if my CurrentUICluture is set as english(United Kingdom) then I want to retrieve the resource value from the file "Resources.en-GB.Resx" instead of the default file (i.e. Resources.Resx).

I don't see any way to pass the culture info in the Required attribute definition. Also, I have tested that it is not inherently look into the culture specific resource file based on the current culture set.

What I want is some way to make the resource retrieval mechanism culture aware.

Thanks,


Solution

  • Finally I got the fix for my problem from this link

    In my app, I was setting the culture at the time of starting the application by putting following code in app.xaml.cs file.

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            InitializeCultures();
        }
    
        private static void InitializeCultures()
        {
            var culture = ConfigurationManager.AppSettings.Get("Culture");
            if (!String.IsNullOrEmpty(culture))
            {
                Thread.CurrentThread.CurrentCulture =  new CultureInfo(culture);
            }
    
            var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
            if (!String.IsNullOrEmpty(UICulture))
            {
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(UICulture);
            }
        }
    

    However problem is even if I set the Culture initially, not all threads will use the same culture set by me initially. So the thread which was reading the resource value for me was still using the default culture and this resulted in reading of resource string always from default culture resource file rather then the culture specific resource file.

    So the trick was to set all the threads in my app to use the same culture which I set initially. There are two properties for this

    1. CultureInfo.DefaultThreadCurrentCulture
    2. CultureInfo.DefaultThreadCurrentUICulture

    Setting required culture value to these two properties initially will ensure that all the subsequent threads used in the application will have the same culture as set by user. These two properties sets the culture on all the threads in current app domain.

    Once culture is set properly, reading of resource values inherently becomes culture aware and reads resource values from culture specific resource files.

    So following is the updated version of InitializeCulture method :

        private static void InitializeCultures()
        {
            var culture = ConfigurationManager.AppSettings.Get("Culture");
            if (!String.IsNullOrEmpty(culture))
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.DefaultThreadCurrentCulture =  new CultureInfo(culture);
            }
    
            var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
            if (!String.IsNullOrEmpty(UICulture))
            {
                Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(UICulture);
            }
        }
    

    P.S. There is a word of caution of using this fix in web application. Pls read about it on original link.

    Hope this helps...