2012-06-27 32 views
5

Quiero cambiar mis vistas en MVC 3 entre dos idiomas: PL y EN. Creé dos carpetas en Views: EN y PL. Así que después de hacer clic en enlace de un lenguaje apropiado en cualquier sitio Quiero que mi cambio de ruta a partir de:¿Cómo cambiar las rutas globalmente?

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

a:

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

Al hacer clic en enlace correspondiente (selector de idiomas) cambia CultureInfo que es persistente en todas las roscas . _Layout View con conmutador:

<ul> 
    <li>@Html.ActionLink("En", "ChangeCulture", null, new { lang = "en"}, null)</li> 
    <li>@Html.ActionLink("Pl", "ChangeCulture", null, new { lang = "pl"}, null)</li> 
</ul> 

y el controlador (que establece también variable estática lang que se puede ver en el método de todos los controladores y ser persistente entre peticiones):

public ActionResult ChangeCulture(string lang) 
    { 

     PLController.lang = lang; 
     CultureSettings setCulture = new CultureSettings(); 
     setCulture.InitializeCulture(lang); 
     cookie.Value = CultureInfo.CurrentCulture.Name; 
     this.ControllerContext.HttpContext.Response.Cookies.Add(cookie); 
     return View("Index"); 
    } 

método InitializeCulture se overriden de la página clase de la siguiente manera:

public class CultureSettings : Page{ 

    public void InitializeCulture(string culture) 
    { 
      String selectedLanguage; 
      if(culture == null) 
      { 
       selectedLanguage = "pl"; 
      } 
      else 
      { 
       selectedLanguage = culture; 
      } 

      UICulture = selectedLanguage; 
      Culture = selectedLanguage; 

      Thread.CurrentThread.CurrentCulture = 
       CultureInfo.CreateSpecificCulture(selectedLanguage); 
      Thread.CurrentThread.CurrentUICulture = new 
       CultureInfo(selectedLanguage); 

     base.InitializeCulture(); 
    } 
} 

Establece CultureInfo correctamente. Ahora quiero (de acuerdo con CultureInfo actual) cambiar las rutas para cada enlace de navegación y cambiar el patrón de ruta desde mysite.com/PL/{controller}/{action} a mysite.com/EN/{controller}/{action}.

¿Alguien tiene alguna idea o mejor enfoque para este problema? Pero la condición es que la dirección debe verse como esta mysite.com/EN o mysite.com/PL - no diferente (es decir, en.mysite.com)

Respuesta

6

Lo primero que debe decidir es dónde almacenar el usuario actual idioma. Hay diferentes posibilidades:

  • parte de cada url
  • galletas
  • sesión

mi humilde opinión para fines de SEO es mejor tenerlo como parte de la URL.

por lo que recomiendo escribir una ruta personalizada que analizar el lenguaje de la URL y establecer la cultura hilo actual:

public class LocalizedRoute : Route 
{ 
    public LocalizedRoute() 
     : base(
      "{lang}/{controller}/{action}/{id}", 
      new RouteValueDictionary(new 
      { 
       lang = "en-US", 
       controller = "home", 
       action = "index", 
       id = UrlParameter.Optional 
      }), 
      new RouteValueDictionary(new 
      { 
       lang = @"[a-z]{2}-[a-z]{2}" 
      }), 
      new MvcRouteHandler() 
     ) 
    { 
    } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     var rd = base.GetRouteData(httpContext); 
     if (rd == null) 
     { 
      return null; 
     } 

     var lang = rd.Values["lang"] as string; 
     if (string.IsNullOrEmpty(lang)) 
     { 
      // pick a default culture 
      lang = "en-US"; 
     } 

     var culture = new CultureInfo(lang); 

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

     return rd; 
    } 
} 

Ahora puede registrar esta ruta personalizada en Global.asax:

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

    routes.Add("Default", new LocalizedRoute()); 
} 

bien, ahora vamos a tener un modelo:

public class MyViewModel 
{ 
    [DisplayFormat(DataFormatString = "{0:d}")] 
    public DateTime Date { get; set; } 
} 

a c ontroller:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel 
     { 
      Date = DateTime.Now 
     }); 
    } 

    public ActionResult Test() 
    { 
     return Content(DateTime.Now.ToLongDateString()); 
    } 
} 

y una vista:

@model MyViewModel 

@Html.DisplayFor(x => x.Date) 

<ul> 
    <li>@Html.ActionLink("switch to fr-FR", "index", new { lang = "fr-FR" })</li> 
    <li>@Html.ActionLink("switch to de-DE", "index", new { lang = "de-DE" })</li> 
    <li>@Html.ActionLink("switch to en-US", "index", new { lang = "en-US" })</li> 
</ul> 

@Html.ActionLink("Test culture", "test") 

Ahora, cuando hace clic en los enlaces que están cambiando el lenguaje y este lenguaje es ahora parte de las rutas. Observe cómo una vez que ha elegido el idioma, este idioma se persiste en las rutas para el enlace test.

Scott Hanselman también escribió un nice blog post sobre localización y globalización en ASP.NET que vale la pena consultar.

+1

¡muchas gracias! ¡Probaré este enfoque! – lukaleli

+0

y también tengo otra pregunta para usted porque no está funcionando:/ No sé por qué, pero creo que las rutas no se configuran después de que se inicia la aplicación. Hay un error: Error del servidor en la aplicación '/'. El recurso no se puede encontrar. Descripción: HTTP 404. El recurso que está buscando (o una de sus dependencias) podría haberse eliminado, haber cambiado su nombre o no estar disponible temporalmente. Revise la siguiente URL y asegúrese de que esté escrita correctamente. URL solicitada:/ ¿Alguna idea? Soy totalmente novato en ASP.NET y MVC – lukaleli

+0

Ok, está funcionando ahora. Olvidé cambiar el nombre del controlador;) – lukaleli

0

Esta solución no va a resolver este problema:

english: /en/home 

french: /fr/accueil 

english: /en/contactus 

french: /fr/contacteznous 

Se acaba de hacer

/en/home 

/fr/home 

También debe localizar las rutas en un diccionario y hacer una búsqueda.

Cuestiones relacionadas