2015-09-15 15 views
21

Tôi đang cố gắng xây dựng một ứng dụng MVC đa ngôn ngữ là gì. Tôi có một mẫu đơn trong đơn đăng ký của mình và tôi có trường để nhập chi phí. Tôi có thể tạo ra một bản ghi sử dụng văn hóa Tây Ban Nha.Cách tốt nhất để xử lý xác thực với văn hóa khác nhau

Nhưng khi cố gắng cập nhật bản ghi, tôi nhận được xác thực jquery sai. và tôi nhận được thông báo lỗi mặc định là:

The field must be numeric.

Trong mô hình chế độ xem của tôi, tôi đã đặt các thuộc tính sau.

[LocalizedDisplayName("Label_Cost")] 
[RegularExpression("^[^<>,<|>]+$", ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Html_Tags_Prevented", ErrorMessageResourceType = typeof(Resources))] 
[Range(0, 9999.99, ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Cost_Not_Valid", ErrorMessageResourceType = typeof(Resources))] 
public decimal? Cost { get; set; } 

tôi đã thiết lập trong file Gobal.asax tôi với sau

protected void Application_AcquireRequestState(object sender, EventArgs e) 
{ 
    try 
    { 
     HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture"); 
     string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en"; 
     CultureInfo ci = new CultureInfo(culutureCode); 
     System.Threading.Thread.CurrentThread.CurrentUICulture = ci; 
     System.Threading.Thread.CurrentThread.CurrentCulture = 
     CultureInfo.CreateSpecificCulture(ci.Name); 
    } 
    catch(Exception ex) 
    { 
     // Code 
    } 
} 

và các phương pháp trên làm việc như mong đợi ở phía máy chủ trong việc thay đổi văn hóa. Tuy nhiên, xác thực bên ứng dụng khách phá vỡ trên nền văn hóa không phải tiếng Anh vì javascript chỉ nhận ra các chữ số thập phân. Tôi muốn biết cách tốt nhất để mở rộng xác thực phía máy khách mvc với xác thực văn hóa cụ thể.

EDIT

Với tham chiếu đến url của Mike Tôi đã thực hiện những thay đổi về Js bó sau. Js bó như sau

public static void RegisterBundles(BundleCollection bundles) 
{ 
    BundleTable.EnableOptimizations = true; 

    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
         "~/Scripts/jquery-{version}.js")); 

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
       "~/Scripts/globalize.js", 
       "~/Scripts/globalize/currency.js", 
       "~/Scripts/globalize/date.js", 
       "~/Scripts/globalize/message.js", 
       "~/Scripts/globalize/number.js", 
       "~/Scripts/globalize/plural.js", 
       "~/Scripts/globalize/relative-time.js")); 

    bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
       "~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js")); 

      bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
       "~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js")); 

      bundles.Add(new ScriptBundle("~/bundles/jqueryuiEN").Include(
         "~/Scripts/jquery-ui-1.10.3.js")); 

      bundles.Add(new ScriptBundle("~/bundles/jqueryuiES").Include(
         "~/Scripts/jquery-ui-1.10.3.js")); 

      bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
       "~/Scripts/jquery.validate.js", 
       "~/Scripts/jquery.validate.unobtrusive.js", 
       "~/Scripts/jquery.unobtrusive-ajax.js", 
       "~/Scripts/jquery.validate.globalize.js")); 
} 

Trong trang bố trí tôi đã thực hiện như sau

HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture"); 
     string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en"; 
     if (culutureCode.Equals("en-AU", StringComparison.OrdinalIgnoreCase)) 
     { 
      culutureCode = "EN"; 
     } 
     else if (culutureCode.Equals("es-AR", StringComparison.OrdinalIgnoreCase)) 
     { 
      culutureCode = "ES"; 
     } 
     else 
     { 
      culutureCode = "EN"; 
     } 
