Using Resource files in MVC 5

If like us you are using resource files in MVC5 and switch on language in the Url:

i.e http://mydomain/en-GB

From RouteConfig.cs:

routes.MapRoute(
            "DefaultLocalized",
            "{language}-{culture}/{controller}/{action}/{id}",
            new
            {
                controller = "Home",
                action = "Index",
                id = string.Empty,
                // defaults to en-GB
                language = "en",
                culture = "GB"
            });

You will need to implement some code handles localization changes based on changes to the Url.

i.e http://mydomain/en-US should now render text from Resources.en-US.resx.

This code will need to:

a) Set the current Thread culture .
b) Add language and culture to the route data if it does not exist.

If you put this code in a Global filter you might find it works at first glance but any text rendered via Model attributes (e.g validation text) do not render localized versions. This is due to the MVC life cycle.

The best place to put this code is in a base controller overriding the Initialize method thus:

 public abstract class BaseController : Controller
 {
    protected void AddModelErrorToSummary(string message)
    {
        this.AddModelErrorToField(string.Empty, message);
    }

    protected void AddModelErrorToField(string key, string message)
    {
        ModelState.AddModelError(key, message);
    }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        this.EnsureRouteDataContainsLanguageAndCulutre(requestContext);

        SetCulture(
            (string)requestContext.RouteData.Values[RouteDataConstants.Language],
            (string)requestContext.RouteData.Values[RouteDataConstants.Culture]);
    }

    private void EnsureRouteDataContainsLanguageAndCulutre(RequestContext requestContext)
    {
        try
        {
            if (!requestContext.RouteData.Values.ContainsKey(RouteDataConstants.Language))
            {
                requestContext.RouteData.Values.Add(RouteDataConstants.Language, LocalizationConstants.DefaultLanguage);
            }

            if (!requestContext.RouteData.Values.ContainsKey(RouteDataConstants.Culture))
            {
                requestContext.RouteData.Values.Add(RouteDataConstants.Culture, LocalizationConstants.DefaultCulture);
            }
        }
        catch (ArgumentException exception)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
        }
    }

    private static void SetCulture(string language, string country)
    {
        Debug.Assert(!string.IsNullOrEmpty(language), "language not null");
        Debug.Assert(!string.IsNullOrEmpty(country), "country not null");

        var cultureCode = string.Format("{0}-{1}", language, country);

        IEnumerable<CultureInfo> cultures = CultureInfo.GetCultures(CultureTypes.AllCultures & ~CultureTypes.NeutralCultures);

        if (cultures.FirstOrDefault(c => c.Name.Equals(cultureCode, StringComparison.OrdinalIgnoreCase)) == null)
        {
            return;
        }

        var culture = CultureInfo.GetCultureInfo(cultureCode);

        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
}
comments powered by Disqus

Dave Leigh

Web, and long time Sitecore developer based in Bristol, UK, working at True Clarity - trueclarity.co.uk - @technologytalks - Minion.
I occasionally do other things too.