Skip to main content

Täielik ASP.NET Core'i lokaliseerimise juhend

IStringLocalizer'ist tootmiskeskkonnani: seadista ASP.NET Core'is ressursipõhine lokaliseerimine ja automatiseeri seejärel tõlked tehisintellektiga.

1

Luba lokaliseerimisteenused

Registreeri lokaliseerimisteenused failis Program.cs funktsiooniga AddLocalization(), seadista toetatud kultuurid ja lisa päringute lokaliseerimise middleware. See ühendab kogu ASP.NET Core'i rakenduse lokaliseerimiskonveieri.

AddLocalization() registreerib IStringLocalizer'i ja IStringLocalizerFactory DI-konteineris. ResourcesPath ütleb raamistikule, kust .resx-faile leida. AddViewLocalization() lubab Razor-vaadetes IViewLocalizeri ja AddDataAnnotationsLocalization() lokaliseeritud valideerimissõnumid.
Program.cs
using Microsoft.AspNetCore.Localization;
using System.Globalization;

var builder = WebApplication.CreateBuilder(args);

// 1. Register localization services
builder.Services.AddLocalization(o => o.ResourcesPath = "Resources");

// 2. Add MVC with view/data-annotation localization
builder.Services.AddControllersWithViews()
    .AddViewLocalization()
    .AddDataAnnotationsLocalization();

var app = builder.Build();

// 3. Configure supported cultures
var supportedCultures = new[] { "en", "de", "ja", "es", "pt-BR" }
    .Select(c => new CultureInfo(c)).ToArray();

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures,
});

app.UseStaticFiles();
app.UseRouting();
app.MapControllers();
app.Run();
2

Loo RESX-ressursifailid

ASP.NET Core kasutab tõlgete jaoks RESX-i (XML-ressursi) faile. Loo üks fail kultuuri ja klassi kohta: HomeController.en.resx, HomeController.de.resx jne. Raamistik lahendab õige faili praeguse päringu kultuuri järgi.

Resources/Controllers/HomeController.{culture}.resx
<!-- Resources/Controllers/HomeController.en.resx -->
<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="Welcome" xml:space="preserve">
    <value>Welcome to our application</value>
  </data>
  <data name="Greeting" xml:space="preserve">
    <value>Hello, {0}!</value>
  </data>
</root>

<!-- Resources/Controllers/HomeController.de.resx -->
<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="Welcome" xml:space="preserve">
    <value>Willkommen in unserer Anwendung</value>
  </data>
  <data name="Greeting" xml:space="preserve">
    <value>Hallo, {0}!</value>
  </data>
</root>
Kasuta oma RESX-failidega SharedResource'i klassi kontrollerite ja vaadete vahel jagatud stringide, näiteks nuppude siltide, navigeerimisüksuste ja levinud valideerimissõnumite jaoks. Nii väldid võtmete dubleerimist kümnetes kontrolleripõhistes RESX-failides.
Shared resources for cross-cutting strings
<!-- Resources/SharedResource.en.resx — shared across controllers -->
<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="AppName" xml:space="preserve">
    <value>My Application</value>
  </data>
  <data name="Save" xml:space="preserve"><value>Save</value></data>
  <data name="Cancel" xml:space="preserve"><value>Cancel</value></data>
</root>

// Marker class (empty — only used for type lookup)
namespace MyApp;
public class SharedResource { }
3

Kasuta IStringLocalizer'it kontrollerites ja teenustes

Sisesta IStringLocalizer&lt;T&gt; sõltuvuste sisestamise kaudu mis tahes kontrollerisse, teenusesse või middleware'i. Üldine tüübiparameeter T määrab laaditava RESX-faili. Hangi tõlgitud stringid nurksulusüntaksiga localizer["Key"] ja lisa soovi korral vormindusparameetrid.

Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

public class HomeController(
    IStringLocalizer<HomeController> localizer,
    IStringLocalizer<SharedResource> shared) : Controller
{
    public IActionResult Index()
    {
        ViewData["Welcome"] = localizer["Welcome"];
        ViewData["AppName"] = shared["AppName"];

        // String interpolation with format parameters
        var greeting = localizer["Greeting", User.Identity?.Name ?? "Guest"];
        return View(new HomeViewModel { Greeting = greeting });
    }
}
Kui IStringLocalizer tagastab tõlgitud väärtuse asemel võtme nime, kontrolli kolme asja: 1) RESX-faili nimi vastab klassi nimeruumile, 2) AddLocalization() funktsiooni ResourcesPath osutab õigesse kausta ja 3) RESX-faili Build Action on Visual Studio's määratud väärtusele Embedded Resource.
4

