Localization of URLs using ASP.NET MVC, Routing & Constraints


Developing a multilingual website, besides localization of the page’s content it also makes sense to localize the URLs. In my first post dealing with localization I explained my basic approach how to localize pages using a derived MvcRouteHandler and a subtype of Route. In this post I am going to show a possibility to localize URLs by using routes and constraints.

What I want

1) I am going to have a search on my new site. I want this search page to have nice localized URLs for the different languages. The term “search” of the URL should be translated to each supported language.

Examples:

USA mysite.com/en-US/Search
Great Britain mysite.com/en-GB/Search
Germany mysite.com/de-DE/Suche
Switzerland mysite.com/de-CH/Suche
Italy mysite.com/it-IT/Ricerca

2) Furthermore I want to have URLs with the same ending for different languages. This ist usefull for URLs, which do not have to be translated.

Examples:

USA mysite.com/en-US/FAQ
Great Britain mysite.com/en-GB/FAQ
Germany mysite.com/de-DE/FAQ
Switzerland mysite.com/de-CH/FAQ
Italy mysite.com/it-IT/FAQ

Approach

1) This can be done by registering different routes and using custom constraints. I did it like this:


public static void RegisterRoutes(RouteCollection routes)
{
    LanguageConstraint enLanguageConstraint = new LanguageConstraint("en");
    LanguageConstraint deLanguageConstraint = new LanguageConstraint("de");

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(
        new MultiLingualRoute("FAQ",
        new RouteValueDictionary(new { controller = "CMS", action = "Show", Id = 1 }),
        new RouteValueDictionary(new { validCountry = new CulturesConstraint() }),
        new MvcApplication1.MultiLingualMvcRouteHandler())
    );

    routes.Add(
        new MultiLingualRoute("Suche",
        new RouteValueDictionary(new { controller = "Search", action = "AdvancedSearch" }),
        new RouteValueDictionary(new { validLanguage = deLanguageConstraint }),
        new MvcApplication1.MultiLingualMvcRouteHandler())
    );

    routes.Add(
        new MultiLingualRoute("Search",
        new RouteValueDictionary(new { controller = "Search", action = "AdvancedSearch" }),
        new RouteValueDictionary(new { validLanguage = enLanguageConstraint }),
        new MvcApplication1.MultiLingualMvcRouteHandler())
    );

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    );            

    foreach (Route r in routes)
    {
        if (r.GetType() == typeof(MultiLingualRoute))
        {
            r.Url = "{culture}/" + r.Url;
            r.Defaults.Add("culture", "en-US");
        }
    }
}

At the first lines two LanguageConstraints are created. These constraints make sure, that this route is only used, if the given language is used.


public class LanguageConstraint : IRouteConstraint
{
    string Language { set; get; }

    /// <summary>
    /// Creates a new lanugage constraint
    /// </summary>
    /// <param name="Language">Allowed lanuage</param>
    public LanguageConstraint(string language)
    {
        Language = language;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        String CultureFromRoute = values["culture"].ToString();

        try
        {
            if (CultureFromRoute.Length > 2 &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; CultureFromRoute.StartsWith(Language))
            {
                //validate, that the given culture from routeData is a valid culture
                System.Globalization.CultureInfo.GetCultureInfo(CultureFromRoute);
                return true;
            }

        }
        catch (Exception) { }
        return false;
    }
}

2) For those URLs with the same ending I crated a CulturesConstraint. This makes sure, that the page is only showed for given cultures


public class CulturesConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        List<String> CultureListe = new List<String>();
        CultureListe.Add("en-GB");
        CultureListe.Add("en-US");
        CultureListe.Add("de-DE");
        CultureListe.Add("it-IT");
        return CultureListe.Contains(values["culture"].ToString());
    }
}

Feel free to drop a line, Alebo

  1. Bisher keine Kommentare.
(wird nicht veröffentlicht)

Spam Protection by WP-SpamFree

  1. Bisher keine Trackbacks.