Setting up multilingual MVC projects

Setting up multilingual projects greatly depends on the routing scheme of your MVC project. If your site uses content tree-based routing, detecting and setting the current culture for each request is handled automatically. If your site uses conventional ASP.NET routing, you need to set up and handle the functionality for detecting and setting the current culture manually.

You can then assign cultures to your site in Xperience, and localize the content displayed on the site's pages. Finally, content editors can then edit and translate content of the individual pages.

Setting up projects with content tree-based routing

Once you have enabled and set up content tree-based routing, the functionality for detecting and setting the current culture for each request is handled automatically by the system. You can then:

In addition to the routing handled by the system, you can also set up routing for pages not represented in the content tree by registering routes using conventional routing provided by ASP.NET. That is, pages not matched by the system router can be always matched by custom routes.

For more information about how to set up custom routing, see Combining content tree-based and ASP.NET routing and the section below.

Setting up projects with custom routing

To serve content in multiple languages on sites that use a custom routing scheme (i.e., conventional ASP.NET routing), you first need to set up functionality that detects and sets the current culture for each request.

At the beginning of every request, you need to:

  1. Retrieve or determine the correct culture to be used in the current request.
    • The way you detect the culture depends on the implementation of your multilingual site. For example, you can use language prefixes in URLs, culture-specific domains, or custom cookies.
  2. Set the Thread.CurrentThread.CurrentUICulture and Thread.CurrentThread.CurrentCulture properties of the current thread (available in the System.Threading namespace).

    If you detect culture using language prefixes in URLs or using culture-specific domains, we recommend using the SiteCultureConstraint (Kentico.Content.Web.Mvc namespace) provided by the Xperience API. The constraint supplies the culture for the current thread automatically based on the following process:

    • detect and validate the culture against site cultures,
    • determine default culture according to the following priorities (first that applies):
      • browser culture
      • default culture (from application settings),
    • set the CurrentUICulture and CurrentCulture properties of the current thread.

    Moreover, the constraint allows you to hide the language prefix in URLs for the default content culture:

    1. Set the constraint's HideLanguagePrefixForDefaultCulture property to true.
    2. Register a custom route without a culture parameter in the URL pattern for the default culture URLs.
    3. Manually set the CurrentUICulture and CurrentCulture properties for the custom route.

    See the example below.

    Note: Thread.CurrentThread.CurrentUICulture and Thread.CurrentThread.CurrentCulture are properties of the .NET framework and use the System.Globalization.CultureInfo type. They are not directly comparable with the CMS.Localization.CultureInfo type, or the CurrentUICulture and CurrentCulture properties of the CMS.Localization.LocalizationContext class provided by the Xperience API.

The Xperience localization API then automatically works with the given culture (for example when resolving resource strings).

You can now:

Example

One common way to determine the culture of requests is to use language prefixes in your site's routes. For example:

  • English – www.example.com/en-us/path
  • Spanish – www.example.com/es-es/path

This example shows how to parse the culture from the route prefix and set the current culture for the MVC application using the system constraint SiteCultureConstraint. It also demonstrates how to hide language prefixes in URLs for the site's default content culture (e.g. if English is set as the default culture, the URL www.example.com/en-us/path becomes www.example.com/path).

Example - RouteConfig.cs
using System.Web.Mvc;
using System.Web.Routing;


public static void RegisterRoutes(RouteCollection routes)
{
    ...

    // Matches a URL containing a culture route prefix
    routes.MapRoute(
        name: "Default",
        url: "{culture}/{controller}/{action}",
        defaults: new { controller = "Home", action = "Index" },
		constraints: new { culture = new SiteCultureConstraint() { HideLanguagePrefixForDefaultCulture = true} }
    );
	
	// Matches a URL with a hidden culture prefix
	// This route needs to be registered AFTER the route which strips the culture parameter from the URL ("Default" in this example)
    routes.MapRoute(
        name: "DefaultWithoutCulturePrefix",
        url: "{controller}/{action}",
        defaults: new { },
        constraints: new { culture = new SetDefaultCultureConstraint() }
     );

}
Example - SetDefaultCultureConstraint
using System.Globalization;
using System.Threading;
using System.Web;
using System.Web.Routing;
 
using CMS.Helpers;
using CMS.SiteProvider;


// Constraint for a route that parses URLs with a hidden culture prefix for the default culture
public class SetDefaultCultureConstraint : IRouteConstraint
{
    // Propagates default culture into the current thread
    public bool Match(HttpContextBase httpContext, 
    				Route route, 
    				string parameterName, 
    				RouteValueDictionary values, 
    				RouteDirection routeDirection)
    {
        var defaultCultureCode = CultureHelper.GetDefaultCultureCode(SiteContext.CurrentSiteName);
        var culture = new CultureInfo(defaultCultureCode);

        Thread.CurrentThread.CurrentUICulture = culture;
        Thread.CurrentThread.CurrentCulture = culture;

        return true; 
    }
}

You can use the SiteCultureConstraint constraint equally for when you detect cultures using culture-specific domains. When the constraint parameter ("culture" in this case) is not found in the URL scheme, the SiteCultureConstraint ensures the culture will be detected from the URL's domain.

SiteCultureConstraint with culture-specific domains
...

	var route = routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}",
        defaults: new { controller = "Home", action = "Index" },
        constraints: new { culture = new SiteCultureConstraint() }
    );

...

Was this page helpful?