2010-01-27 11 views
18

Tôi cần tuyến đường URL đa ngôn ngữ của bộ điều khiển hiện có. Để tôi giải thích thêm:Cách định tuyến một URL đa ngôn ngữ với một MVC

Tôi có bộ điều khiển có tên "Sản phẩm" và Chế độ xem có tên "Phần mềm"; do đó, theo mặc định nếu người dùng nhập "http://example.com/en/Product/Software", nhận nội dung phù hợp (thực sự tồn tại trong http://example.com/Product/Software),

Tuy nhiên, nếu người dùng khác - người dùng Pháp - loại "http://example.com/fr/Produits/logiciels", phải vượt qua trình điều khiển và hiển thị với nội dung phù hợp (cùng một số http://example.com/Product/Software nhưng với văn bản tiếng Pháp).

Lưu ý: Tôi thiết lập các bảng định tuyến với "{ngôn ngữ}/{controller}/{action}/{id}"

Bất kỳ URL không hợp lệ khác phải hiển thị trang 404.

Có thể không?

+0

Thực ra đó không phải là ý tưởng hay nếu bạn lo ngại về xếp hạng công cụ tìm kiếm. Bạn có thể chuyển hướng đến trang tiếng Anh luôn HOẶC sử dụng URL chuẩn chuẩn cho tất cả các phiên bản của cùng một thực thể. –

Trả lời

6

Xây dựng theo bài của Dan, tôi đang sử dụng phần bên dưới để dịch bộ điều khiển và tên hành động của mình.

Tôi đã tạo một bảng để lưu trữ các giá trị, điều này có thể và có lẽ nên được giữ trong các tệp tài nguyên để giữ mọi thứ lại với nhau; tuy nhiên tôi đã sử dụng một bảng cơ sở dữ liệu vì nó hoạt động tốt hơn với các quy trình công ty của tôi.

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) 

Các RouteConfig.cs tập tin sau đó được đổi thành:

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

    } 
} 

Theo mặc định này sẽ luôn luôn sử dụng bộ điều khiển và hành động tên tiếng Anh, nhưng cho phép bạn để cung cấp một ghi đè bằng cách nhập các giá trị vào bàn.

(mã quốc tế của tôi chủ yếu dựa từ bài đăng blog tuyệt vời này. http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx)

+0

Tuy nhiên, tính năng này sẽ không hoạt động với các tuyến mới được thêm vào, vì nó sẽ chỉ thực thi khi khởi động? – alex

2

Bạn phải có url giống như "http://mysite.com/en/Product/Software" cho tiếng Anh và "http://mysite.com/fr/Product/Software" cho tiếng Pháp, điều này sẽ có ý nghĩa nhiều.

Sử dụng cùng một chế độ xem cho cả hai.

Mã hóa vui vẻ.

+0

Điều này có nghĩa là các URL không thân thiện, vì không phải tất cả mọi người trên thế giới đều nói tiếng Anh – erikkallen

+0

Theo mặc định, bạn nên sử dụng tiếng Anh erikkallen – Ravia

+0

lý do tại sao bạn bỏ phiếu xuống là – Ravia

4

Như đã được đề xuất trước đây, điều này sẽ khởi hành từ quy ước nơi url trang web (và tuyến đường) sử dụng tiếng Anh.

Tuy nhiên, có thể, nhưng để làm điều đó, bạn có thể sẽ phải xem xét việc tạo ra một lộ trình cho mỗi hành động cho mọi ngôn ngữ nước ngoài. Vì vậy, đối với một trang web với 20 hành động và ba ngôn ngữ (tiếng Anh, tiếng Pháp và tiếng Đức), bạn sẽ cần 41 tuyến đường (20 tiếng Pháp, 20 tiếng Đức và 1 tiếng Anh). Không phải là hệ thống hiệu quả nhất, tôi thừa nhận, nhưng nó hoạt động như bạn muốn nó.

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

Trong hành động của bạn, ví dụ như sản phẩm/Phần mềm ...

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

tôi sẽ TÌNH YÊU nó nếu ai đó đến cùng và nói rằng có một cách tốt hơn để làm điều này, bởi vì tôi đồng ý rằng có url trong một ngôn ngữ nước ngoài là không tốt, và cho rằng Internet chính nó đang di chuyển theo hướng cho phép các ký tự không phải La Mã trong url, chúng ta càng sớm xem xét các giải pháp cho điều này, thì càng tốt.

Không chỉ vậy, nhưng tôi biết những người Pháp tự hào không thích nhìn thấy url trang web của họ có chứa tiếng Anh. :)

+1

(ai đó đến cùng với một cách tốt hơn ...) Điều gì về không quan tâm những gì được thông qua vào phương pháp hành động? Thay vào đó, hãy định tuyến nó như bình thường. Nhưng có một tình trạng quá tải cho OnActionExecuting() trên (các) bộ điều khiển cơ bản của bạn để đặt CultureUI phù hợp dựa trên tuyến đường (ví dụ: nó sẽ nhìn vào Request.Url trong filterContext). Hoặc một phiên bản được đánh máy mạnh mẽ hơn là tạo ra lớp LangaugeRoute() của riêng bạn mà kế thừa từ Route. Thêm một thuộc tính mới vào nó, LanguageCode, và đặt nó trong MapRoute của bạn ở đây trong câu trả lời của bạn. Sau đó, bạn có thể cast nó mạnh mẽ-gõ trong OnActionExecuting() của bạn. – eduncan911

+0

Tôi thích điều này, nhưng việc kiểm tra văn hóa hiện tại có những rủi ro của nó, chủ yếu liên quan đến khả năng bạn thực sự không có phiên bản của trang web. Ví dụ, Thổ Nhĩ Kỳ có khá nhiều vấn đề khi nói đến Văn hóa (Google là vấn đề Thổ Nhĩ Kỳ-i). Trong mọi trường hợp, bạn sẽ phải tạo một loạt các câu lệnh if/else hoặc casing ở đâu đó để xử lý các bản dịch mà bạn có để mặc định bản dịch khác nếu nó không đúng. –

+1

Ngoài ra, đây là một bài đăng blog tuyệt vời của Maarten Balliauw về chủ đề này. http://blog.maartenballiauw.be/post/2010/01/26/Translating-routes-(ASPNET-MVC-and-Webforms).aspx –

0

tôi khuyên các phương pháp sau đây để thực hiện đa ngôn ngữ trong một ứng dụng web MVC 5 (và <), bởi vì tôi tìm nó là một trong những linh hoạt nhất trong số những người tôi đã cố gắng trong những năm gần đây nhất.

Bạn về cơ bản cần phải thực hiện ba điều:

  • Một đa ngôn ngữ nhận thức được con đường để xử lý các URL đến (nếu bạn đang sử dụng MVC5 hoặc cao hơn bạn cũng có thể đi cho Thuộc tính dựa trên định tuyến thay vào đó, nhưng tôi vẫn thích sử dụng một quy tắc toàn cầu để xử lý điều này).
  • LocalizationAttribute để xử lý các loại yêu cầu đa ngôn ngữ này.
  • Phương pháp trợ giúp để tạo các URL này trong ứng dụng của bạn (Html.ActionLink và/hoặc Url.Action phương pháp mở rộng).

Xem this answer để biết thêm chi tiết và mẫu mã.

Để biết thêm thông tin và các mẫu khác về chủ đề này, bạn cũng có thể đọc this post.