Skip to main content

Kompletná príručka lokalizácie ASP.NET Core

Od IStringLocalizer po produkciu: nastavte lokalizáciu ASP.NET Core pomocou prostriedkov a potom automatizujte preklady pomocou AI.

1

Povoľte lokalizačné služby

Zaregistrujte lokalizačné služby v Program.cs pomocou AddLocalization(), nakonfigurujte podporované kultúry a pridajte middleware lokalizácie požiadaviek. Prepojíte tak celú lokalizačnú pipeline svojej aplikácie ASP.NET Core.

AddLocalization() registruje IStringLocalizer a IStringLocalizerFactory v kontajneri DI. ResourcesPath určuje frameworku umiestnenie Vašich súborov .resx. AddViewLocalization() povoľuje IViewLocalizer v zobrazeniach Razor a AddDataAnnotationsLocalization() povoľuje lokalizované validačné správy.
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

Vytvorte súbory prostriedkov RESX

ASP.NET Core používa na preklady súbory RESX (prostriedky XML). Vytvorte jeden súbor pre každú kultúru a triedu: HomeController.en.resx, HomeController.de.resx atď. Framework vyhodnotí správny súbor podľa kultúry aktuálnej požiadavky.

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>
Pre reťazce zdieľané medzi kontrolérmi a zobrazeniami – štítky tlačidiel, navigačné položky a bežné validačné správy – používajte triedu SharedResource s vlastnými súbormi RESX. Vyhnete sa duplikovaniu kľúčov v desiatkach súborov RESX pre konkrétne kontroléry.
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

Používajte IStringLocalizer v kontroléroch a službách

Prostredníctvom vkladania závislostí injektujte IStringLocalizer&lt;T&gt; do ľubovoľného kontroléra, služby alebo middleware. Generický typový parameter T určuje načítaný súbor RESX. Preložené reťazce získajte hranatou syntaxou localizer["Key"] s voliteľnými parametrami formátu.

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 });
    }
}
Ak IStringLocalizer namiesto preloženej hodnoty vracia názov kľúča, skontrolujte tri veci: (1) pomenovanie súboru RESX zodpovedá mennému priestoru triedy, (2) ResourcesPath v AddLocalization() odkazuje na správny priečinok a (3) Build Action súboru RESX je vo Visual Studio nastavená na Embedded Resource.
4

Nakonfigurujte middleware kultúry požiadaviek

ASP.NET Core určuje kultúru požiadavky pomocou reťazca poskytovateľov: reťazec dopytu, súbor cookie a hlavička Accept-Language (v tomto poradí). Môžete pridať vlastných poskytovateľov, napríklad čítanie kultúry zo segmentu trasy URL, ako je /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);
}
Na poradí middleware záleží. UseRequestLocalization() sa musí volať po UseRouting(), ale pred UseEndpoints() alebo MapControllers(). Ak je umiestnené príliš neskoro, pri spustení kontrolérov kultúra nebude nastavená.
5

Lokalizujte dátové anotácie

Validačné atribúty, ako sú [Required], [StringLength] a [Display], môžete lokalizovať nastavením ich vlastností ErrorMessage alebo Name na názvy kľúčov RESX. Povoľte to volaním AddDataAnnotationsLocalization() v Program.cs.

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"
Lokalizácia dátových anotácií vyhľadáva súbory RESX podľa názvu triedy ViewModel, nie kontroléra. Pre RegisterViewModel hľadá framework Resources/ViewModels/RegisterViewModel.de.resx. Ak sú Vaše súbory RESX pomenované podľa kontroléra, validačné správy sa nelokalizujú.
6

Spracujte tvary množného čísla a správy ICU

