
ASP.NET Core yerelleştirmesine yönelik eksiksiz rehber
IStringLocalizer'dan üretim ortamına kadar ASP.NET Core'da kaynak tabanlı yerelleştirmeyi kurun ve ardından çevirileri yapay zeka ile otomatikleştirin.
Yerelleştirme hizmetlerini etkinleştirin
Yerelleştirme hizmetlerini Program.cs içinde AddLocalization() ile kaydedin, desteklenen kültürleri yapılandırın ve istek yerelleştirme ara yazılımını ekleyin. Bu işlem, ASP.NET Core uygulamanızın yerelleştirme işlem hattının tamamını bağlar.
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 kaynak dosyalarını oluşturun
ASP.NET Core, çeviriler için RESX (XML kaynağı) dosyalarını kullanır. Her kültür ve sınıf için bir dosya oluşturun: HomeController.en.resx, HomeController.de.resx vb. Çerçeve, geçerli istek kültürüne göre doğru dosyayı çözümler.
<!-- 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 { }Denetleyicilerde ve hizmetlerde IStringLocalizer kullanın
IStringLocalizer<T> bileşenini bağımlılık ekleme aracılığıyla herhangi bir denetleyiciye, hizmete veya ara yazılıma ekleyin. T genel tür parametresi hangi RESX dosyasının yükleneceğini belirler. Çevrilmiş dizeleri almak için isteğe bağlı biçim parametreleriyle localizer["Key"] köşeli parantez söz dizimini kullanın.
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 });
}
}İstek kültürü ara yazılımını yapılandırın
ASP.NET Core, istek kültürünü sırasıyla sorgu dizesi, çerez ve Accept-Language üst bilgisinden oluşan bir sağlayıcı zinciriyle belirler. Özel sağlayıcılar ekleyebilirsiniz; örneğin kültürü /de/home gibi bir URL yolu bölümünden okuyabilirsiniz.
// 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);
}Veri ek açıklamalarını yerelleştirin
[Required], [StringLength] ve [Display] gibi doğrulama öznitelikleri, ErrorMessage veya Name özellikleri RESX anahtar adlarına ayarlanarak yerelleştirilebilir. Bunu etkinleştirmek için Program.cs içinde AddDataAnnotationsLocalization() çağrısını yapın.
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"Çoğulları ve ICU iletilerini yönetin
.NET, ICU gibi yerleşik çoğul kuralı desteğine sahip değildir. Basit durumlarda bir kod anahtarıyla ayrı RESX anahtarları (ItemCount_One, ItemCount_Other) kullanın. Tüm CLDR çoğul kategorilerinde eksiksiz ICU MessageFormat desteği için MessageFormat.NET kitaplığını kullanın.
// 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 görünümlerini yerelleştirin
Razor görünümlerinde @inject aracılığıyla IViewLocalizer kullanın. Bu bileşen RESX dosyalarını görünümün dosya yoluna göre çözümler. İşaretleme içeren ve HTML açısından güvenli dizeler için IHtmlLocalizer kullanın. asp-for ve asp-validation-for gibi Tag Helpers bileşenleri, yerelleştirilmiş Display ve ErrorMessage özniteliklerini otomatik olarak kullanır.
@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 çevirilerini otomatikleştirin
Yerelleştirme kurulumunuz tamamlandıktan sonra RESX dosyalarınızı yapay zeka kullanarak çevirin. IDE'nizde yapay zeka yardımcınızdan kaynak RESX dosyanızı çevirmesini isteyin veya çevirileri eş zamanlı tutmak için CI/CD işlem hattınızda i18n Agent CLI'ı kullanın.
# 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Çeviri kalitesini otomatikleştirin
LocaleChain.NET ile yerel ayar yedeklemesini düzeltin
.NET'in yerleşik CultureInfo.Parent hiyerarşisi yalnızca BCP 47 kısaltmasını kullanır: pt-BR önce pt'ye, ardından pt-PT'yi atlayarak InvariantCulture'a geçer. LocaleChain.NET, tüm .NET ekosistemi için yerel ayar başına yapılandırılabilir yedekleme zincirleri sağlar.
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<>));Yaygın hatalar
İstekte kültürün ayarlanmaması
RESX dosyasının bulunamaması
Ara yazılım sırasının yanlış olması
Arka plan iş parçacığının yanlış kültürü kullanması
Önerilen proje yapısı
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.csproji18n Agent'ı şimdi deneyin
Çeviri dosyanızı buraya bırakın
JSON, YAML, PO, XML, CSV, Markdown, Properties
veya göz atmak için tıklayın
Hedef diller
I18nAgent.LocaleChain ile yerel ayar yedeklemesi
pt-BR gibi bölgesel bir yerel ayarda çeviri anahtarı eksik olduğunda .NET, önce üst yerel ayar pt'yi denetlemek yerine doğrudan değişmez kültüre geçer.
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"},
});Desteklenen çerçevelerin ve 75 yerleşik zincirin tam listesi için Yerel Ayar Yedekleme Rehberimize bakın. Learn more →