Večjezična podpora za DataAnnotations, ki se uporablja za imena parametrov, sporočila za preverjanje veljavnosti vnosa itd.

Datum ustvarjanja strani :

okolje

ASP.NET Core
  • 5.0 MVC

Predpostavki

Ti nasveti so napisani kot razumevanje naslednjih nasvetov:

Če ustvarjate nov projekt, morate na podlagi zgornjih nasvetov dodati naslednje datoteke in kodo.

  • Ustvarite datoteko SharedResource.resx (+sl, es). (Vsebina je lahko prazna.)
  • Ustvarjanje datoteke v skupni rabi.cs datoteke
  • Dodajanje kode lokalizacije zagonu.ConfigureServices
  • Dodajte kodo za lokalizacijo v zagon.Konfiguriraj

Popravki .cs zagona

Ker so potrebne dodatne večjezične nastavitve, povezane z DataAnnotations, spremenite metodo na Startup.ConfigureServices naslednji način:

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

Modeliranje za vnos

Ustvarite model, ki se bo priklopio na vhodni zaslon. V tem vzorcu smo ustvarili številne lastnosti za namestitev različnih vhodnih kontrolnikov. Če imate težave pri ustvarjanju, lahko ustvarite le dve.

Ustvarite userViewModel .cs v mapi Modeli.

Koda bi morala izgledati takole: Imenski prostor mora biti primeren. Atributi, ki ste jih nastavili, niso zelo pomembni za več jezikov, ker so jim dodeljeni le. Večjezična podpora bo opravljena kasneje.

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

    // 省略
  }

  // 省略
}

Ustvarjanje dejanja

Ustvarite dejanja za prikaz uporabnikovega zaslona za registracijo in izvajanje HomeController registracijskih dejanj.

Ustvarjanje zaslonov in dejanj ni glavna tema teh nasvetov, zato je primerno. Poleg tega dejanski postopek registracije ni izveden.

// 初期コードは省略

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

Povezava do zaslona za registracijo uporabnika

Ustvarite povezavo do zaslona za registracijo uporabnika v views\Home\Index.cshtml. Vse lahko napišete, dokler imate prehod zaslona.

asp-route-culture Atribut odpre stran v določenem jeziku.

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

<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>

Ustvarjanje zaslona za registracijo uporabnika

Create Z desno tipko miške kliknite dejanje in izberite Dodaj pogled.

Izberite Pogled britvic.

Naredite predlogo »Ustvari« in razred modela »UserViewModel«. Če uporabljate vzorčno kodo, sem v kodo vključil tudi UserViewModel komentarje. Če postavite določene atribute v lastnost, boste pri generiranju kode pri odrih dobili napako. Preden ustvarite pogled, začasno komentirajte.

Če pri ustvarjanju res pride do napake, ustvarite prazen pogled Razor in vključite naslednjo kodo:

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

Za zdaj lahko kot pripravljalno fazo do zdaj uspešno zgradite kodo in poskusite videti in pravilno zagnati zaslon.

Večjezična registracija besedila za DataAnnotations

Vse nepremičnine so dolgo za pojasniti, tako da bomo govorili ID z in za . Name Druge lastnosti so večjezične na podoben način, zato jih preizkusite.

Naslednja besedila so na voljo v več jezikih tukaj.

Večjezične besedilne tipke
Prikazano ime parametra ID ID_DisplayName
Sporočilo o napaki, ko ID ni vnesen Validate_Required
Sporočilo o napaki, ko vhodni znak ID presega 20 znakov Validate_StringLength
Sporočilo o napaki pri vnašanju ID-ja z neštevilčnimi znaki Validate_Alphanumeric
Prikazano ime parametra imena Name_DisplayName
Sporočilo o napaki, ko je vneseno več kot 50 znakov Validate_StringLength

Validate_XXXXX univerzalna. Ni konvencije o imenovanju ključev, zato jo lahko prosto priložite.

S temi ključi kot osnovo bomo prevedeno besedilo izpolnili v SharedResource.resx SharedResource.en.resx , , SharedResource.es.resx .

Skupna raboResource.resx

Vrednost
imena
Validate_Required "{0}" je potrebno.
Validate_StringLength V »{1}« lahko vnesete do »{0}«.
Validate_Alphanumeric {0} je lahko samo alfanumerično.
ID_DisplayName ID (alfanumerično)
Name_DisplayName identiteta

SharedResource.sl.resx

Vrednost
imena
Validate_Required "{0}" je zahtevan vhod.
Validate_StringLength Največje število znakov, ki jih je mogoče vnesti v »{0}« je »{1}«.
Validate_Alphanumeric Za »{0}« lahko vnesete le alfanumerične znake.
ID_DisplayName ID (alfanumerični znaki)
Name_DisplayName Polno ime

SharedResource.es.resx

Vrednost
imena
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 (karakteres alfanuméricos)
Name_DisplayName Nombre completo

Sporočila o napakah pri preverjanju vnosa nadomestijo imena parametrov in številke z {0} in {1}. Uporabimo ga pozitivno.

Večjezična uporaba za DataAnnotations

Vse večjezične nastavitve se uporabljajo za atribute modela (DataAnnotations).

Če ga želite uporabiti za prikazano ime parametra, v lastnosti priložite in določite ključ v skupni Display Name rabiResource.resx.

Če želite uporabiti sporočila o napakah med preverjanjem veljavnosti vnosa, v lastnosti vsakega atributa preverjanja veljavnosti določite ključ v skupni ErrorMessage rabiResource.resx.

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

  // 省略
}

S tem se dokonča nastavitev. Po tem ga zaženite, da vidite, kako deluje.

Mimogrede, število vhodnih znakov je omejeno z atributom vhodne maxlength oznake. Če želite videti sporočilo, morate odstraniti omejitve, na primer v orodjih razvijalcev spletnega brskalnika.

Mimogrede, pri registraciji vaše starosti, datuma itd. so prikazana nekatera sporočila prazna. To je sporočilo, ki je nastavljeno na okvirni strani, drugi nasveti pa vam bodo pokazali, kako ga podpreti v več jezikih.

Za vse kode

Ta Namigi vsebujejo le nekatere lastnosti, vendar vzorčna koda zajema vsa vhodna polja, ki jih omogoča HTML5. Če želite preveriti, si oglejte povezavo nad stranjo.

V nadaljevanju naveden del

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

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