Skip to main content

Celovit vodnik po lokalizaciji ASP.NET Core

Od IStringLocalizer do produkcije: v ASP.NET Core nastavite lokalizacijo na podlagi virov, nato pa prevode avtomatizirajte z umetno inteligenco.

1

Omogočite lokalizacijske storitve

V Program.cs z AddLocalization() registrirajte lokalizacijske storitve, nastavite podprte kulture in dodajte vmesno programsko opremo za lokalizacijo zahtev. Tako povežete celoten lokalizacijski pipeline svoje aplikacije ASP.NET Core.

AddLocalization() v vsebniku DI registrira IStringLocalizer in IStringLocalizerFactory. ResourcesPath ogrodju pove, kje naj poišče Vaše datoteke .resx. AddViewLocalization() v pogledih Razor omogoči IViewLocalizer, AddDataAnnotationsLocalization() pa lokalizirana sporočila preverjanja.
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

Ustvarite datoteke virov RESX

ASP.NET Core za prevode uporablja datoteke RESX (viri XML). Za vsak razred in kulturo ustvarite eno datoteko: HomeController.en.resx, HomeController.de.resx itd. Ogrodje ustrezno datoteko razreši glede na trenutno kulturo zahteve.

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>
Za besedila, ki si jih delijo krmilniki in pogledi, uporabite razred SharedResource z lastnimi datotekami RESX: oznake gumbov, navigacijske elemente in pogosta sporočila preverjanja. Tako ključev ne podvajate v desetinah datotek RESX za posamezne krmilnike.
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

Uporabljajte IStringLocalizer v krmilnikih in storitvah

Z vstavljanjem odvisnosti v kateri koli krmilnik, storitev ali vmesno programsko opremo vstavite IStringLocalizer&lt;T&gt;. Splošni parameter vrste T določa, katera datoteka RESX se naloži. Za pridobivanje prevedenih besedil z neobveznimi oblikovnimi parametri uporabite skladnjo oglatih oklepajev localizer["Key"].

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 });
    }
}
Če IStringLocalizer namesto prevedene vrednosti vrne ime ključa, preverite tri stvari: (1) poimenovanje datoteke RESX se ujema z imenskim prostorom razreda, (2) ResourcesPath v AddLocalization() kaže v pravo mapo in (3) lastnost Build Action datoteke RESX je v Visual Studio nastavljena na Embedded Resource.
4

Nastavite vmesno programsko opremo za kulturo zahteve

ASP.NET Core določi kulturo zahteve z verigo ponudnikov: poizvedbenim nizom, piškotkom in glavo Accept-Language (v tem vrstnem redu). Dodate lahko ponudnike po meri, na primer takega, ki kulturo prebere iz odseka poti naslova URL, kot 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);
}
Vrstni red vmesne programske opreme je pomemben. UseRequestLocalization() morate poklicati za UseRouting(), vendar pred UseEndpoints() ali MapControllers(). Če ga postavite prepozno, kultura ob izvajanju Vaših krmilnikov ne bo nastavljena.
5

Lokalizirajte podatkovne opombe

Atribute preverjanja, kot so [Required], [StringLength] in [Display], lahko lokalizirate tako, da njihove lastnosti ErrorMessage ali Name nastavite na imena ključev RESX. To omogočite s klicem 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"
Lokalizacija podatkovnih opomb datoteke RESX poišče po imenu razreda ViewModel, ne Controller. Ogrodje za RegisterViewModel poišče Resources/ViewModels/RegisterViewModel.de.resx. Če so Vaše datoteke RESX poimenovane po krmilniku, sporočila preverjanja ne bodo lokalizirana.
6

Obravnavajte množinske oblike in sporočila ICU

