2010-10-14 27 views
13

Tôi đang làm việc với một khách hàng muốn URL trong ứng dụng web của chúng tôi bằng tiếng Pháp. Tôi là một nhà phát triển tiếng Anh và chúng tôi cũng có khách hàng tiếng Anh. Đây là một vấn đề thú vị nhưng tôi không nghĩ rằng cái gì đó của ASP.NET MVC Framework sẽ hỗ trợ.Có thể bản địa hóa URL/định tuyến trong ASP.NET MVC không?

Đây là kịch bản. Các tuyến đường ...

ví dụ cụ thể
tiếng Anh URL
www.stackoverflow.com/questions/ask

cũng sẽ hỗ trợ

URL Pháp
www.stackoverflow.com/problème/poser

VÍ DỤ chung
tiếng Anh URL
http://clientA.product.com/AreaNameEnglish/ControllerNameEnglish/ActionNameEnglish/params

cũng cần hỗ trợ

URL Pháp
http://clientB.product.com/AreaNameFrench/ControllerNameFrench/ActionNameFrench/params

Vì vậy, trong MVC Diện tích của tôi, điều khiển và hành động tất cả cần phải có cả tiếng Anh và bản dịch tiếng Pháp.

Rõ ràng khả năng bảo trì sẽ là vấn đề HUGE nếu tôi đi và mã hóa tất cả các tên Bộ điều khiển, Chế độ xem và Hành động của tôi sang tiếng Pháp. Có anyway để bản địa hóa các tuyến đường được trình bày trong trình duyệt mà không làm điều này? Lưu ý rằng có rất nhiều tuyến đường khác nhau trong ứng dụng. Một vài khu vực với một số ít các bộ điều khiển mỗi với nhiều hành động?

Cảm ơn,
Justin

EDIT
Nhờ @womp đây là những gì tôi đã đi lên với cho đến nay ... Mặc dù cuối cùng thì tôi lấy phương pháp mà tôi được đăng như một câu trả lời .

public class LocalizedControllerFactory : DefaultControllerFactory 
{ 
    public override IController CreateController(RequestContext requestContext, string controllerName) 
    { 
     if (string.IsNullOrEmpty(controllerName)) 
      throw new ArgumentNullException("controllerName"); 

     if (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "fr") 
     { 
      controllerName = this.ReplaceControllerName(requestContext, controllerName); 
      this.ReplaceActionName(requestContext); 
      this.ReplaceAreaName(requestContext); 
     } 

     return base.CreateController(requestContext, controllerName); 
    } 

    private string ReplaceControllerName(RequestContext requestContext, string controllerName) 
    { 
     // would use the language above to pick the propery controllerMapper. For now just have french 
     Dictionary<string, string> controllerMapper = new Dictionary<string, string>() 
     { 
      {"frenchControllerA", "englishControllerA"}, 
      {"frenchControllerB", "englishControllerB"} 
     }; 

     return this.ReplaceRouteValue(requestContext, "controller", controllerMapper); 
    } 

    private void ReplaceAreaName(RequestContext requestContext) 
    { 
     // would use the language above to pick the propery areaMapper. For now just have french 
     Dictionary<string, string> areaMapper = new Dictionary<string, string>() 
     { 
      {"frenchAreaX", "englishAreaX"}, 
      {"frenchAreaY", "englishAreaY"} 
     }; 

     this.ReplaceRouteValue(requestContext, "area", areaMapper); 
    } 

    private void ReplaceActionName(RequestContext requestContext) 
    { 
     // would use the language above to pick the propery actionMapper. For now just have french 
     Dictionary<string, string> actionMapper = new Dictionary<string, string>() 
     { 
      {"frenchAction1", "englishAction1"}, 
      {"frenchAction2", "englishAction2"} 
     }; 

     this.ReplaceRouteValue(requestContext, "action", actionMapper); 
    } 

    private string ReplaceRouteValue(RequestContext requestContext, string paramName, Dictionary<string, string> translationLookup) 
    { 
     if (requestContext.RouteData.Values[paramName] == null) 
     { 
      return null; 
     } 

     string srcRouteValue = requestContext.RouteData.Values[paramName] as string; 
     if (srcRouteValue != null && translationLookup.ContainsKey(srcRouteValue)) 
     { 
      requestContext.RouteData.Values[paramName] = translationLookup[srcRouteValue]; 
     } 

     return requestContext.RouteData.Values[paramName] as string; 
    } 
} 

Khởi đầu tốt. Nếu tôi chỉ bản địa hóa ControllerName và ActionName trong Url, nó sẽ tìm và hiển thị View thích hợp. Tuy nhiên tôi có những vấn đề sau.

Diện tích Tên không thể được dịch
Phối khu vực có nghĩa là phương pháp Controller.View() thất bại trong việc tìm xem. Mặc dù tôi đã thay thế tên Khu vực trong ngữ cảnh yêu cầu nhưng phương thức ViewEngineCollection.Find() dường như không nhận được nó. Bất cứ nơi nào trong lớp điều khiển của tôi mà không "trở lại View()" không tìm thấy xem mặc định cho hành động của nó. Nếu tôi không bản địa hóa Khu vực thì các bước khác sẽ hoạt động.

