2010-01-27 23 views
18

Ho bisogno di un percorso URL multi-lingua del controller esistente. Lasciatemi spiegare altro:Come indirizzare un URL di più lingue con un MVC

Ho un controller con nome "Prodotto" e Visualizza con nome "Software"; Pertanto, per impostazione predefinita se l'utente immette "http://example.com/en/Product/Software", ottenere contenuti a destra (che esiste realmente in http://example.com/Product/Software),

Tuttavia, se un altro utente - un utente francese - tipi "http://example.com/fr/Produits/logiciels", deve ottenere sopra controller e spettacolo con il giusto contenuto (stesso http://example.com/Product/Software ma con testo francese).

Nota: ho impostato la tabella di route con "{lingua}/{Controller}/{action}/{id}"

Qualsiasi altro URL non valido deve mostrare la pagina 404.

È possibile?

+0

In realtà non è una buona idea se sei preoccupato per il ranking dei motori di ricerca. Puoi sempre reindirizzare alla pagina inglese sempre O utilizzare un URL canonico standard per tutte le istanze della stessa entità. –

risposta

6

Basandosi sul post di Dan, sto utilizzando il sotto per la traduzione dei nomi dei miei controller e azioni.

Ho creato una tabella per memorizzare i valori, questo potrebbe e probabilmente dovrebbe essere contenuto nei file delle risorse per tenere tutto insieme; tuttavia ho usato una tabella di database perché funziona meglio con i miei processi aziendali.

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) 

Il file RouteConfig.cs è stato poi cambiato in:

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

    } 
} 

Di default questo sarà sempre utilizzare il controller e azione nomi inglesi, ma consente di fornire un override inserendo i valori in tavolo.

(Il mio codice di internazionalizzazione si basa prevalentemente da questo grande post sul blog. http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx)

+0

Tuttavia, questo non funzionerà con le rotte aggiunte di recente, dal momento che i percorsi di registrazione vengono eseguiti solo all'avvio? – alex

4

Come è stato suggerito prima, questo non parte dalla convenzione in cui gli URL del sito Web (e le route) utilizzano l'inglese.

Tuttavia, è possibile, ma per farlo, probabilmente dovrai cercare di generare un percorso per azione per ogni lingua straniera. Pertanto, per un sito Web con 20 azioni e tre lingue (inglese, francese e tedesco), sono necessari 41 percorsi (20 francesi, 20 tedeschi e 1 inglese). Non è il sistema più efficiente, lo ammetto, ma funziona come vuoi tu.

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

nelle vostre azioni, per esempio prodotto/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); 
} 

vorrei AMORE se qualcuno è arrivato e ha detto che c'è un modo migliore di fare questo, perché sono d'accordo che avere l'url in una lingua straniera non è buono, e dato che Internet stessa si sta muovendo verso la possibilità di includere caratteri non romani negli url, prima cerchiamo soluzioni a questo, meglio è.

Non solo, ma so che i francesi orgogliosi non amano vedere gli URL dei loro siti Web contenenti l'inglese. :)

+1

(qualcuno sta arrivando con un modo migliore ...) Che dire non preoccuparsi di ciò che viene passato nel metodo di azione? Invece, instradarlo come normale. Ma ha un sovraccarico per OnActionExecuting() sul tuo controller di base che imposta CultureUI di conseguenza in base alla rotta (ad es. Dovrebbe dare un'occhiata a Request.Url nel filterContext). O una versione più fortemente tipizzata sarebbe quella di creare la tua classe LangaugeRoute() che eredita da Route. Aggiungi una nuova proprietà su di essa, LanguageCode, e impostalo nel tuo MapRoute qui nella tua risposta. Quindi, puoi scriverlo con forza nel tuo OnActionExecuting(). – eduncan911

+0

Mi piace, ma controllare l'attuale cultura ha i suoi rischi, principalmente in relazione alla possibilità che tu non abbia effettivamente una versione del sito web. Ad esempio, il turco ha alcuni problemi quando si tratta di cultura (Google il problema turco-i). In ogni caso, dovrai creare una serie di istruzioni if ​​/ else o casing da qualche parte per gestire le traduzioni che hai in modo da impostarle su un altro se non è corretto. –

+1

Inoltre, questo è un eccellente post sul blog di Maarten Balliauw sull'argomento. http://blog.maartenballiauw.be/post/2010/01/26/Translating-routes-(ASPNET-MVC-and-Webforms).aspx –

0

Consiglio vivamente il seguente approccio per implementare il multi-lingua in un MVC 5 (e <) applicazione web, perché trovo è il più versatile tra quelli che ho provato negli ultimi anni.

Che, fondamentalmente, devono attuare tre cose:

  • Un multi-lingua percorso consapevole per gestire gli URL in entrata (se si sta utilizzando MVC5 o sopra di voi potrebbe anche andare per il routing basato sugli attributi invece, ma preferisco comunque usare una regola globale per gestirlo).
  • Un LocalizationAttribute per gestire questo tipo di richieste multilingue.
  • Un metodo di supporto per generare questi URL all'interno dell'applicazione (metodi di estensione Html.ActionLink e/o Url.Action).

Vedere this answer per ulteriori dettagli e esempi di codice.

Per ulteriori informazioni e altri campioni su questo argomento si può anche leggere this post.

Problemi correlati