
Az ASP.NET Core lokalizáció teljes útmutatója
Az IStringLocalizer elemtől az éles környezetig: állítsa be az erőforrás-alapú lokalizációt ASP.NET Core-ban, majd automatizálja a fordítást mesterséges intelligenciával.
Lokalizációs szolgáltatások engedélyezése
Regisztrálja a lokalizációs szolgáltatásokat a Program.cs fájlban az AddLocalization() segítségével, állítsa be a támogatott kultúrákat, és adja hozzá a kéréslokalizációs middleware-t. Ez összeköti az ASP.NET Core-alkalmazás teljes lokalizációs folyamatát.
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();RESX-erőforrásfájlok létrehozása
Az ASP.NET Core RESX (XML-erőforrás) fájlokat használ fordításokhoz. Kultúránként és osztályonként hozzon létre egy fájlt: HomeController.en.resx, HomeController.de.resx stb. A keretrendszer az aktuális kéréskultúra alapján oldja fel a megfelelő fájlt.
<!-- 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><!-- 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 { }IStringLocalizer használata vezérlőkben és szolgáltatásokban
Függőségbefecskendezéssel adjon IStringLocalizer<T> elemet bármely vezérlőhöz, szolgáltatáshoz vagy middleware-hez. A T általános típusparaméter határozza meg a betöltendő RESX-fájlt. A lefordított karakterláncokat a localizer["Key"] zárójeles szintaxissal és választható formázási paraméterekkel kérje le.
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 });
}
}Kéréskultúra-middleware beállítása
Az ASP.NET Core szolgáltatólánccal határozza meg a kérés kultúráját: lekérdezési karakterlánc, cookie, majd Accept-Language fejléc. Egyéni szolgáltatókat is hozzáadhat — például a kultúra kiolvasását egy URL-útvonalszegmensből, mint a /de/home.
// 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: 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);
}Adatannotációk lokalizálása
Az olyan ellenőrzési attribútumok, mint a [Required], [StringLength] és [Display], az ErrorMessage vagy Name tulajdonságuk RESX-kulcsnévre állításával lokalizálhatók. Engedélyezéséhez hívja meg az AddDataAnnotationsLocalization() függvényt a Program.cs fájlban.
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"Többes számok és ICU-üzenetek kezelése
A .NET nem rendelkezik az ICU-hoz hasonló beépített többesszám-szabályokkal. Egyszerű esetekben használjon külön RESX-kulcsokat (ItemCount_One, ItemCount_Other) kódbeli elágazással. Minden CLDR többesszám-kategória teljes ICU MessageFormat-támogatásához használja a MessageFormat.NET könyvtárat.
// 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 {# عنصر}}";Razor-nézetek lokalizálása
Razor-nézetekben @inject segítségével használjon IViewLocalizer elemet. A RESX-fájlokat a nézet fájlútvonala alapján oldja fel. Jelölést tartalmazó, HTML-biztos karakterláncokhoz használjon IHtmlLocalizer elemet. Az asp-for és asp-validation-for típusú Tag Helperek automatikusan a lokalizált Display és ErrorMessage attribútumokat használják.
@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>RESX-fordítások automatizálása
A lokalizáció beállítása után fordítsa le RESX-fájljait mesterséges intelligenciával. Kérje meg az IDE MI-alapú segédét a forrás RESX lefordítására, vagy használja az i18n Agent parancssori eszközét a CI/CD-folyamatban a fordítások szinkronban tartásához.
# 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,esA fordítási minőség automatizálása
Területi tartalék javítása LocaleChain.NET használatával
A .NET beépített CultureInfo.Parent hierarchiája csak BCP 47-csonkolást használ: a pt-BR pt, majd InvariantCulture értékre vált, a pt-PT változatot kihagyja. A LocaleChain.NET a teljes .NET ökoszisztémához beállítható, területenkénti tartalékláncokat biztosít.
dotnet add package I18nAgent.LocaleChainusing 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<>));Gyakori buktatók
Nincs beállítva a kérés kultúrája
A RESX-fájl nem található
Hibás middleware-sorrend
A háttérszál rossz kultúrát használ
Ajánlott projektszerkezet
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.csprojTry i18n Agent Now
Drop your translation file here
JSON, YAML, PO, XML, CSV, Markdown, Properties
or click to browse
Target languages
Területi tartalék I18nAgent.LocaleChain használatával
Ha egy fordítási kulcs hiányzik egy regionális területi beállításból, például a pt-BR változatból, a .NET a pt szülőterület ellenőrzése helyett közvetlenül az invariáns kultúrára vált.
dotnet add package I18nAgent.LocaleChainusing I18nAgent.LocaleChain;
LocaleChain.Configure(new Dictionary<string, string[]>
{
["pt-BR"] = new[] {"pt", "en"},
["zh-Hant-HK"] = new[] {"zh-Hant", "zh", "en"},
});A támogatott keretrendszerek és a 75 beépített lánc teljes listájáért tekintse meg Területi tartalék útmutatónkat. Learn more →