@Scripts.Render("~/bundles/jquery", 
        "~/bundles/globalisation", 
        string.Format("~/bundles/globalisation{0}", culutureCode), 
        "~/bundles/jqueryval", 
        string.Format("~/bundles/jqueryui{0}", culutureCode)) 
+0

Tôi không giỏi về thông tin Văn hóa, nhưng bạn có thể muốn lấy 'catch', mở rộng nó để bao gồm ngoại lệ chung và ghi vào bàn điều khiển (cho mục đích gỡ lỗi):' catch (Exception err) {Console.WriteLine (err); } 'Chúc may mắn! – jp2code

+0

Bạn đã xem xét giải pháp được đưa ra trong câu hỏi tương tự này: http://stackoverflow.com/questions/5199835/mvc-3-jquery-validation-globalizing-of-number-decimal-field –

+0

Tại sao bạn lại để trống bắt ngoại lệ và sau đó yêu cầu SO sửa lỗi này? –

Trả lời

23

Có 2 jQuery Toàn cầu hoá plugins.

Phiên bản cũ là v0.0.1 chứa một kịch bản globalize.js và nó có một thư mục con cultures nơi bạn có thể tìm thấy tất cả các nền văn hóa kịch bản như:

  • globalize.culture.en-AU.js
  • toàn cầu hoá. culture.es-AR.js

những kịch bản cho phép bạn thêm bao nhiêu nền văn hóa có muốn như vậy nó sẽ là hoàn toàn tốt đẹp đã bó bạn được xây dựng theo cách này:

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
    "~/Scripts/globalize.js", 
    "~/Scripts/cultures/globalize.culture.en-AU.js", 
    "~/Scripts/cultures/globalize.culture.es-AR.js" 
)); 

Globalize sẽ có một bộ sưu tập các kịch bản nội địa hóa mà bạn có thể thiết lập chỉ đơn giản sử dụng:

Globalize.culture('en-AU'); 

hoặc

Globalize.culture('es-AR'); 

Nó có thể sử dụng một số loại gần để tìm ra văn hóa gần nhất bạn muốn sử dụng. Nếu bạn đã tải trong gói globalize.culture.es-AR.js, bạn có thể đặt Globalize.culture('es');Globalize sẽ có thể tìm ra rằng bạn muốn sử dụng văn bản 'es-AR'; tất nhiên nếu bạn đã thêm globalize.culture.es.js trình tải sẽ chọn cái cuối cùng này.

Phiên bản mới của jQuery Globalize (ổn định) là v1.0.0 và hoạt động theo cách hoàn toàn khác.

Nó vẫn có tệp tập lệnh chính có tên là globalize.js nhưng bạn phải thêm nhiều tập lệnh để làm cho tập lệnh hoạt động.

Ai đó đã tạo một tool cho bạn biết chính xác tập lệnh nào bạn cần, tùy thuộc vào loại mô-đun (số, ngày, đơn vị tiền tệ) bạn muốn sử dụng.

Nếu bạn chọn sử dụng v1.0.0 bạn sẽ thấy rằng công cụ này sẽ gợi ý để bao gồm các kịch bản cơ sở (chỉ số):

  • cldr.js
  • CLDR/event.js
  • CLDR/supplemental.js
  • globalize.js
  • toàn cầu hoá/number.js

cộng với một số kịch bản CLDR JSON:

  • CLDR/bổ sung/likelySubtags.json
  • CLDR/main/{} locale /numbers.json
  • CLDR/bổ sung/numberingSystems.json

Bạn có thể tìm thấy các tệp này trong gói core và gói numbers.
Nếu bạn muốn xác thực ngày tháng là package. Thông tin thêm here.

Đây là tất cả các tệp json và bạn không thể nhóm chúng. Bạn có thể tải chúng trong thời gian chạy làm một cái gì đó như thế này:

Application.loadCulture = function (culture) { 

    $.when(
     $.get(Application.CldrFetch + '/' + culture + '/' + encodeURIComponent("likelySubtags.json")), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "numberingSystems.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "plurals.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "ordinals.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "currencyData.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "timeData.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "weekData.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "ca-gregorian.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "timeZoneNames.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "numbers.json"), 
     $.get(Application.CldrFetch + '/' + culture + '/' + "currencies.json") 
    ) 
    .then(function() { 
     // Normalize $.get results, we only need the JSON, not the request statuses. 
     return [].slice.apply(arguments, [0]).map(function (result) { 
      return result[0]; 
     }); 

    }).then(Globalize.load).then(function() { 
     Globalize.locale(culture); 
    }); 
}; 

Dù sao; giả sử bạn muốn gắn bó với v0.0.1 cũ mà vẫn là tốt nhất.
bó của bạn sẽ có kịch bản toàn cầu hoá và những nền văn hóa:

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
    "~/Scripts/globalize.js", 
    "~/Scripts/cultures/globalize.culture.en-AU.js", 
    "~/Scripts/cultures/globalize.culture.es-AR.js" 
)); 

jQuery validation cung cấp một số phần mở rộng bổ sung khác mà bạn có thể muốn xem xét:

  • thêm-methods.js
  • nội địa/messages_es_AR.js (thông báo lỗi cho văn hóa)

Tôi đã thấy rằng bạn đang thiết lập văn hóa trong số Application_AcquireRequestState. Có người đề nghị nó tốt hơn để làm điều đó trong Application_BeginRequest khi được xử lý trước đó trong ống:

protected void Application_BeginRequest(object sender, EventArgs e) 
    { 
     HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture"); 
     string cultureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en"; 
     CultureInfo ci = new CultureInfo(cultureCode); 
     System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureCode); 
     System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture; 
    } 

Có vẻ như bạn đang sử dụng jQuery plugin này cho xác nhận. Những gì tôi thường làm là, ngay sau khi tôi tải các kịch bản, cấu hình văn hóa và thiết lập xác nhận tùy chỉnh:

Globalize.culture(this.culture); 

    $.validator.methods.number = function (value, element) { 
     return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value)); 
    }; 

    $.validator.methods.date = function (value, element) { 
     return (this.optional(element) || Globalize.parseDate(value)); 
    }; 

    jQuery.extend(jQuery.validator.methods, { 
     range: function (value, element, param) { 
      var val = Globalize.parseFloat(value); 
      return this.optional(element) || (val >= param[0] && val <= param[1]); 
     } 
    }); 

Một điều mà bạn đang thiếu là một chất kết dính mô hình cho số thập phân:

using System; 
using System.Web.Mvc; 
using System.Globalization; 

public class DecimalModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     ModelState modelState = new ModelState { Value = valueResult }; 
     object actualValue = null; 
     try 
     { 
      //Check if this is a nullable decimal and a null or empty string has been passed 
      var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType && string.IsNullOrEmpty(valueResult.AttemptedValue)); 

      //If not nullable and null then we should try and parse the decimal 
      if (!isNullableAndNull) 
      { 
       actualValue = decimal.Parse(valueResult.AttemptedValue, NumberStyles.Any, CultureInfo.CurrentCulture); 
      } 
     } 
     catch (FormatException e) 
     { 
      modelState.Errors.Add(e); 
     } 

     bindingContext.ModelState.Add(bindingContext.ModelName, modelState); 
     return actualValue; 
    } 
} 

có thể được đặt trong Global.asax của bạn Application_Start:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder()); 

này là khá nhiều tất cả mọi thứ bạn cần.

Chỉ có một vấn đề khó chịu với cách tiếp cận này.
Giả sử bạn đang sử dụng văn bản en-AU và bạn nhập vào trường số của mình một giá trị: 10,4. Số này hoàn toàn hợp lệ trong es-AR nhưng số này không hợp lệ đối với văn hóa en-AU.

jQuery Toàn cầu hoá sẽ xem xét nó có giá trị nào vì nó sẽ traslate nó đến 104 ở đây:

$.validator.methods.number = function (value, element) { 
    return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value)); 
}; 

