Skip to main content

ASP.NET Core लोकलाइज़ेशन की संपूर्ण गाइड

IStringLocalizer से प्रोडक्शन तक: ASP.NET Core में रिसोर्स-आधारित लोकलाइज़ेशन सेट अप करें, फिर AI से अनुवादों को ऑटोमेट करें।

1

लोकलाइज़ेशन सेवाएँ चालू करें

Program.cs में AddLocalization() के साथ लोकलाइज़ेशन सेवाएँ रजिस्टर करें, समर्थित कल्चर कॉन्फ़िगर करें और रिक्वेस्ट लोकलाइज़ेशन मिडलवेयर जोड़ें। इससे आपके ASP.NET Core एप्लिकेशन के लिए पूरी लोकलाइज़ेशन पाइपलाइन तैयार हो जाती है।

AddLocalization() DI कंटेनर में IStringLocalizer और IStringLocalizerFactory को रजिस्टर करता है। ResourcesPath फ़्रेमवर्क को बताता है कि आपकी .resx फ़ाइलें कहाँ मिलेंगी। AddViewLocalization() Razor व्यू में IViewLocalizer चालू करता है और AddDataAnnotationsLocalization() स्थानीयकृत वैलिडेशन संदेशों को चालू करता है।
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 रिसोर्स फ़ाइलें बनाएँ

ASP.NET Core अनुवादों के लिए RESX (XML रिसोर्स) फ़ाइलों का उपयोग करता है। प्रत्येक क्लास और कल्चर के लिए एक फ़ाइल बनाएँ: HomeController.en.resx, HomeController.de.resx आदि। फ़्रेमवर्क मौजूदा रिक्वेस्ट कल्चर के आधार पर सही फ़ाइल चुनता है।

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>
कंट्रोलर और व्यू में साझा की जाने वाली स्ट्रिंग—जैसे बटन लेबल, नेविगेशन आइटम और सामान्य वैलिडेशन संदेश—के लिए अपनी RESX फ़ाइलों वाली SharedResource क्लास का उपयोग करें। इससे दर्जनों कंट्रोलर-विशिष्ट RESX फ़ाइलों में एक ही कुंजी दोहराने की आवश्यकता नहीं पड़ती।
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 का उपयोग करें

डिपेंडेंसी इंजेक्शन के माध्यम से किसी भी कंट्रोलर, सेवा या मिडलवेयर में IStringLocalizer&lt;T&gt; इंजेक्ट करें। जेनेरिक टाइप पैरामीटर T तय करता है कि कौन-सी RESX फ़ाइल लोड होगी। वैकल्पिक फ़ॉर्मैट पैरामीटर के साथ अनूदित स्ट्रिंग पाने के लिए ब्रैकेट सिंटैक्स 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 });
    }
}
यदि IStringLocalizer अनूदित मान के बजाय कुंजी का नाम लौटाता है, तो तीन चीज़ें जाँचें: (1) RESX फ़ाइल का नाम क्लास नेमस्पेस से मेल खाता हो, (2) AddLocalization() में ResourcesPath सही फ़ोल्डर की ओर इंगित करता हो और (3) Visual Studio में RESX फ़ाइल का Build Action Embedded Resource पर सेट हो।
4

रिक्वेस्ट कल्चर मिडलवेयर कॉन्फ़िगर करें

ASP.NET Core प्रोवाइडर की एक शृंखला का उपयोग करके रिक्वेस्ट कल्चर तय करता है: क्वेरी स्ट्रिंग, कुकी और Accept-Language हेडर (इसी क्रम में)। आप कस्टम प्रोवाइडर भी जोड़ सकते हैं—उदाहरण के लिए, /de/home जैसे URL रूट सेगमेंट से कल्चर पढ़ने वाला प्रोवाइडर।

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);
}
मिडलवेयर का क्रम महत्वपूर्ण है। UseRequestLocalization() को UseRouting() के बाद, लेकिन UseEndpoints() या MapControllers() से पहले कॉल किया जाना चाहिए। इसे बहुत देर से रखने पर आपके कंट्रोलर के चलने तक कल्चर सेट नहीं होगा।
5