Seadista päringukultuuri middleware

ASP.NET Core määrab päringu kultuuri pakkujate ahelaga: päringustring, küpsis ja Accept-Language'i päis selles järjekorras. Saad lisada kohandatud pakkujaid, mis loevad kultuuri näiteks URL-i marsruudisegmendist, nagu /de/home.

Custom RouteDataRequestCultureProvider
// Culture resolved in order: QueryString, Cookie, Accept-Language
// Custom provider: read culture from URL route segment /de/home
public class RouteDataRequestCultureProvider : RequestCultureProvider
{
    public override Task<ProviderCultureResult?> DetermineProviderCultureResult(
        HttpContext httpContext)
    {
        var culture = httpContext.GetRouteValue("culture")?.ToString();
        if (string.IsNullOrEmpty(culture))
            return NullProviderCultureResult;
        return Task.FromResult<ProviderCultureResult?>(
            new ProviderCultureResult(culture));
    }
}

// Register in Program.cs (route provider first = highest priority):
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures,
    RequestCultureProviders = new List<IRequestCultureProvider>
    {
        new RouteDataRequestCultureProvider(),
        new QueryStringRequestCultureProvider(),
        new CookieRequestCultureProvider(),
        new AcceptLanguageHeaderRequestCultureProvider(),
    }
});
Language Switcher Action
// Language switcher: persist choice in cookie
[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) });
    return LocalRedirect(returnUrl);
}
Middleware'i järjekord on oluline. UseRequestLocalization() tuleb kutsuda pärast UseRouting() funktsiooni, kuid enne UseEndpoints() või MapControllers() funktsiooni. Liiga hilise paigutuse korral pole kultuur kontrollerite käitamisel määratud.
5

Lokaliseeri andmeannotatsioonid

Valideerimisatribuute, nagu [Required], [StringLength] ja [Display], saab lokaliseerida, määrates nende ErrorMessage'i või Name'i atribuudiks RESX-võtme nime. Selle lubamiseks kutsu failis Program.cs funktsiooni AddDataAnnotationsLocalization().

ViewModels/RegisterViewModel.cs
using System.ComponentModel.DataAnnotations;

public class RegisterViewModel
{
    [Required(ErrorMessage = "NameRequired")]
    [Display(Name = "FullName")]
    [StringLength(100, ErrorMessage = "NameLength", MinimumLength = 2)]
    public string Name { get; set; } = string.Empty;

    [Required(ErrorMessage = "EmailRequired")]
    [EmailAddress(ErrorMessage = "EmailInvalid")]
    [Display(Name = "EmailAddress")]
    public string Email { get; set; } = string.Empty;

    [Required(ErrorMessage = "PasswordRequired")]
    [StringLength(100, ErrorMessage = "PasswordLength", MinimumLength = 8)]
    [Display(Name = "Password")]
    public string Password { get; set; } = string.Empty;
}
// RESX keys map to ErrorMessage/Name values:
// RegisterViewModel.de.resx: NameRequired = "Name ist erforderlich"
// RegisterViewModel.de.resx: FullName = "Vollständiger Name"
Andmeannotatsioonide lokaliseerimine leiab RESX-failid ViewModeli klassi, mitte kontrolleri nime järgi. RegisterViewModeli jaoks otsib raamistik faili Resources/ViewModels/RegisterViewModel.de.resx. Kui RESX-failid on nimetatud kontrolleri järgi, ei lokaliseerita valideerimissõnumeid.
6

Töötle mitmusevorme ja ICU sõnumeid

.NET-il puudub ICU-laadne sisseehitatud mitmusereeglite tugi. Lihtsatel juhtudel kasuta eraldi RESX-võtmeid (ItemCount_One, ItemCount_Other) koos koodi switch'iga. Kõiki CLDR-i mitmusekategooriaid hõlmava ICU MessageFormat'i toe jaoks kasuta MessageFormat.NET teeki.