Globalize.parseFloat('10,4') cho nền văn hóa en-AU sẽ thay đổi con số đó đến 104.

Cùng một điều sẽ xảy ra nếu bạn làm tương tự cho Globalize.parseFloat('10.4') cho văn hóa es-AR; nó sẽ trở lại, một lần nữa, 104.

Bạn có thể kiểm tra hành vi này chạy fiddle này.

Cả hai ,. là các ký hiệu hợp lệ vì chúng sẽ được sử dụng làm dấu tách thập phân và dấu phân cách hàng nghìn.

Có một vài vấn đề mở về chủ đề này trên github và tôi đoán sẽ rất khó khắc phục vì hiện tại họ đang làm việc trên phiên bản mới, trong đó cùng một vấn đề vẫn tồn tại.

Bạn sẽ phải đối mặt với cùng một vấn đề trên server-side với decimal model binder của chúng tôi:

decimal.Parse('10,4', NumberStyles.Any, CultureInfo.CurrentCulture); 

nơi CultureInfo.CurrentCulture là 'en-AU', một lần nữa, tạo ra cùng một kết quả: .

Nó có thể đặt điểm ngắt ở đó và xem cách nó chuyển đổi giá trị.

Tôi đoán có lẽ điều này sẽ dễ sửa hơn, có thể sử dụng một số cụm từ thông dụng.

Nếu bạn muốn chơi với giải pháp với jQuery Validator v.0.1.1 hoặc jQuery Validator v.1.0.0 Tôi đã tạo hai kho lưu trữ herehere.

1

Bạn đã thêm bó trong RegisterBundles nhưng không sử dụng chúng trong trang bố trí. Bạn cũng đã thêm tệp jqueryui dư thừa trong RegisterBundles. Cập nhật RegisterBundles bạn phương pháp như thế này:

public static void RegisterBundles(BundleCollection bundles) 
{ 
    BundleTable.EnableOptimizations = true; 
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
        "~/Scripts/jquery-{version}.js")); 
    bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
      "~/Scripts/globalize.js",     
      "~/Scripts/globalize/currency.js", 
      "~/Scripts/globalize/date.js", 
      "~/Scripts/globalize/message.js", 
      "~/Scripts/globalize/number.js", 
      "~/Scripts/globalize/plural.js", 
      "~/Scripts/globalize/relative-time.js")); 
    bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
      "~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js")); 
    bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
      "~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js")); 
    bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
        "~/Scripts/jquery-ui-1.10.3.js"));  

    bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
      "~/Scripts/jquery.validate.js", 
      "~/Scripts/jquery.validate.unobtrusive.js", 
      "~/Scripts/jquery.unobtrusive-ajax.js", 
      "~/Scripts/jquery.validate.globalize.js")); 
    } 

và sau đó cập nhật trang bố trí như thế này:

@section Scripts 
{ 
    @Scripts.Render("~/bundles/jquery", 
       "~/bundles/globalisation", 
       "~/bundles/globalisationEN", 
       "~/bundles/globalisationES", 
       "~/bundles/jqueryval", 
       "~/bundles/jqueryui")) 

    <script type="text/javascript"> 
    $.validator.methods.number = function (value, element) { 
     return this.optional(element) || 
      !isNaN(Globalize.parseFloat(value)); 
    } 
    $(document).ready(function() { 
     Globalize.culture('es-AR'); //set spanish culture 
    }); 

    </script> 
} 

Hy vọng điều này sẽ giúp :)

+0

Thực ra tôi đã quên đăng globalisationEN "và globalisationES". Tôi đã bao gồm trong ứng dụng của mình và tôi đã sửa lại bài đăng của mình. Sau khi thêm các globalisation.culture js tôi nhận được một lỗi giao diện điều khiển "Uncaught TypeError: t.addCultureInfo không phải là một chức năng" –

+0

bạn sẽ đề cập đến cách bạn đang sử dụng t.addCultureInfo? –

+0

Lỗi thực sự phát sinh từ jquery.gloablisation.js. –

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