Локализация для поля ввода с двойным значением в Razor Pages - PullRequest
1 голос
/ 27 мая 2019

В моей ViewModel у меня есть такое свойство:

[DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)]        
public double SomeDoubleProperty { get; set; }

Markup:

<div class="form-group row">
    <label asp-for="ViewModel.SomeDoubleProperty" class="col-sm-3 col-form-label">
        @Localizer[nameof(Model.ViewModel.SomeDoubleProperty)]
    </label>
    <div class="col-sm-9">
        <div class="input-group">
            <div class="input-group-prepend">
                <span class="input-group-text">%</span>
            </div>
            <input asp-for="ViewModel.SomeDoubleProperty"
                   class="form-control">
        </div>
        <span asp-validation-for="ViewModel.SomeDoubleProperty" class="text-danger"></span>
    </div>
</div>

После загрузки страницы (со значением по умолчанию 0) она отображается следующим образом в поле ввода:

enter image description here

(текущая культура и текущая культура интерфейса потока - это "de", поэтому десятичный разделитель "," является ожидаемым).

Но когда я сейчас покидаю поле ввода, отображается следующая ошибка проверки:

Поле SomeDoubleProperty должно быть числом.

При замене «,» на «.» Валидатор принимает значение. Как я могу добиться того, чтобы "," тоже принималось, если текущая культура пользовательского интерфейса - "де"?

Ответы [ 2 ]

1 голос
/ 27 мая 2019

вам нужно скачать и настроить клиентские сценарии проверки:

  • cldrjs
  • CLDR-данные
  • globalizejs

в корне вашего проекта создайте новое имя файла "libman.json" и добавьте в него следующие библиотеки:

{
  "version": "1.0",
  "defaultProvider": "jsdelivr",
  "libraries": [
    {
      "library": "cldrjs@0.5.1",
      "destination": "wwwroot/lib/cldr"
    },
    {
      "library": "cldr-data@35.1.0",
      "destination": "wwwroot/lib/cldr-data"
    },
    {
      "library": "globalize@1.4.2",
      "destination": "wwwroot/lib/globalize"
    }
  ]
}

Когда вы сохраните файл, он загрузит все сценарии в папку wwwroor / lib.

Затем откройте wwwroot/lib/cldr-data/package.json и добавьте следующие строки в конец страницы перед закрывающей скобкой:

"peerDependencies": {
    "cldr-data": ">=26"
  }

Когда вы сохраняете файл, он загружает все данные JSON (нумерация, дата, время, валюта и т. Д.) Для всех культур. Загрузка может занять некоторое время (~ 35 МБ).

Необходимо установить еще одну библиотеку js "jquery.validate.globalize.min.js", но версия в jsdelivr 0.1.1 не совместима, нам нужен v1.0, поэтому либо загрузите ее вручную с GitHub или просто используйте функцию импорта jsdelivr из GitHub, как показано ниже:

<script src="https://cdn.jsdelivr.net/gh/johnnyreilly/jquery-validation-globalize@1.0.0/jquery.validate.globalize.min.js"></script>

Затем создайте новое частичное имя с именем «_LocalizationValidationScriptsPartial.cshtml» и добавьте в него библиотеки:

<!-- cldr scripts (needed for globalize) -->
<script src="/lib/cldr/dist/cldr.min.js"></script>
<script src="/lib/cldr/dist/cldr/event.min.js"></script>
<script src="/lib/cldr/dist/cldr/supplemental.min.js"></script>

<!-- globalize scripts -->
<script src="/lib/globalize/dist/globalize.min.js"></script>
<script src="/lib/globalize/dist/globalize/number.min.js"></script>
<script src="/lib/globalize/dist/globalize/date.min.js"></script>
<script src="/lib/globalize/dist/globalize/currency.min.js"></script>

<!-- this file can be downloaded from : -->
<!-- https://github.com/johnnyreilly/jquery-validation-globalize -->
<script src="https://cdn.jsdelivr.net/gh/johnnyreilly/jquery-validation-globalize@1.0.0/jquery.validate.globalize.min.js"></script>