RedirectToAction hoặc Html.ActionLink
Bất kỳ khi nào ứng dụng gọi RedirectToAction hoặc nếu tôi sử dụng một helper Html.ActionLink hoặc một cái gì đó tương tự các url tạo là những người Anh. Có vẻ như tôi sẽ phải thêm logic ở đâu đó có thể ở nhiều điểm để chuyển đổi một Url tiếng Anh sang tiếng Pháp (hoặc ngôn ngữ khác).

Trả lời

14

Blog sau đây chứa giải pháp hoàn chỉnh về vấn đề chính xác này. Nó thực sự là một giải pháp rất thanh lịch mà tôi rất khuyên bạn nên.

https://blog.maartenballiauw.be/post/2010/01/26/translating-routes-(aspnet-mvc-and-webforms).html

Note để làm cho nó làm việc cho khu vực tôi đã có thêm phương pháp mở rộng sau đây để "TranslatedRouteCollectionExtensions.cs" class của mình:

public static Route MapTranslatedRoute(this AreaRegistrationContext areaContext, string name, string url, object defaults, object routeValueTranslationProviders, bool setDetectedCulture) 
    { 
     TranslatedRoute route = new TranslatedRoute(
      url, 
      new RouteValueDictionary(defaults), 
      new RouteValueDictionary(routeValueTranslationProviders), 
      setDetectedCulture, 
      new MvcRouteHandler()); 

     route.DataTokens["area"] = areaContext.AreaName; 

     // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up 
     // controllers belonging to other areas 
     bool useNamespaceFallback = (areaContext.Namespaces == null || areaContext.Namespaces.Count == 0); 
     route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback; 

     areaContext.Routes.Add(route); 

     return route; 
    } 

Tuy nhiên, ngay cả với điều này một con đường dịch với một KHU VỰC có thể được đọc và giải thích các tuyến đường được tạo luôn có vẻ như bao gồm một tên AREA tiếng Anh nhưng địa phương hóa mọi thứ khác.

Tôi đã được chuyển hướng đến một blog thông qua cùng một câu hỏi được yêu cầu trên ASP.NET MVC Forums

+0

Rất đẹp. Về cơ bản nó là khái niệm tương tự, ngoại trừ đóng gói trong định tuyến, thay vì trong logic điều khiển instantiation. Tôi đồng ý, nó có lẽ thanh lịch hơn một chút, có vẻ như một miền phù hợp hơn cho giải pháp. – womp

+0

Tôi biết đây là một bài đăng cũ, nhưng bạn chỉ cần lưu da của tôi. Câu trả lời chính xác! –

3

Khung MVC hỗ trợ khá nhiều kịch bản định tuyến mà bạn có thể nghĩ đến, nhưng không nhất thiết với các lớp định tuyến mặc định.

Hầu hết các giải pháp bản địa hóa mà tôi đã chạy đều liên quan đến việc sử dụng cùng tên của Phương thức điều khiển và hành động, nhưng chỉ định tham số văn hóa trong tuyến mà phiên bản phiên bản của Chế độ xem được dịch. Ví dụ:

http://clientA.product.com/AreaName/Controller/Action //en-US 
http://clientB.product.com/es-MX/AreaName/Controller/Action // spanish 

Nếu bạn thực sự phải dịch URL, tôi không thấy nhiều lựa chọn khác để duy trì bảng ánh xạ ở đâu đó. Nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn cần có khả năng ánh xạ tất cả các bản dịch ngôn ngữ khác nhau của "câu hỏi" và "hỏi" (hành động) cho cùng một kết hợp điều khiển/hành động.

Tuy nhiên, khi bạn đã xây dựng bảng này ở đâu đó (tệp tài nguyên?), Bạn có thể dễ dàng ghi đè lên khung DefaultControllerFactory mà đang sử dụng và thực hiện logic của riêng bạn để xác định bộ điều khiển để khởi tạo. Vì vậy, thay vì chỉ khớp mã thông báo {controller} từ URL dưới dạng so sánh chuỗi đơn giản, bạn có thể triển khai lôgic để kiểm tra nó so với bảng ánh xạ của bạn để chọn bộ điều khiển phù hợp.

Để có hướng dẫn về cách tạo nhà máy sản xuất bộ điều khiển tùy chỉnh, check this great blog post. Nó thực sự là một ví dụ địa phương hóa là tốt, nhưng nó dựa trên cài đặt văn hóa của người dùng, chứ không phải là ngôn ngữ của URL.

+0

Rất thú vị. Tôi đang nhìn vào nó. Cảm ơn bạn đã bắt đầu. – Justin

+0

Bạn được chào đón, chúc bạn may mắn với nó. Nếu câu trả lời của tôi có ích chút nào, đừng quên upvote :) – womp

+0

Tôi đang mắc kẹt trên Request.Header. Tôi đang xem xét nó, nhưng nếu bạn có thể cho tôi biết làm thế nào để cấu hình teh "ex-MX" một phần được giải thích như là một tiêu đề yêu cầu nó sẽ giúp đỡ. Tôi không thể tìm thấy nó bài đăng blog mẫu. Tôi đã có thể mong đợi nó là một phần của RouteTable trong tập tin Global.asax.cs nhưng không đi. – Justin

Các vấn đề liên quan