Plural handling strategies
// Option 1: Separate RESX keys with code switch
// HomeController.en.resx: ItemCount_One = "You have {0} item"
// HomeController.en.resx: ItemCount_Other = "You have {0} items"
public string GetItemCount(int count)
{
    var key = count == 1 ? "ItemCount_One" : "ItemCount_Other";
    return _localizer[key, count];
}

// Option 2: ICU MessageFormat (dotnet add package MessageFormat.NET)
using Jeffijoe.MessageFormat;
var formatter = new MessageFormatter();

var pattern = "{count, plural, one {# item} other {# items}} in your cart";
var result = formatter.FormatMessage(pattern,
    new Dictionary<string, object> { { "count", 5 } });
// => "5 items in your cart"

// Arabic: 6 plural forms (zero, one, two, few, many, other)
var arPattern = @"{count, plural,
    zero {لا عناصر} one {عنصر واحد} two {عنصران}
    few {# عناصر} many {# عنصرًا} other {# عنصر}}";
Ära kunagi tuvasta ainsust tingimusega count == 1. Prantsuse keel käsitleb arvu 0 ainsusena. Vene keeles on eraldi vormid few ja many. Araabia keeles on kuus mitmusekategooriat. Kasuta CLDR-i arvestavaid mitmusereegleid või sellist teeki nagu MessageFormat.NET, mis käsitleb seda õigesti.
7

Lokaliseeri Razor-vaated

Kasuta Razor-vaadetes IViewLocalizerit direktiiviga @inject. See lahendab RESX-failid vaate failitee järgi. HTML-turvaliste märgistusega stringide jaoks kasuta IHtmlLocalizerit. Sellised Tag Helperid nagu asp-for ja asp-validation-for kasutavad lokaliseeritud Display ja ErrorMessage atribuute automaatselt.

Views/Home/Index.cshtml
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedHtml

<h1>@Localizer["Welcome"]</h1>
<p>@Localizer["Greeting", User.Identity?.Name]</p>

@* IHtmlLocalizer: does NOT escape — use for RESX values with HTML *@
<p>@SharedHtml["TermsNotice"]</p>

@* Tag Helpers auto-localize Display/ErrorMessage attributes *@
<form asp-action="Register">
    <label asp-for="Name"></label>
    <input asp-for="Name" />
    <span asp-validation-for="Name"></span>
    <button type="submit">@Localizer["Submit"]</button>
</form>
IViewLocalizer lahendab RESX-failid vaate tee järgi: Views/Home/Index.cshtml otsib faili Resources/Views/Home/Index.de.resx. Kui soovid stringe vaadete vahel jagada, sisesta eraldi IStringLocalizer&lt;SharedResource&gt;.
8

Automatiseeri RESX-tõlked

Kui lokaliseerimise seadistus on valmis, tõlgi RESX-failid tehisintellektiga. Palu IDE-s oma tehisintellekti abilisel RESX-lähtefail tõlkida või hoia tõlked sünkroonis i18n Agent'i CLI-ga oma CI/CD-konveieris.

Terminal
# In your IDE, ask your AI assistant:
> Translate Resources/Controllers/HomeController.en.resx to German, Japanese, Spanish

# HomeController.de.resx created (1.2s)
# HomeController.ja.resx created (1.5s)
# HomeController.es.resx created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate Resources/Controllers/HomeController.en.resx --lang de,ja,es
Tõlgi järk-järgult — kui lisad RESX-lähtefaili uusi võtmeid, tõlgi kõigi failide uuesti loomise asemel ainult diff. Nii säilivad inimeste ülevaadatud tõlked ja vähenevad tarbetud muudatused.

Automatiseeri tõlkekvaliteet

Leia i18n-validate'i abil puuduvad võtmed ja katkised kohatäitjad enne avaldamist. Testi kasutajaliidest i18n-pseudo abil pseudotõlgetega enne päris tõlgete saabumist.

Paranda varulokaadid LocaleChain.NET-iga

.NET-i sisseehitatud CultureInfo.Parenti hierarhia kasutab ainult BCP 47 kärpimist: pt-BR taandub pt-le ja seejärel InvariantCulture'ile, jättes pt-PT vahele. LocaleChain.NET pakub kogu .NET-i ökosüsteemile seadistatavaid lokaadipõhiseid varulokaadiahelaid.

Ilma LocaleChain.NET-ita näeb pt-BR kasutaja puuduva portugali stringi korral inglise keelt isegi siis, kui täielik pt-PT tõlge on olemas. Sama probleem mõjutab es-MX-i (jätab es-419 vahele), zh-Hanti (jätab zh-Hansi vahele) ja kümneid teisi piirkondlikke variante.
Terminal
dotnet add package I18nAgent.LocaleChain
Program.cs
using I18nAgent.LocaleChain;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLocalization(o => o.ResourcesPath = "Resources");

// Zero-config: built-in chains (pt-BR -> pt-PT -> pt -> en, etc.)
LocaleChain.Configure();

// Or customize specific chains:
LocaleChain.Configure(new Dictionary<string, string[]>
{
    ["pt-BR"] = new[] { "pt-PT", "pt", "en" },
    ["es-MX"] = new[] { "es-419", "es", "en" },
});

// Register the chain-aware string localizer
builder.Services.AddSingleton(
    typeof(IStringLocalizer<>),
    typeof(LocaleChainStringLocalizer<>));

Levinud komistuskivid

Päringu kultuur pole määratud

Tõlked kuvatakse alati vaikekeeles. Kontrolli, et middleware'i konveieris kutsutaks UseRequestLocalization() ja kultuuripakkujad oleks seadistatud. Veendu, et veebilehitseja saadaks Accept-Language'i päiseid. Middleware'i toimimise kinnitamiseks testi päringustringiga ?culture=de.

RESX-faili ei leitud

IStringLocalizer tagastab tõlgitud väärtuse asemel võtme nime. Kõige tavalisem põhjus on RESX-faili nimi, mis ei vasta klassi täielikule nimeruumiteele ResourcesPathi suhtes. Luba Microsoft.Extensions.Localizationi silumislogimine, et näha raamistiku otsitud teid.

Middleware'i järjekord on vale

UseRequestLocalization() peab olema enne UseEndpoints() ja MapControllers() funktsioone. Kui see asub pärast neid, pole päringukultuur kontrollerite käitamisel määratud. .NET 6+ minimaalses hostimises kutsu seda enne app.MapControllers().

Taustalõim kasutab valet kultuuri

CultureInfo.CurrentCulture ja CurrentUICulture on lõimepõhised. Taustülesanded (Task.Run, hostitud teenused) pärivad lõimepuuli kultuuri, mitte päringu kultuuri. Taustatöö edastamisel jäädvusta ja määra kultuur selgesõnaliselt.

Soovituslik projektistruktuur

Project Structure
MyAspNetApp/
├── Controllers/
│   └── HomeController.cs
├── ViewModels/
│   └── RegisterViewModel.cs
├── Views/
│   └── Home/
│       └── Index.cshtml
├── Resources/
│   ├── Controllers/
│   │   ├── HomeController.en.resx     # English (source)
│   │   ├── HomeController.de.resx     # German
│   │   └── HomeController.ja.resx     # Japanese
│   ├── ViewModels/
│   │   ├── RegisterViewModel.en.resx
│   │   └── RegisterViewModel.de.resx
│   ├── Views/Home/
│   │   ├── Index.en.resx
│   │   └── Index.de.resx
│   └── SharedResource.en.resx
├── SharedResource.cs                  # Marker class
├── Program.cs
└── MyAspNetApp.csproj

Proovi i18n Agent'i kohe

Kukuta tõlkefail siia

JSON, YAML, PO, XML, CSV, Markdown, Properties

või klõpsa faili valimiseks

Sihtkeeled

Registreerumine pole vajalikKohene hinnang

Varulokaat I18nAgent.LocaleChain'iga

Kui piirkondlikust lokaadist, näiteks pt-BR-st, puudub tõlkevõti, liigub .NET otse muutumatusse kultuuri ega kontrolli esmalt põhilokaati pt.

Terminal
dotnet add package I18nAgent.LocaleChain
Configuration
using I18nAgent.LocaleChain;

LocaleChain.Configure(new Dictionary<string, string[]>
{
    ["pt-BR"] = new[] {"pt", "en"},
    ["zh-Hant-HK"] = new[] {"zh-Hant", "zh", "en"},
});

Vaata meie varulokaadi juhendist kõigi toetatud raamistike ja 75 sisseehitatud ahela loendit. Learn more →

Korduma kippuvad küsimused