.NET nemá vstavanú podporu pravidiel množného čísla ako ICU. V jednoduchých prípadoch použite samostatné kľúče RESX (ItemCount_One, ItemCount_Other) s prepínačom v kóde. Na úplnú podporu ICU MessageFormat vo všetkých kategóriách množného čísla CLDR použite knižnicu MessageFormat.NET.

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 {# عنصر}}";
Na rozpoznanie jednotného čísla nikdy nepoužívajte count == 1. Francúzština považuje 0 za jednotné číslo. Ruština má samostatné tvary 'few' a 'many'. Arabčina má šesť kategórií množného čísla. Používajte pravidlá zohľadňujúce CLDR alebo knižnicu, ako je MessageFormat.NET, ktorá ich spracúva správne.
7

Lokalizujte zobrazenia Razor

V zobrazeniach Razor používajte IViewLocalizer prostredníctvom @inject. Vyhodnocuje súbory RESX podľa cesty k súboru zobrazenia. Pri reťazcoch s bezpečnými značkami HTML použite IHtmlLocalizer. Pomocné značky ako asp-for a asp-validation-for automaticky používajú lokalizované atribúty Display a ErrorMessage.

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 vyhodnocuje súbory RESX podľa cesty zobrazenia: Views/Home/Index.cshtml hľadá Resources/Views/Home/Index.de.resx. Ak chcete reťazce zdieľať medzi zobrazeniami, injektujte samostatne IStringLocalizer&lt;SharedResource&gt;.
8

Automatizujte preklady RESX

Po dokončení nastavenia lokalizácie preložte svoje súbory RESX pomocou AI. Vo svojom IDE požiadajte asistenta AI o preklad zdrojového RESX alebo použite CLI i18n Agent vo svojej pipeline CI/CD, aby preklady zostali synchronizované.

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
Prekladajte prírastkovo – po pridaní nových kľúčov do zdrojového súboru RESX preložte iba rozdiel namiesto opätovného generovania všetkých súborov. Zachováte tak preklady skontrolované človekom a obmedzíte zbytočné zmeny.

Automatizujte kvalitu prekladu

Pomocou i18n-validate odhaľte chýbajúce kľúče a poškodené zástupné symboly ešte pred vydaním. Kým dorazia skutočné preklady, otestujte svoje rozhranie pseudoprekladmi pomocou i18n-pseudo.

Opravte náhradné lokalizácie pomocou LocaleChain.NET

Vstavaná hierarchia CultureInfo.Parent v .NET používa iba skracovanie BCP 47: pt-BR prejde na pt a potom InvariantCulture, pričom preskočí pt-PT. LocaleChain.NET ponúka konfigurovateľné reťazce náhrad pre jednotlivé lokalizácie v celom ekosystéme .NET.

Bez LocaleChain.NET uvidí používateľ pt-BR pri chýbajúcom portugalskom reťazci angličtinu, aj keď máte úplný preklad pt-PT. Rovnaký problém postihuje es-MX (preskočí es-419), zh-Hant (preskočí zh-Hans) a desiatky ďalších regionálnych variantov.
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<>));

Bežné nástrahy

Požiadavka nemá nastavenú kultúru

Preklady vždy zobrazujú predvolený jazyk. Skontrolujte volanie UseRequestLocalization() v pipeline middleware a konfiguráciu poskytovateľov kultúry. Overte, že prehliadač odosiela hlavičky Accept-Language. Funkčnosť middleware potvrďte testom s ?culture=de v reťazci dopytu.

Súbor RESX sa nenašiel

IStringLocalizer vracia názov kľúča namiesto preloženej hodnoty. Najčastejšou príčinou je názov súboru RESX, ktorý nezodpovedá úplnej ceste menného priestoru triedy vzhľadom na ResourcesPath. Povoľte ladiace zaznamenávanie pre Microsoft.Extensions.Localization a pozrite si cesty, ktoré framework prehľadáva.

Nesprávne poradie middleware

UseRequestLocalization() musí byť pred UseEndpoints() a MapControllers(). Ak je za nimi, pri spustení kontrolérov nebude kultúra požiadavky nastavená. V minimálnom hostingu .NET 6+ ho volajte pred app.MapControllers().

Vlákno na pozadí používa nesprávnu kultúru

CultureInfo.CurrentCulture a CurrentUICulture sa vzťahujú na jednotlivé vlákna. Úlohy na pozadí (Task.Run, hostované služby) dedia kultúru fondu vlákien, nie kultúru požiadavky. Pri odosielaní práce na pozadí kultúru explicitne zachyťte a nastavte.

Odporúčaná štruktúra projektu

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

Vyskúšajte i18n Agent teraz

Potiahnite súbor na preklad sem

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

alebo kliknite a vyberte súbor

Cieľové jazyky

Bez registrácieOkamžitý odhad

Náhradná lokalizácia pomocou I18nAgent.LocaleChain

Keď v regionálnej lokalizácii, ako je pt-BR, chýba prekladový kľúč, .NET prejde priamo na invariantnú kultúru namiesto toho, aby najprv skontroloval nadradenú lokalizáciu 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"},
});

Úplný zoznam podporovaných frameworkov a 75 vstavaných reťazcov nájdete v našej príručke k náhradným lokalizáciám. Learn more →

Často kladené otázky