Skip to main content

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.

1

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.

Az AddLocalization() regisztrálja az IStringLocalizer és IStringLocalizerFactory elemet a DI-tárolóban. A ResourcesPath megadja a keretrendszernek a .resx fájlok helyét. Az AddViewLocalization() engedélyezi az IViewLocalizer elemet Razor-nézetekben, az AddDataAnnotationsLocalization() pedig a lokalizált ellenőrzési üzeneteket.
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

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.{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>
A vezérlők és nézetek között megosztott karakterláncokhoz — gombcímkékhez, navigációs elemekhez és gyakori ellenőrzési üzenetekhez — használjon saját RESX-fájlokkal rendelkező SharedResource osztályt. Így nem kell kulcsokat ismételni több tucat vezérlőspecifikus RESX-fájlban.
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

IStringLocalizer használata vezérlőkben és szolgáltatásokban

Függőségbefecskendezéssel adjon IStringLocalizer&lt;T&gt; 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.

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 });
    }
}
Ha az IStringLocalizer a lefordított érték helyett a kulcs nevét adja vissza, ellenőrizze: (1) a RESX-fájlnév megfelel-e az osztály névterének, (2) az AddLocalization() ResourcesPath értéke a megfelelő mappára mutat-e, és (3) a RESX-fájl Build Action értéke Embedded Resource-e a Visual Studióban.
4

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.

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);
}
A middleware sorrendje számít. A UseRequestLocalization() hívásnak a UseRouting() után, de a UseEndpoints() vagy MapControllers() előtt kell állnia. Ha túl későn szerepel, a vezérlők végrehajtásakor még nem lesz beállítva a kultúra.
5

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.

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"
Az adatannotációk lokalizációja a ViewModel osztálynevét használja a RESX-fájlok megtalálásához, nem a vezérlőt. RegisterViewModel esetén a keretrendszer a Resources/ViewModels/RegisterViewModel.de.resx fájlt keresi. Ha a RESX-fájlok a vezérlőről kapták nevüket, az ellenőrzési üzenetek nem lokalizálódnak.
6

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.

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 {# عنصر}}";
Soha ne használjon count == 1 feltételt az egyes szám felismeréséhez. A francia a 0 értéket egyes számként kezeli, az orosznak külön „few” és „many” alakja, az arabnak hat többesszám-kategóriája van. Használjon CLDR-t ismerő szabályokat vagy ezt helyesen kezelő könyvtárat, például MessageFormat.NET-et.
7

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.

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>
Az IViewLocalizer a nézet útvonala alapján oldja fel a RESX-fájlokat: a Views/Home/Index.cshtml a Resources/Views/Home/Index.de.resx fájlt keresi. Nézetek közötti karakterláncmegosztáshoz külön fecskendezzen be IStringLocalizer&lt;SharedResource&gt; elemet.
8

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.

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
Fordítson fokozatosan — új kulcsok forrás RESX-fájlhoz adásakor csak a különbséget fordítsa le az összes fájl újragenerálása helyett. Így megmaradnak az ember által ellenőrzött fordítások, és minimális a változtatási zaj.

A fordítási minőség automatizálása

Az i18n-validate segítségével még kiadás előtt találja meg a hiányzó kulcsokat és hibás helyőrzőket. Az i18n-pseudo használatával valódi fordítások beérkezése előtt tesztelje a felületet pszeudofordításokkal.

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.

LocaleChain.NET nélkül egy pt-BR felhasználó hiányzó portugál karakterláncnál angol szöveget lát — akkor is, ha teljes pt-PT fordítás áll rendelkezésre. Ugyanez érinti az es-MX (kihagyja es-419), zh-Hant (kihagyja zh-Hans) és több tucat más regionális változatot.
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<>));

Gyakori buktatók

Nincs beállítva a kérés kultúrája

A fordítások mindig az alapértelmezett nyelven jelennek meg. Ellenőrizze, hogy a UseRequestLocalization() szerepel-e a middleware-folyamatban, és be vannak-e állítva a kultúraszolgáltatók. Ellenőrizze, hogy a böngésző küld-e Accept-Language fejlécet. A middleware működését a lekérdezési karakterlánc ?culture=de értékével tesztelje.

A RESX-fájl nem található

Az IStringLocalizer a lefordított érték helyett a kulcs nevét adja vissza. A leggyakoribb ok, hogy a RESX-fájlnév nem egyezik az osztály ResourcesPath értékhez viszonyított teljes névtérútvonalával. Engedélyezze a Microsoft.Extensions.Localization hibakeresési naplózását a keretrendszer által keresett útvonalak megtekintéséhez.

Hibás middleware-sorrend

A UseRequestLocalization() elemnek a UseEndpoints() és MapControllers() előtt kell szerepelnie. Ha utánuk áll, a vezérlők végrehajtásakor nincs beállítva a kérés kultúrája. .NET 6 vagy újabb minimális kiszolgálásnál az app.MapControllers() előtt hívja meg.

A háttérszál rossz kultúrát használ

A CultureInfo.CurrentCulture és CurrentUICulture szálankénti. A háttérfeladatok (Task.Run, üzemeltetett szolgáltatások) a szálkészlet, nem a kérés kultúráját öröklik. Háttérmunka indításakor kifejezetten rögzítse és állítsa be a kultúrát.

Ajánlott projektszerkezet

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

Try i18n Agent Now

Drop your translation file here

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

or click to browse

Target languages

No signup requiredInstant estimate

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.

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

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 →

Gyakran Ismételt Kérdések