डेटा एनोटेशन को स्थानीयकृत करें

[Required], [StringLength] और [Display] जैसे वैलिडेशन एट्रिब्यूट की ErrorMessage या Name प्रॉपर्टी को RESX कुंजी के नाम पर सेट करके उन्हें स्थानीयकृत किया जा सकता है। इसे चालू करने के लिए Program.cs में AddDataAnnotationsLocalization() कॉल करें।

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"
डेटा एनोटेशन लोकलाइज़ेशन RESX फ़ाइलें खोजने के लिए Controller नहीं, बल्कि ViewModel क्लास का नाम इस्तेमाल करता है। RegisterViewModel के लिए फ़्रेमवर्क Resources/ViewModels/RegisterViewModel.de.resx खोजता है। यदि आपकी RESX फ़ाइलों के नाम कंट्रोलर पर आधारित हैं, तो वैलिडेशन संदेश स्थानीयकृत नहीं होंगे।
6

बहुवचन और ICU संदेशों को संभालें

.NET में ICU जैसा अंतर्निहित बहुवचन नियम समर्थन नहीं है। सामान्य मामलों में कोड स्विच के साथ अलग-अलग RESX कुंजियों (ItemCount_One, ItemCount_Other) का उपयोग करें। सभी CLDR बहुवचन श्रेणियों के लिए पूर्ण ICU MessageFormat समर्थन पाने हेतु 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 {# عنصر}}";
एकवचन रूप पहचानने के लिए कभी भी count == 1 का उपयोग न करें। फ़्रेंच में 0 को एकवचन माना जाता है। रूसी में 'few' और 'many' के लिए अलग-अलग रूप हैं। अरबी में छह बहुवचन श्रेणियाँ हैं। CLDR-संगत बहुवचन नियमों या इसे सही ढंग से संभालने वाली MessageFormat.NET जैसी लाइब्रेरी का उपयोग करें।
7

Razor व्यू को स्थानीयकृत करें

Razor व्यू में @inject के माध्यम से IViewLocalizer का उपयोग करें। यह व्यू के फ़ाइल पाथ के आधार पर RESX फ़ाइलें चुनता है। मार्कअप वाली HTML-सुरक्षित स्ट्रिंग के लिए IHtmlLocalizer का उपयोग करें। asp-for और asp-validation-for जैसे Tag Helpers स्थानीयकृत Display और 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 व्यू पाथ के आधार पर RESX फ़ाइलें चुनता है: Views/Home/Index.cshtml के लिए यह Resources/Views/Home/Index.de.resx खोजता है। यदि आप कई व्यू में स्ट्रिंग साझा करना चाहते हैं, तो IStringLocalizer&lt;SharedResource&gt; को अलग से इंजेक्ट करें।
8

RESX अनुवादों को ऑटोमेट करें

लोकलाइज़ेशन सेटअप पूरा होने के बाद AI का उपयोग करके अपनी RESX फ़ाइलों का अनुवाद करें। अपने IDE में AI सहायक से सोर्स RESX का अनुवाद करवाएँ या अनुवादों को सिंक में रखने के लिए अपनी CI/CD पाइपलाइन में i18n Agent CLI का उपयोग करें।

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
चरणबद्ध तरीके से अनुवाद करें—जब आप अपनी सोर्स RESX फ़ाइल में नई कुंजियाँ जोड़ें, तो सभी फ़ाइलें फिर से जनरेट करने के बजाय केवल अंतर का अनुवाद करें। इससे मनुष्यों द्वारा समीक्षित अनुवाद सुरक्षित रहते हैं और अनावश्यक बदलाव कम होते हैं।

अनुवाद की गुणवत्ता को ऑटोमेट करें

i18n-validate की मदद से रिलीज़ से पहले छूटी हुई कुंजियाँ और खराब प्लेसहोल्डर पकड़ें। वास्तविक अनुवाद आने से पहले i18n-pseudo से छद्म-अनुवादों का उपयोग करके अपने UI की जाँच करें।

LocaleChain.NET से लोकेल फ़ॉलबैक ठीक करें

.NET की अंतर्निहित CultureInfo.Parent हायरार्की केवल BCP 47 ट्रंकेशन का उपयोग करती है: pt-BR पहले pt और फिर InvariantCulture पर फ़ॉलबैक होता है तथा pt-PT को छोड़ देता है। LocaleChain.NET पूरे .NET इकोसिस्टम के लिए प्रति-लोकेल कॉन्फ़िगर की जा सकने वाली फ़ॉलबैक शृंखलाएँ उपलब्ध कराता है।

LocaleChain.NET के बिना, पुर्तगाली स्ट्रिंग न मिलने पर pt-BR यूज़र को अंग्रेज़ी दिखाई देती है—भले ही आपके पास pt-PT का पूरा अनुवाद मौजूद हो। यही समस्या es-MX (es-419 को छोड़ता है), zh-Hant (zh-Hans को छोड़ता है) और दर्जनों अन्य क्षेत्रीय वेरिएंट को भी प्रभावित करती है।
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<>));