.NET nima vgrajene podpore za množinska pravila, kot jo ima ICU. Za preproste primere uporabite ločene ključe RESX (ItemCount_One, ItemCount_Other) s stikalom v kodi. Za popolno podporo ICU MessageFormat v vseh množinskih kategorijah CLDR uporabite knjižnico 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 {# عنصر}}";
Za zaznavanje edninskih oblik nikoli ne uporabljajte count == 1. Francoščina 0 obravnava kot ednino. Ruščina ima ločeni obliki 'few' in 'many'. Arabščina ima šest množinskih kategorij. Uporabite množinska pravila, ki upoštevajo CLDR, ali knjižnico, kot je MessageFormat.NET, ki to pravilno obravnava.
7

Lokalizirajte poglede Razor

IViewLocalizer v pogledih Razor uporabite prek @inject. Datoteke RESX razreši glede na datotečno pot pogleda. Za besedila z oznakami, varna za HTML, uporabite IHtmlLocalizer. Pomožne oznake, kot sta asp-for in asp-validation-for, samodejno uporabljajo lokalizirana atributa Display in 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 datoteke RESX razreši po poti pogleda: Views/Home/Index.cshtml poišče Resources/Views/Home/Index.de.resx. Če želite besedila souporabljati med pogledi, posebej vstavite IStringLocalizer&lt;SharedResource&gt;.
8

Avtomatizirajte prevode RESX

Ko je nastavitev lokalizacije končana, svoje datoteke RESX prevedite z umetno inteligenco. V svojem razvojnem okolju IDE prosite pomočnika umetne inteligence, naj prevede izvorni RESX, ali pa v pipelineu CI/CD uporabite CLI i18n Agent, da bodo prevodi usklajeni.

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
Prevajajte postopoma: ko v izvorno datoteko RESX dodate nove ključe, prevedite le diff in ne ustvarjajte znova vseh datotek. Tako ohranite prevode, ki so jih pregledali ljudje, in zmanjšate nepotrebne spremembe.

Avtomatizirajte kakovost prevodov

Z i18n-validate odkrijte manjkajoče ključe in poškodovane označbe mest, preden dosežejo uporabnike. Z i18n-pseudo preizkusite uporabniški vmesnik s psevdoprevodi, preden prispejo pravi prevodi.

Popravite nadomestne jezikovne različice z LocaleChain.NET

Vgrajena hierarhija CultureInfo.Parent v .NET uporablja samo krajšanje BCP 47: pt-BR preide na pt in nato InvariantCulture ter preskoči pt-PT. LocaleChain.NET ponuja nastavljive nadomestne verige za posamezne jezikovne različice v celotnem ekosistemu .NET.

Brez LocaleChain.NET uporabnik pt-BR ob manjkajočem portugalskem besedilu vidi angleščino, tudi če imate popoln prevod pt-PT. Ista težava prizadene es-MX (preskoči es-419), zh-Hant (preskoči zh-Hans) in desetine drugih regionalnih različic.
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<>));

Pogoste pasti

Kultura zahteve ni nastavljena

Prevodi vedno kažejo privzeti jezik. Preverite, ali je UseRequestLocalization() poklican v pipelineu vmesne programske opreme in ali so ponudniki kulture nastavljeni. Preverite, ali brskalnik pošilja glave Accept-Language. Z ?culture=de v poizvedbenem nizu preverite, ali vmesna programska oprema deluje.

Datoteke RESX ni mogoče najti

IStringLocalizer namesto prevedene vrednosti vrne ime ključa. Najpogostejši vzrok je ime datoteke RESX, ki se glede na ResourcesPath ne ujema s polno potjo imenskega prostora razreda. Vključite razhroščevalno beleženje za Microsoft.Extensions.Localization, da vidite, katere poti preiskuje ogrodje.

Napačen vrstni red vmesne programske opreme

UseRequestLocalization() mora biti pred UseEndpoints() in MapControllers(). Če ga postavite za njiju, kultura zahteve ob izvajanju krmilnikov ni nastavljena. Pri minimalnem gostovanju v .NET 6+ ga pokličite pred app.MapControllers().

Nit v ozadju uporablja napačno kulturo

CultureInfo.CurrentCulture in CurrentUICulture veljata za posamezno nit. Opravila v ozadju (Task.Run, gostovane storitve) podedujejo kulturo skupine niti, ne kulture zahteve. Pri pošiljanju dela v ozadje kulturo izrecno zajemite in nastavite.

Priporočena struktura projekta

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

Preizkusite i18n Agent zdaj

Spustite prevajalsko datoteko sem

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

ali kliknite za izbiro

Ciljni jeziki

Registracija ni potrebnaTakojšnja ocena

Nadomestne jezikovne različice z I18nAgent.LocaleChain

Ko v regionalni jezikovni različici, kot je pt-BR, manjka prevajalski ključ, .NET preskoči naravnost na nespremenljivo kulturo, namesto da bi najprej preveril nadrejeno različico 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"},
});

V našem vodniku po nadomestnih jezikovnih različicah si oglejte celoten seznam podprtih ogrodij in 75 vgrajenih verig. Learn more →

Pogosta vprašanja