4

I want to display model error message in spanish and I have defined those string in resourse files. I have done the same for other string on the page using razor syntax but the ones from ViewModel annotation are not being picked.

It is actually picking the default values - English. So my guess is that may be the language/culture was not detected, but other string on the page are displayed in spanish

//Spanish: El campo {0} se requiere
//English: The {0} field is required  <--- this comes out always irrespective of set language

[Required(ErrorMessageResourceName = "ErrorMessage_Required", 
     ErrorMessageResourceType = typeof(GlobalResources.Resources))]
[Display(Name = "CardNumber", ResourceType = typeof(GlobalResources.Resources) )]
public string CardNumber { get; set; }

I set the language in my Controller

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);

    HttpCookie cookie = Request.Cookies["lang"];

    string lang = cookie != null ? cookie.Value : "en-US";
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);
}

How do I extend the culture settings to ViewModels?

Update A similar post: MVC3 globalization: need global filter before model binding

Update Changing the preferred language in my browser settings made it work. This means the model attributes is using this settings which is not affected by System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);. Is there a way to make this happen? - Still searching....

Update: Moving the code to Application_AcquireRequestState seems to solve it.

protected void Application_AcquireRequestState()
{
    HttpCookie cookie = Request.Cookies["lang"];

    string lang = cookie != null ? cookie.Value : "en-US";
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);
}

The explanation I got, also found in the link posted in this question, that it was too late for the model to make use of the culture being set in controller overridden method as the binding had already occurred before the method is called. This link was helpful

Community
  • 1
  • 1
codingbiz
  • 26,179
  • 8
  • 59
  • 96
  • _More clarity_: The cookie shows "es" which is spanish when written out. Like I said, other text on the page shows spanish, only the model error message and properties are not affected – codingbiz Apr 24 '13 at 22:43

2 Answers2

3

Try using the below class

public sealed class LanguageManager
{
    /// <summary>
    /// Default CultureInfo
    /// </summary>
    public static readonly CultureInfo DefaultCulture = new CultureInfo("en-US");

    /// <summary>
    /// Available CultureInfo that according resources can be found
    /// </summary>
    public static readonly CultureInfo[] AvailableCultures;

    static LanguageManager()
    {
        List<string> availableResources = new List<string>();
        string resourcespath = Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "App_GlobalResources");
        DirectoryInfo dirInfo = new DirectoryInfo(resourcespath);
        foreach (FileInfo fi in dirInfo.GetFiles("*.*.resx", SearchOption.AllDirectories))
        {
            //Take the cultureName from resx filename, will be smt like en-US
            string cultureName = Path.GetFileNameWithoutExtension(fi.Name); //get rid of .resx
            if (cultureName.LastIndexOf(".") == cultureName.Length - 1)
                continue; //doesnt accept format FileName..resx
            cultureName = cultureName.Substring(cultureName.LastIndexOf(".") + 1);
            availableResources.Add(cultureName);
        }

        List<CultureInfo> result = new List<CultureInfo>();
        foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
        {
            //If language file can be found
            if (availableResources.Contains(culture.ToString()))
            {
                result.Add(culture);
            }
        }

        AvailableCultures = result.ToArray();

        CurrentCulture = DefaultCulture;
        if (!result.Contains(DefaultCulture) && result.Count > 0)
        {
            CurrentCulture = result[0];
        }
    }

    /// <summary>
    /// Current selected culture
    /// </summary>
    public static CultureInfo CurrentCulture
    {
        get { return Thread.CurrentThread.CurrentCulture; }
        set
        {
            Thread.CurrentThread.CurrentUICulture = value;
            Thread.CurrentThread.CurrentCulture = value;
        }
    }
}

And finally set the culture like below.

LanguageManager.CurrentCulture = new CultureInfo("Your culture");

and now override the culture

1

Make sure you set both CurrentCulture and CurrentUICulture. I suspect CurrentCulture is actually what the resource files are looking at:

 //I've taken off System.Threading, add a using to it (aids readability)

 Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);
 Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(lang);
Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
  • No luck with that. I believe `CurrentCulture` is used when you want currency, date formats etc to be affected. I purposely left it out. I added it as you mentioned but it did not work – codingbiz Apr 24 '13 at 19:42
  • If you debug does the cookie value come out? Have you definitely derived the resource in the resource file for that culture? – Mathew Thompson Apr 24 '13 at 19:59
  • The cookie shows "es" which is spanish. Like I said, other text on the page shows spanish, only the model error message and properties are not affected – codingbiz Apr 24 '13 at 22:43
  • You haven't hard coded any globalization in the web.config have you? – Mathew Thompson Apr 25 '13 at 07:48
  • Moving the code to Global.asax worked for me. I have updated my post. Thanks. – codingbiz Apr 25 '13 at 18:21