<!-- code to get check if current cultures scripts are exists -->
<!-- if not, select parent cultures scripts -->
@inject Microsoft.AspNetCore.Hosting.IHostingEnvironment HostingEnvironment
@{
    string GetDefaultLocale()
    {
        const string localePattern = "lib\\cldr-data\\main\\{0}";
        var currentCulture = System.Globalization.CultureInfo.CurrentCulture;
        var cultureToUse = "en"; //Default regionalisation to use

        if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.Name))))
            cultureToUse = currentCulture.Name;
        else if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.TwoLetterISOLanguageName))))
            cultureToUse = currentCulture.TwoLetterISOLanguageName;

        return cultureToUse;
    }
}

<script type="text/javascript">
    var culture = "@GetDefaultLocale()";
    $.when(
        $.get("/lib/cldr-data/supplemental/likelySubtags.json"),
        $.get("/lib/cldr-data/main/" + culture + "numbers.json"),
        $.get("/lib/cldr-data/main/" + culture + "/currencies.json"),
        $.get("/lib/cldr-data/supplemental/numberingSystems.json"),
        $.get("/lib/cldr-data/main/" + culture + "/ca-gregorian.json"),
        $.get("/lib/cldr-data/main/" + culture + "/timeZoneNames.json"),
        $.get("/lib/cldr-data/supplemental/timeData.json"),
        $.get("/lib/cldr-data/supplemental/weekData.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);
    });
</script>

Наконец, просто включите это частичное представление после _ValidationScriptsPartial.cshtml по умолчанию, где вам нужно выполнить проверку локализации.

<partial name="_ValidationScriptsPartial.cshtml" />
<partial name="_LocalizationValidationScriptsPartial.cshtml" />

Альтернативный метод

Я создал TagHelperComponent, чтобы избежать всей тяжелой работы, вам даже не нужно загружать скрипты на свой локальный компьютер.

  • установить пакет nuget:
Install-Package LazZiya.TagHelpers -Version 2.1.0
  • добавить LazZiya.TagHelpers в _ViewImports:
@using LazZiya.TagHelpers
@addTagHelper *, LazZiya.TagHelpers
  • зарегистрировать вспомогательный компонент тега проверки локализации при запуске:
services.AddTransient<ITagHelperComponent, LocalizationValidationScriptsTagHelperComponent>();
  • добавьте тег в раздел скриптов на странице для проверки локализованных полей ввода (также должен быть загружен файл по умолчанию _ValidationScriptsPartial.cshtml):
<partial name="_ValidationScriptsPartial.cshtml" />
<localization-validation-scripts></localization-validation-scripts>

Этот TagHelper автоматически определит текущее имя культуры и добавит все необходимые сценарии для проверки локализованных значений.

Подробнее см. LazZiya.TagHelpers

0 голосов
/ 28 мая 2019

Благодаря @Laz Ziya я нашел комбинацию, которая делает свое дело:

ViewModel:

    [DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)]
    [Range(0, 100, ErrorMessage = "RangeAttribute_ValidationError")]
    public double SomeDoubleProperty { get; set; }

Разметка:

    <div class="form-group row">
        <label asp-for="ViewModel.SomeDoubleProperty" class="col-sm-3 col-form-label">
            @Localizer[nameof(Model.ViewModel.SomeDoubleProperty)]
        </label>
        <div class="col-sm-9">
            <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text">%</span>
                </div>
                <input asp-for="ViewModel.SomeDoubleProperty"
                       class="form-control"
                       id="some-double-input" digit-count="2">
            </div>
            <span asp-validation-for="ViewModel.SomeDoubleProperty" class="text-danger"></span>
        </div>
    </div>
<partial name="_NumberInputPartial" />

NumberInputPartial:

 @using System.Threading;

@*To use this partial add the following attribute to the input element: digit-count="{enter requested digit count here}"*@

<script asp-location="Footer">
    function toLocalizedNumberString(numberAsString, digitCount) {
        var decimalSeparator = '@(Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator)';
        var groupSeparator = '@(Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberGroupSeparator)';
          var num = parseFloat(numberAsString.replace(decimalSeparator, '.'));
          return ( num
            .toFixed(digitCount)
            .replace('.', decimalSeparator)
            .replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + groupSeparator)
            )
    }
    $("input[digit-count]").on("focusin", function () {
        $(this).val($(this).val().replace(@("/[" + Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberGroupSeparator + "]/g"), ""));
    });
    $("input[digit-count]").on("focusout", function () {
        $(this).val(toLocalizedNumberString($(this).val(), $(this).attr("digit-count")));
    });
</script>

<partial name="_ValidationScriptsPartial" />
<localization-validation-scripts></localization-validation-scripts>
...