2010-01-27 65 views
18

Necesito una ruta URL en varios idiomas del controlador existente. Permítanme explicar más:Cómo enrutar una URL de múltiples idiomas con un MVC

Tengo un controlador con el nombre "Producto" y Vista con el nombre "Software"; Por lo tanto, por defecto si el usuario introduce "http://example.com/en/Product/Software", obtener contenido correcto (que realmente existe en http://example.com/Product/Software),

Sin embargo, si otro usuario - un usuario francés - "tipos" http://example.com/fr/Produits/logiciels, debe obtener por encima de controlador y espectáculo con contenido correcto (el mismo http://example.com/Product/Software pero con texto en francés).

Nota: He definido la tabla de rutas con "lenguaje {}/{controlador}/{acción}/{id}"

cualquier otra URL inválida debe mostrar la página 404.

¿Es posible?

+0

En realidad, esa no es una muy buena idea si te preocupa la clasificación de los motores de búsqueda. Puede redireccionar a la página en inglés siempre O usar una URL canónica estándar para todas las instancias de la misma entidad. –

Respuesta

6

Según la publicación de Dan, estoy usando lo de abajo para traducir mis nombres de controlador y acción.

Creé una tabla para almacenar los valores, esto podría y probablemente debería guardarse en los archivos de recursos para mantener todo junto; sin embargo, utilicé una tabla de base de datos, ya que funciona mejor con los procesos de mi empresa.

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) 

El archivo RouteConfig.cs entonces fue cambiado a:

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 } 
     ); 

    } 
} 

Por defecto siempre utilizará el controlador y la acción nombres en inglés, pero le permite proporcionar una anulación mediante la introducción de los valores en la mesa.

(Mi código de internacionalización se basa en gran parte de esta gran entrada de blog. http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx)

+0

Sin embargo, esto no funcionará con las rutas recién agregadas, ya que desde las rutas de registro solo se ejecuta un inicio? – alex

4

Como se ha sugerido anteriormente, esto se aparta de la convención donde las URL del sitio web (y las rutas) usan el inglés.

Sin embargo, es posible, pero para poder hacerlo, probablemente deba considerar generar una ruta por acción para cada idioma extranjero. Entonces, para un sitio web con 20 acciones y tres idiomas (inglés, francés y alemán), necesitará 41 rutas (20 en francés, 20 en alemán y 1 en inglés). No es el sistema más eficiente, lo admito, pero funciona como usted lo desea.

//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" } 
); 

En sus acciones, por ejemplo Producto/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); 
} 

lo haría AMOR que si alguien llegó y dijo que hay una mejor manera de hacer esto, porque estoy de acuerdo que tener la url en un idioma extranjero no es bueno, y dado que Internet se está moviendo para permitir el uso de caracteres no romanos en las URL, mientras más pronto veamos soluciones a esto, mejor.

No solo eso, sino que sé que a los orgullosos franceses no les gusta ver que las URL de sus sitios web contengan inglés. :)

+1

(alguien que viene con una mejor manera ...) ¿Qué hay de no importar lo que se pasa al método de acción? En cambio, enrutarlo como de costumbre. Pero tiene una sobrecarga para OnActionExecuting() en su (s) controlador (es) base (s) que establece (n) la CultureUI en función de la ruta (por ejemplo, podría ver el Request.Url en el filterContext). O una versión más fuertemente tipada sería crear su propia clase LangaugeRoute() que hereda de Route. Agregue una nueva propiedad en él, LanguageCode, y configúrelo en su MapRoute aquí en su respuesta. Luego, puede convertirlo fuertemente en su OnActionExecuting(). – eduncan911

+0

Me gusta esto, pero comprobar la cultura actual tiene sus riesgos, principalmente en relación con la posibilidad de que no tenga realmente una versión del sitio web. Por ejemplo, el turco tiene bastantes problemas en lo que respecta a Cultura (Google, el problema turco-i). En cualquier caso, tendrá que crear un montón de sentencias if/else o casing en alguna parte para manejar las traducciones que tiene para cambiar a otra si no es correcto. –

+1

Además, esta es una excelente publicación de blog de Maarten Balliauw sobre el tema. http://blog.maartenballiauw.be/post/2010/01/26/Translating-routes-(ASPNET-MVC-and-Webforms).aspx –

0

os recomiendo el siguiente enfoque para implementar el multi-idioma en una aplicación web MVC 5 (y <), porque encuentro es el más versátil entre los que he probado en los últimos años.

que básicamente necesita para implementar tres cosas:

  • Un multi-idioma ruta conscientes para manejar las direcciones URL entrantes (si está usando MVC5 o superior también se puede ir para enrutamiento basado en Atributo en su lugar, pero aún prefiero usar una regla global para manejar esto).
  • A LocalizationAttribute para manejar este tipo de solicitudes multilingües.
  • Método de ayuda para generar estas URL dentro de su aplicación (Html.ActionLink y/o Url.Action métodos de extensión).

Consulte this answer para obtener más detalles y ejemplos de código.

Para obtener más información y más muestras sobre este tema, también puede leer this post.

Cuestiones relacionadas