आम समस्याएँ

रिक्वेस्ट पर कल्चर सेट नहीं है

अनुवाद हमेशा डिफ़ॉल्ट भाषा में दिखाई देते हैं। जाँचें कि मिडलवेयर पाइपलाइन में UseRequestLocalization() कॉल किया गया है और कल्चर प्रोवाइडर कॉन्फ़िगर किए गए हैं। पुष्टि करें कि ब्राउज़र Accept-Language हेडर भेजता है। मिडलवेयर के काम करने की पुष्टि करने के लिए क्वेरी स्ट्रिंग में ?culture=de के साथ जाँच करें।

RESX फ़ाइल नहीं मिली

IStringLocalizer अनूदित मान के बजाय कुंजी का नाम लौटाता है। इसका सबसे आम कारण ऐसी RESX फ़ाइल का नाम है, जो ResourcesPath के सापेक्ष क्लास के पूरे नेमस्पेस पाथ से मेल नहीं खाता। फ़्रेमवर्क किन पाथ पर खोज करता है, यह देखने के लिए Microsoft.Extensions.Localization की डीबग लॉगिंग चालू करें।

मिडलवेयर का क्रम गलत है

UseRequestLocalization() को UseEndpoints() और MapControllers() से पहले होना चाहिए। इसे बाद में रखने पर कंट्रोलर के चलने के समय रिक्वेस्ट कल्चर सेट नहीं होता। .NET 6+ की मिनिमल होस्टिंग में इसे app.MapControllers() से पहले कॉल करें।

बैकग्राउंड थ्रेड गलत कल्चर का उपयोग करता है

CultureInfo.CurrentCulture और CurrentUICulture प्रत्येक थ्रेड के लिए अलग होते हैं। बैकग्राउंड टास्क (Task.Run, होस्टेड सेवाएँ) रिक्वेस्ट कल्चर के बजाय थ्रेड पूल का कल्चर इनहेरिट करते हैं। बैकग्राउंड कार्य भेजते समय कल्चर को स्पष्ट रूप से कैप्चर और सेट करें।

अनुशंसित प्रोजेक्ट संरचना

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

i18n Agent अभी आज़माएँ

अपनी अनुवाद फ़ाइल यहाँ छोड़ें

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

या ब्राउज़ करने के लिए क्लिक करें

लक्षित भाषाएँ

साइन अप की ज़रूरत नहींतुरंत अनुमान

I18nAgent.LocaleChain के साथ लोकेल फ़ॉलबैक

जब pt-BR जैसे क्षेत्रीय लोकेल में कोई अनुवाद कुंजी नहीं मिलती, तो .NET पहले पैरेंट लोकेल 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"},
});

समर्थित फ़्रेमवर्क और 75 अंतर्निहित शृंखलाओं की पूरी सूची के लिए हमारी लोकेल फ़ॉलबैक गाइड देखें। Learn more →

अक्सर पूछे जाने वाले प्रश्न