Meertalige ondersteuning voor dataannotaties die worden gebruikt voor parameternamen, invoervalidatieberichten, enz.

Aanmaakdatum van pagina :

milieu

ASP.NET kern
  • 5,0 MVC

premisse

Deze tips zijn geschreven als begrip van de volgende tips:

Als u een nieuw project maakt, moet u ook de volgende bestanden en code hebben toegevoegd op basis van bovenstaande tips.

  • Maak een SharedResource.resx-bestand (+en, es). (De inhoud kan leeg zijn.)
  • Een SharedResource.cs bestand maken
  • Lokalisatiecode toevoegen aan Startup.ConfigureServices
  • Lokalisatiecode toevoegen aan Startup.Configure

Oplossingen voor opstart.cs

Omdat aanvullende meertalige instellingen met betrekking tot DataAnnotations vereist zijn, Startup.ConfigureServices wijzigt u de methode als volgt:

public void ConfigureServices(IServiceCollection services)
{
  services.AddControllersWithViews();

  services.AddMvc()
    // ローカライズに必要。Resx ファイルのフォルダパスを指定
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
    // DataAnnotations のローカライズに必要 (追加)
    .AddDataAnnotationsLocalization(options =>
     {
       // DataAnnotation を使ったときのメッセージは SharedResource に集約する
       options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource));
     });
}

Modellering voor invoer

Maak een model om aan het invoerscherm te binden. In dit voorbeeld hebben we een aantal eigenschappen gemaakt voor verschillende invoerbesturingselementen. Als u problemen ondervindt bij het maken, kunt u er gewoon twee maken.

Maak een UserViewModel-.cs in de map Modellen.

