
Pilnīgs ASP.NET Core lokalizācijas ceļvedis
No IStringLocalizer līdz produkcijas videi: iestatiet uz resursiem balstītu lokalizāciju ASP.NET Core, pēc tam automatizējiet tulkošanu ar MI.
Iespējot lokalizācijas pakalpojumus
Reģistrējiet lokalizācijas pakalpojumus Program.cs ar AddLocalization(), konfigurējiet atbalstītās kultūras un pievienojiet pieprasījuma lokalizācijas starpprogrammatūru. Tas savieno visu ASP.NET Core lietotnes lokalizācijas konveijeru.
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();Izveidot RESX resursu failus
ASP.NET Core tulkojumiem izmanto RESX (XML resursu) failus. Izveidojiet vienu failu katrai kultūrai katrai klasei: HomeController.en.resx, HomeController.de.resx utt. Sistēma atrisina pareizo failu pēc pašreizējā pieprasījuma kultūras.
<!-- 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 { }Izmantot IStringLocalizer kontrolleros un pakalpojumos
Ar atkarību injicēšanu ievadiet IStringLocalizer<T> jebkurā kontrollerī, pakalpojumā vai starpprogrammatūrā. Vispārīgais tipa parametrs T nosaka, kuru RESX failu ielādēt. Tulkotu virkņu iegūšanai izmantojiet iekavu sintaksi localizer["Key"] un pēc izvēles formāta parametrus.
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 });
}
}Konfigurēt pieprasījuma kultūras starpprogrammatūru
ASP.NET Core nosaka pieprasījuma kultūru ar nodrošinātāju ķēdi: vaicājuma virkni, sīkfailu un galveni Accept-Language (šādā secībā). Varat pievienot pielāgotus nodrošinātājus, piemēram, kultūras nolasīšanai no URL maršruta segmenta /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);
}Lokalizēt datu anotācijas
Validācijas atribūtus, piemēram, [Required], [StringLength] un [Display], var lokalizēt, iestatot to rekvizītus ErrorMessage vai Name uz RESX atslēgu nosaukumiem. Program.cs izsauciet AddDataAnnotationsLocalization(), lai to iespējotu.
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"Apstrādāt daudzskaitli un ICU ziņojumus
.NET nav ICU līdzīga iebūvēta daudzskaitļa kārtulu atbalsta. Vienkāršos gadījumos izmantojiet atsevišķas RESX atslēgas (ItemCount_One, ItemCount_Other) un koda pārslēgu. Pilnam ICU MessageFormat atbalstam visās CLDR daudzskaitļa kategorijās izmantojiet bibliotēku MessageFormat.NET.
// 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 {# عنصر}}";Lokalizēt Razor skatus
Razor skatos izmantojiet IViewLocalizer ar @inject. Tas atrisina RESX failus pēc skata faila ceļa. HTML drošām virknēm ar marķējumu izmantojiet IHtmlLocalizer. Tādi tagu palīgi kā asp-for un asp-validation-for automātiski izmanto lokalizētus Display un ErrorMessage atribūtus.
@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>Automatizēt RESX tulkošanu
Kad lokalizācijas iestatīšana ir pabeigta, tulkojiet RESX failus ar MI. IDE lūdziet MI asistentam iztulkot avota RESX vai izmantojiet i18n Agent CLI CI/CD konveijerā, lai tulkojumi paliktu sinhronizēti.
# 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,esAutomatizēt tulkojumu kvalitāti
Izlabojiet lokalizācijas atkāpšanos ar LocaleChain.NET
.NET iebūvētā CultureInfo.Parent hierarhija izmanto tikai BCP 47 saīsināšanu: pt-BR atkāpjas uz pt, tad InvariantCulture, izlaižot pt-PT. LocaleChain.NET nodrošina konfigurējamas atkāpšanās ķēdes katrai lokalizācijai visā .NET ekosistēmā.
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<>));Biežākās kļūdas
Pieprasījumā nav iestatīta kultūra
RESX fails nav atrasts
Nepareiza starpprogrammatūras secība
Fona pavediens izmanto nepareizu kultūru
Ieteicamā projekta struktūra
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.csprojIzmēģiniet i18n Agent tūlīt
Nometiet tulkošanas failu šeit
JSON, YAML, PO, XML, CSV, Markdown, Properties
vai noklikšķiniet, lai izvēlētos
Mērķa valodas
Lokalizācijas atkāpšanās ar I18nAgent.LocaleChain
Ja reģionālajā lokalizācijā, piemēram, pt-BR, trūkst tulkojuma atslēgas, .NET uzreiz pāriet uz invarianto kultūru, nevis vispirms pārbauda vecāklokalizāciju pt.
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"},
});Pilnu atbalstīto sistēmu sarakstu un 75 iebūvētās ķēdes skatiet mūsu lokalizāciju atkāpšanās ceļvedī. Learn more →