Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to route a multiple language URL with a MVC

I need multi-language URL route of existing controller. Let me explain more:

I have a controller with name "Product" and View with name "Software"; therefore, by default if the user enters "http://example.com/en/Product/Software", get right content (that really exists in http://example.com/Product/Software),

However, if another user -- a French user -- types "http://example.com/fr/Produits/logiciels", must get above controller and show with right content (same http://example.com/Product/Software but with French text).

Note: I set the route table with "{language}/{controller}/{action}/{id}"

Any other invalid URL must show the 404 page.

Is it possible?

like image 788
Hamid Avatar asked Jan 27 '10 10:01

Hamid


People also ask

Can we have multiple routes in MVC?

Multiple Routes You need to provide at least two parameters in MapRoute, route name, and URL pattern. The Defaults parameter is optional. You can register multiple custom routes with different names.

How will you localize URL in MVC application?

To offer a website in multiple languages using ASP.Net we simply need to add some resource. resx files to our project and voilà. Based on the language of the browser, IIS will match the localization resource.

What is URL routing in MVC?

The ASP.NET MVC framework includes a flexible URL routing system that enables you to define URL mapping rules within your applications. The routing system has two main purposes: Map incoming URLs to the application and route them so that the right Controller and Action method executes to process them.


3 Answers

Building upon Dan's post, I'm using the beneath for translating my controller and action names.

I created a table to store the values, this could and probably should be held in the resource files to keep everything together; however I used a database table as it works better with my companies processes.

CREATE TABLE [dbo].[RoutingTranslations](
[RouteId] [int] IDENTITY(1,1) NOT NULL,
[ControllerName] [nvarchar](50) NOT NULL,
[ActionName] [nvarchar](50) NOT NULL,
[ControllerDisplayName] [nvarchar](50) NOT NULL,
[ActionDisplayName] [nvarchar](50) NOT NULL,
[LanguageCode] [varchar](10) NOT NULL)

The RouteConfig.cs file was then changed to:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        //Build up routing table based from the database.  
        //This will stop us from having to create shedloads of these statements each time a new language, controller or action is added
        using (GeneralEntities db = new GeneralEntities())
        {
            List<RoutingTranslation> rt = db.RoutingTranslations.ToList();
            foreach (var r in rt)
            {
                routes.MapRoute(
                    name: r.LanguageCode + r.ControllerDisplayName + r.ActionDisplayName,
                    url: r.LanguageCode + "/" + r.ControllerDisplayName + "/" + r.ActionDisplayName + "/{id}",
                    defaults: new { culture = r.LanguageCode, controller = r.ControllerName, action = r.ActionName, id = UrlParameter.Optional },
                    constraints: new { culture = r.LanguageCode }
                );
            }                
        }

        //Global catchall
        routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new {culture = CultureHelper.GetDefaultCulture(), controller = "Default", action = "Index", id = UrlParameter.Optional }
            //defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }
}

By default this will always use the English controller and action names, but allows you to provide an override by entering the values into the table.

(My internationalization code is largely based from this great blog post. http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx)

like image 185
Jay Avatar answered Oct 02 '22 02:10

Jay


As has been suggested before, this does depart from convention where the website urls (and routes) use English.

Nevertheless, it is possible, but in order to do it, you'll probably have to look at generating one route per action for every foreign language. So for a website with 20 actions and three languages (English, French, and German), you'll need 41 routes (20 French, 20 German and 1 English). Not the most efficient system, I admit, but it works as you want it to.

//You'll only need one of these, which is the default.
routes.MapRoute(
  "English route",
  "en/{controller}/{action}/{id}"
  new { controller = "Home", action = "Index", language = "en" },
);

routes.MapRoute(
  "FrenchHome",
  "fr/Demarrer/Index/{id}",
  new { controller = "Home", action = "Index", language = "fr" }
);

routes.MapRoute(
  "GermanHome",
  "de/Heim/Index/{id}", //'Heim' is, I believe the correct usage of Home in German.
  new { controller = "Home", action = "Index", language = "de" }
);

//Some more routes...

routes.MapRoute(
  "FrenchSoftware",
  "fr/Produit/Logiciels/{id}",
  new { controller = "Product", action = "Software", language = "fr" }
);

routes.MapRoute(
  "GermanSoftware",
  "de/Produkt/Software/{id}", //In this instance, Software should be the same in German and English.
  new { controller = "Product", action = "Software", language = "de" }
);

//And finally, the 404 action.
routes.MapRoute(
  "Catchall",
  "{language}/{*catchall}",
  new { controller = "Home", action = "PageNotFound", language = "en" },
  new { language = "^(en|fr|de)$" }
);

//This is for the folks who didn't put a language in their url.
routes.MapRoute(
  "Catchall",
  "{*catchall}",
  new { controller = "Home", action = "PageNotFound", language = "en" }
);

In your actions, for example Product/Software...

public ActionResult Software(string language, int id)
{
  //This would go off to the DAL and get the content in whatever language you want.
  ProductModel model = ProductService.GetSoftware(language, id);

  return View(model);
}

I would LOVE it if somebody came along and said that there's a better way of doing this, because I agree that having the url in a foreign language isn't good, and given that the Internet itself is moving towards allowing non-Roman characters in urls, the sooner we look at solutions to this, the better.

Not only that, but I know proud French people don't like to see their website urls contain English. :)

like image 6
Dan Atkinson Avatar answered Oct 02 '22 02:10

Dan Atkinson


You should have url something like "http://mysite.com/en/Product/Software" for English and "http://mysite.com/fr/Product/Software" for French, which would make much sense.

Use the same view for both.

Happy coding.

like image 2
Ravi Vanapalli Avatar answered Oct 02 '22 01:10

Ravi Vanapalli