De code zou er als volgt uit moeten zien: De naamruimte moet geschikt zijn. De attributen die u instelt, zijn niet erg relevant voor meerdere talen, omdat ze alleen aan hen worden toegewezen. Meertalige ondersteuning zal later worden gedaan.

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace LocalizationDataAnnotation.Models
{
  public class UserViewModel
  {
    [Required]
    [Display(Name = "ID (半角英数字)")]
    [StringLength(20)]
    [RegularExpression(@"^[0-9a-zA-Z]*$")]
    public string ID { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    [StringLength(50, MinimumLength = 8)]
    [DataType(DataType.Password)]
    [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Password")]
    public string Password { get; set; }

    // 省略
  }

  // 省略
}

Een actie maken

Maak acties in om het registratiescherm van de gebruiker weer te geven en registratieacties uit te HomeController voeren.

Het maken van schermen en acties is niet het hoofdonderwerp van deze Tips, dus het is gepast. Bovendien wordt het eigenlijke registratieproces niet uitgevoerd.

// 初期コードは省略

namespace LocalizationDataAnnotation.Controllers
{
  public class HomeController : Controller
  {
    // 初期コードは省略

    public IActionResult Create()
    {
      return View();
    }

    [HttpPost]
    public IActionResult Create(UserViewModel model)
    {
      // エラーなら差し戻し
      if (ModelState.IsValid == false) return View(model);

      // 正常に登録できた場合は Index に戻る
      return RedirectToAction(nameof(Index));
    }
  }
}

Link naar gebruikersregistratiescherm

Maak een koppeling naar het gebruikersregistratiescherm in Views\Home\Index.cshtml. Je kunt alles schrijven zolang je maar een schermovergang kunt hebben.

asp-route-culture Met het kenmerk wordt de pagina geopend in de opgegeven taal.

<!-- 初期コード省略 -->

<ul>
  <li><a asp-action="Create">Create</a></li>
  <li><a asp-action="Create" asp-route-culture="ja">Create (ja)</a></li>
  <li><a asp-action="Create" asp-route-culture="en">Create (en)</a></li>
  <li><a asp-action="Create" asp-route-culture="es">Create (es)</a></li>
</ul>

Een gebruikersregistratiescherm maken

Create Klik met de rechtermuisknop op de actie en selecteer Weergave toevoegen.

Selecteer Scheermesweergave.

Maak de sjabloon "Create" en de modelklasse "UserViewModel". Als je de UserViewModel voorbeeldcode gebruikt, heb ik ook opmerkingen in de code opgenomen. Als u bepaalde attributen in een eigenschap plaatst, krijgt u een foutmelding bij het genereren van code in steigers. Geef tijdelijk een opmerking voordat u een weergave maakt.

Als u echt een fout krijgt wanneer u deze maakt, maakt u een lege Razor-weergave en neemt u de volgende code op:

@model LocalizationDataAnnotation.Models.UserViewModel
@using System.Globalization;
@{
  ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>UserViewModel</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Create">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="ID" class="control-label"></label>
        <input asp-for="ID" class="form-control" />
        <span asp-validation-for="ID" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Name" class="control-label"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Password" class="control-label"></label>
        <input asp-for="Password" class="form-control" />
        <span asp-validation-for="Password" class="text-danger"></span>
      </div>

      <!-- 省略 -->

      <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" asp-route-culture="@CultureInfo.CurrentCulture.Name" />
      </div>
    </form>
  </div>
</div>

<div>
  <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
  @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Voor nu, als voorbereidende fase, kunt u de code tot nu toe met succes bouwen en proberen het scherm correct te zien en uit te voeren.

Meertalige tekstregistratie voor DataAnnotations

Alle eigenschappen zijn lang om uit te leggen, dus we ID zullen praten met en voor . Name Andere eigenschappen zijn op een vergelijkbare manier meertalig, dus probeer ze uit.

De volgende teksten zijn hier in meerdere talen beschikbaar.

Meertalige teksttoetsen
Weergavenaam van parameter Id ID_DisplayName
Foutbericht wanneer id niet is ingevoerd Validate_Required
Foutbericht wanneer id-invoerteken langer is dan 20 tekens Validate_StringLength
Foutbericht wanneer id wordt getypt met niet-numerieke tekens Validate_Alphanumeric
Naam parameter weergavenaam Name_DisplayName
Foutbericht wanneer de naam meer dan 50 tekens bevat Validate_StringLength

Validate_XXXXX universeel zijn. Er is geen belangrijke naamgevingsconventie, dus u kunt deze vrijelijk toevoegen.

Met deze sleutels als basis SharedResource.resx vullen we de vertaalde tekst in SharedResource.en.resx in , , SharedResource.es.resx .

SharedResource.resx

Naamwaarde
Validate_Required "{0}" is vereist.
Validate_StringLength U kunt maximaal "{1}" invoeren in "{0}".
Validate_Alphanumeric {0} kan alleen alfanumeriek zijn.
ID_DisplayName ID (alfanumeriek)
Name_DisplayName identiteit

SharedResource.nl.resx

Naamwaarde
Validate_Required "{0}" is een vereiste invoer.
Validate_StringLength Het maximale aantal tekens dat kan worden ingevoerd in "{0}" is "{1}".
Validate_Alphanumeric Alleen alfanumerieke tekens kunnen worden ingevoerd voor "{0}".
ID_DisplayName ID (alfanumerieke tekens)
Name_DisplayName Volledige naam

SharedResource.es.resx

Naamwaarde
Validate_Required "{0}" es una entrada obligatoria.
Validate_StringLength El número máximo de caracteres que se pueden ingresar en "{0}" es "{1}".
Validate_Alphanumeric Solo se pueden ingresar caracteres alfanuméricos para "{0}".
ID_DisplayName ID (caracteres alfanuméricos)
Name_DisplayName Nombre completo

Invoervalidatiefoutberichten vervangen parameternamen en -nummers door {0} en {1}. Laten we het positief gebruiken.

Meertalige toepassing op DataAnnotaties

Alle meertalige instellingen worden toegepast op de kenmerken van het model (DataAnnotations).

Als u deze wilt toepassen op de weergavenaam van de parameter, Display koppelt u een sharedResource.resx-sleutel aan en geeft u deze Name op in de eigenschap.

Als u wilt toepassen op foutberichten tijdens invoervalidatie, geeft u een ErrorMessage sleutel sharedResource.resx op in de eigenschap van elk validatiekenmerk.

public class UserViewModel
{
  [Required(ErrorMessage = "Validate_Required")]
  [Display(Name = "ID_DisplayName")]
  [StringLength(20, ErrorMessage = "Validate_StringLength")]
  [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
  public string ID { get; set; }

  [Display(Name = "Name_DisplayName")]
  [StringLength(50, ErrorMessage = "Validate_StringLength")]
  public string Name { get; set; }

  // 省略
}

Hiermee is de installatie voltooid. Voer het daarna uit om te zien hoe het werkt.

Overigens wordt het aantal invoertekens beperkt door het attribuut van de maxlength invoertag. Als u het bericht wilt zien, moet u de beperkingen verwijderen, bijvoorbeeld in de hulpprogramma's voor ontwikkelaars van uw webbrowser.

Overigens worden er enkele berichten weergegeven bij het registreren van uw leeftijd, datum, etc. leeg. Dit is een bericht dat is ingesteld aan de framework-kant, maar een andere tips laat u zien hoe u het in meerdere talen kunt ondersteunen.

Voor alle codes

Deze tips bevatten slechts enkele eigenschappen, maar de voorbeeldcode omvat alle invoervelden met html5.This Tips bevat slechts enkele eigenschappen, maar de voorbeeldcode bestrijkt alle invoervelden met html5.This Tips contains only properties, but the sample code covers all html5-enabled input fields. Als u wilt controleren, raadpleegt u de link boven de pagina.

Hieronder in een deel vermeld

UserViewModel.cs

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace LocalizationDataAnnotation.Models
{
  public class UserViewModel
  {
    [Required(ErrorMessage = "Validate_Required")]
    [Display(Name = "ID_DisplayName")]
    [StringLength(20, ErrorMessage = "Validate_StringLength")]
    [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
    public string ID { get; set; }

    [Display(Name = "Name_DisplayName")]
    [StringLength(50, ErrorMessage = "Validate_StringLength")]
    public string Name { get; set; }

    [Display(Name = "Password_DisplayName")]
    [StringLength(50, MinimumLength = 8, ErrorMessage = "Validate_StringLengthRange")]
    [DataType(DataType.Password)]
    [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
    public string Password { get; set; }

    [Display(Name = "ConfirmPassword_DisplayName")]
    [StringLength(50, MinimumLength = 8, ErrorMessage = "Validate_StringLengthRange")]
    [DataType(DataType.Password)]
    [Compare(nameof(Password), ErrorMessage = "Validate_Compare")]
    public string ConfirmPassword { get; set; }

    [Display(Name = "Email_DisplayName")]
    [EmailAddress(ErrorMessage = "Validate_EmailAddress")]
    [DataType(DataType.EmailAddress)] // スキャフォールディングするときはコメントアウトする
    public string Email { get; set; }

    [Display(Name = "Age_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    [Range(0, 150, ErrorMessage = "Validate_Range")]
    public int Age { get; set; }

    [Display(Name = "Gender_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    [EnumDataType(typeof(GenderType))]
    public GenderType Gender { get; set; }

    [Display(Name = "Birthday_DisplayName")]
    [DataType(DataType.Date)]
    public DateTime Birthday { get; set; }

    [Display(Name = "Phone_DisplayName")]
    [Phone(ErrorMessage = "Validate_Phone")]
    [DataType(DataType.PhoneNumber)] // スキャフォールディングするときはコメントアウトする
    public string Phone { get; set; }

    [Display(Name = "PostalCode_DisplayName")]
    [DataType(DataType.PostalCode)]
    public string PostalCode { get; set; }

    [Display(Name = "CreditCard_DisplayName")]
    [CreditCard(ErrorMessage = "Validate_CreditCard")]
    [DataType(DataType.CreditCard)] // スキャフォールディングするときはコメントアウトする
    public string CreditCard { get; set; }

    [Display(Name = "Money_DisplayName")]
    [DataType(DataType.Currency)]
    public decimal Money { get; set; }

    [Display(Name = "StartDateTime_DisplayName")]
    [DataType(DataType.DateTime)]
    public DateTime StartDateTime { get; set; }

    [Display(Name = "WakeUpTime_DisplayName")]
    [DataType(DataType.Time)]
    public TimeSpan WakeUpTime { get; set; }

    [Display(Name = "Homepage_DisplayName")]
    [Url(ErrorMessage = "Validate_Url")]
    [DataType(DataType.Url)] // スキャフォールディングするときはコメントアウトする
    public string Homepage { get; set; }

    [Display(Name = "MyImage_DisplayName")]
    [Url(ErrorMessage = "Validate_Url")]
    [DataType(DataType.ImageUrl)] // スキャフォールディングするときはコメントアウトする
    public string MyImage { get; set; }

    [Display(Name = "MyColor_DisplayName")]
    public string MyColor { get; set; }

    [Display(Name = "WorkingDays_DisplayName")]
    [MaxLength(5, ErrorMessage = "Validate_MaxLength")]
    [EnumDataType(typeof(DayOfWeek))]
    public DayOfWeek[] WorkingDays { get; set; }

    [Display(Name = "VacationDay_DisplayName")]
    [MinLength(3, ErrorMessage = "Validate_MinLength")]
    [EnumDataType(typeof(DayOfWeek))]
    public DayOfWeek[] VacationDay { get; set; }

    [Display(Name = "Comment_DisplayName")]
    [StringLength(200, ErrorMessage = "Validate_StringLength")]
    [DataType(DataType.MultilineText)]
    public string Comment { get; set; }

    [Display(Name = "FileName_DisplayName")]
    [FileExtensions(Extensions = "png", ErrorMessage = "Validate_FileExtensions")]
    public string FileName { get; set; }

    [Display(Name = "UploadFile_DisplayName")]
    [DataType(DataType.Upload)]
    public List<IFormFile> UploadFile { get; set; }

    [Display(Name = "Month_DisplayName")]
    public DateTime Month { get; set; }

    [Display(Name = "Search_DisplayName")]
    public string Search { get; set; }

    [Display(Name = "Range_DisplayName")]
    [Range(10, 100, ErrorMessage = "Validate_Range")]
    public int Range { get; set; }

    [Display(Name = "Week_DisplayName")]
    public string Week { get; set; }

    [Display(Name = "IsAccepted_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    public bool IsAccepted { get; set; }
  }

  public enum GenderType
  {
    None,
    Man,
    Woman,
    Other,
  }
}

Homecontroller.cs

using LocalizationDataAnnotation.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace LocalizationDataAnnotation.Controllers
{
  public class HomeController : Controller
  {
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
      _logger = logger;
    }

    public IActionResult Index()
    {
      return View();
    }

    public IActionResult Privacy()
    {
      return View();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
      return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }

    public IActionResult Create()
    {
      SetDayOfWeeksViewData();
      return View();
    }

    [HttpPost]
    public IActionResult Create(UserViewModel model)
    {
      SetDayOfWeeksViewData();

      // エラーなら差し戻し
      if (ModelState.IsValid == false) return View(model);

      // 正常に登録できた場合は Index に戻る
      return RedirectToAction(nameof(Index));
    }

    /// <summary>曜日の一覧を ViewData に設定します。</summary>
    private void SetDayOfWeeksViewData()
      => ViewData["DayOfWeeks"] = ((DayOfWeek[])Enum.GetValues(typeof(DayOfWeek))).Select(x => new SelectListItem(x.ToString(), ((int)x).ToString()));
  }
}

Create.cshtml

@model LocalizationDataAnnotation.Models.UserViewModel
@using System.Globalization;
@{
  ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>UserViewModel</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Create" enctype="multipart/form-data" >
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="ID" class="control-label"></label>
        <input asp-for="ID" class="form-control" />
        <span asp-validation-for="ID" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Name" class="control-label"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Password" class="control-label"></label>
        <input asp-for="Password" class="form-control" />
        <span asp-validation-for="Password" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="ConfirmPassword" class="control-label"></label>
        <input asp-for="ConfirmPassword" class="form-control" />
        <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Email" class="control-label"></label>
        <input asp-for="Email" class="form-control" />
        <span asp-validation-for="Email" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Age" class="control-label"></label>
        <input asp-for="Age" class="form-control" />
        <span asp-validation-for="Age" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Gender"></label>
        <div>
          <label><input type="radio" asp-for="Gender" value="@(GenderType.None)" />@(GenderType.None)</label>
          <label><input type="radio" asp-for="Gender" value="@(GenderType.Man)" />@(GenderType.Man)</label>
          <label><input type="radio" asp-for="Gender" value="@(GenderType.Woman)" />@(GenderType.Woman)</label>
        </div>
        <span asp-validation-for="Gender" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Birthday" class="control-label"></label>
        <input asp-for="Birthday" class="form-control" />
        <span asp-validation-for="Birthday" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Phone" class="control-label"></label>
        <input asp-for="Phone" class="form-control" />
        <span asp-validation-for="Phone" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="PostalCode" class="control-label"></label>
        <input asp-for="PostalCode" class="form-control" />
        <span asp-validation-for="PostalCode" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="CreditCard" class="control-label"></label>
        <input asp-for="CreditCard" class="form-control" />
        <span asp-validation-for="CreditCard" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Money" class="control-label"></label>
        <input asp-for="Money" class="form-control" />
        <span asp-validation-for="Money" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="StartDateTime" class="control-label"></label>
        <input asp-for="StartDateTime" class="form-control" />
        <span asp-validation-for="StartDateTime" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="WakeUpTime" class="control-label"></label>
        <input asp-for="WakeUpTime" class="form-control" />
        <span asp-validation-for="WakeUpTime" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Homepage" class="control-label"></label>
        <input asp-for="Homepage" class="form-control" />
        <span asp-validation-for="Homepage" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="MyImage" class="control-label"></label>
        <input asp-for="MyImage" class="form-control" />
        <span asp-validation-for="MyImage" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="MyColor" class="control-label"></label>
        <input asp-for="MyColor" class="form-control" type="color" />
        <span asp-validation-for="MyColor" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="WorkingDays" class="control-label"></label>
        <select asp-for="WorkingDays" class="form-control" asp-items="@((IEnumerable<SelectListItem>)ViewData["DayOfWeeks"])" multiple></select>
        <span asp-validation-for="WorkingDays" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="VacationDay" class="control-label"></label>
        <select asp-for="VacationDay" class="form-control" asp-items="@((IEnumerable<SelectListItem>)ViewData["DayOfWeeks"])" multiple></select>
        <span asp-validation-for="VacationDay" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Comment" class="control-label"></label>
        <textarea asp-for="Comment" class="form-control"></textarea>
        <span asp-validation-for="Comment" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="FileName" class="control-label"></label>
        <input asp-for="FileName" class="form-control" />
        <span asp-validation-for="FileName" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UploadFile" class="control-label"></label>
        <input asp-for="UploadFile" type="file" multiple />
        <span asp-validation-for="UploadFile" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Month" class="control-label"></label>
        <input asp-for="Month" class="form-control" type="month" />
        <span asp-validation-for="Month" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Search" class="control-label"></label>
        <input asp-for="Search" class="form-control" type="search" />
        <span asp-validation-for="Search" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Range" class="control-label"></label>
        <input asp-for="Range" class="form-control" type="range" min="10" max="100" />
        <span asp-validation-for="Range" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Week" class="control-label"></label>
        <input asp-for="Week" class="form-control" type="week" />
        <span asp-validation-for="Week" class="text-danger"></span>
      </div>
      <div class="form-group form-check">
        <label class="form-check-label">
          <input class="form-check-input" asp-for="IsAccepted" /> @Html.DisplayNameFor(model => model.IsAccepted)
        </label>
      </div>
      <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" asp-route-culture="@CultureInfo.CurrentCulture.Name" />
      </div>
    </form>
  </div>
</div>

<div>
  <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
  @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}