{"id":75826,"date":"2022-10-18T08:00:49","date_gmt":"2022-10-18T06:00:49","guid":{"rendered":"https:\/\/drafts.code-maze.com\/?p=75501"},"modified":"2024-01-31T15:38:10","modified_gmt":"2024-01-31T14:38:10","slug":"aspnetcore-localization","status":"publish","type":"post","link":"https:\/\/code-maze.com\/aspnetcore-localization\/","title":{"rendered":"Localization in ASP.NET Core"},"content":{"rendered":"<p>Making websites multi-lingual allows users from around the globe to use our applications in their native language. In this article, we are going to see how ASP.NET Core provides us with the ability to enable localization to support different languages and cultures.\u00a0<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To download the source code for this article, you can visit our <a href=\"https:\/\/github.com\/CodeMazeBlog\/CodeMazeGuides\/tree\/main\/aspnetcore-features\/Localization\" target=\"_blank\" rel=\"nofollow noopener\">GitHub repository<\/a>.<\/div>\n<p>Let&#8217;s get started.<\/p>\n<h2>The Difference Between Globalization and Localization<\/h2>\n<p>Globalization and Localization are two very closely related terms, so let&#8217;s define and understand them.\u00a0<\/p>\n<p><strong>Globalization is the process of designing applications to support different languages and cultures.<\/strong><\/p>\n<p><strong>Localization, on the other hand, is the process of adjusting an application for a specific language\/culture.<\/strong><\/p>\n<p>With these definitions in mind, let&#8217;s look at how we can <strong>design our applications for<\/strong>\u00a0<strong>globalization<\/strong> by <strong>introducing<\/strong>\u00a0<strong>localization<\/strong> for specific cultures.<\/p>\n<h2>Add Localization to an Application<\/h2>\n<p>We&#8217;ll start by creating an MVC application. This will allow us to look at the various ways we can localize our applications and serve content based on the user&#8217;s locale. Let&#8217;s open a command terminal and run <code>dotnet new webapp -n Localization<\/code>, or we can also use Visual Studio to create a new project.<\/p>\n<h2>Resource Files<\/h2>\n<p>Resource files are a specific file format (<code>.resx<\/code>) that allows us to define translations for any plaintext content we want to display in our application, in a key-value pair format. They allow us to separate the localized content from our code, meaning we can easily swap out different resource files for different languages without having to change our code.<\/p>\n<h3>File Naming Convention<\/h3>\n<p>By convention, resource files should be separated into a separate folder called\u00a0<code>Resources<\/code>. When naming these files, they should follow the name of the class that will consume them, as well as include the language they represent.<\/p>\n<p>We can either organize the files into separate folders, such as <code>Resources\/Controllers\/LocalizationController.es.resx<\/code>, or leave them in the root Resources folder, ensuring to name them appropriately, in this case <code>Resources\/Controllers.LocalizationController.es.resx<\/code>.<\/p>\n<h3>Create Resource Files<\/h3>\n<p>For our application, we will follow the folder hierarchy for organizing our resource files. With that in mind, let&#8217;s create 2 resource files for the <code>LocalizationController<\/code> that we will create shortly. One will be in English and another in Spanish.<\/p>\n<p>To start, let&#8217;s create a <code>Resources<\/code> folder, and in that, we&#8217;ll add another folder called <code>Controllers<\/code>.<\/p>\n<p>Now, we add a file called <code>LocalizationController.en.resx<\/code>, and one called <code>LocalizationController.es.resx<\/code>.<\/p>\n<p>Let&#8217;s open the <code>LocalizationController.en.resx<\/code> file first and add a new entry:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.en_.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75830\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.en_.png\" alt=\"localization controller english\" width=\"418\" height=\"48\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.en_.png 418w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.en_-300x34.png 300w\" sizes=\"auto, (max-width: 418px) 100vw, 418px\" \/><\/a><\/p>\n<p>We&#8217;ll do the same for the Spanish resource file, making sure to use the same name:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.es_-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75831\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.es_-1.png\" alt=\"localization controller spanish\" width=\"453\" height=\"51\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.es_-1.png 453w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.es_-1-300x34.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/LocalizationController.es_-1-440x51.png 440w\" sizes=\"auto, (max-width: 453px) 100vw, 453px\" \/><\/a><\/p>\n<h2>Configure Supported Cultures<\/h2>\n<p>Before we can test out the localization of the application, we need to configure our application to register the required services. In the <code>Program<\/code> class, let&#8217;s add localization to our application:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">builder.Services.AddLocalization(options =&gt; options.ResourcesPath = \"Resources\");<\/code><\/p>\n<p>We need to set the <code>ResourcesPath<\/code> property to our Resources folder, so ASP.NET Core knows where to look for our resource files.<\/p>\n<p>Also, we can configure the supported cultures for our application:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">const string defaultCulture = \"en-GB\";\r\n\r\nvar supportedCultures = new[]\r\n{\r\n    new CultureInfo(defaultCulture),\r\n    new CultureInfo(\"es\")\r\n};\r\n\r\nbuilder.Services.Configure&lt;RequestLocalizationOptions&gt;(options =&gt; {\r\n    options.DefaultRequestCulture = new RequestCulture(defaultCulture);\r\n    options.SupportedCultures = supportedCultures;\r\n    options.SupportedUICultures = supportedCultures;\r\n});<\/pre>\n<p>Here, we define our default culture (<code>en-GB<\/code>) as well as another supported culture (<code>es<\/code>).<\/p>\n<p>Finally, we need to tell our application to use these supported cultures:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">app.UseRequestLocalization(app.Services.GetRequiredService&lt;IOptions&lt;RequestLocalizationOptions&gt;&gt;().Value);<\/code><\/p>\n<p>With our resource files defined and our application configured for localization, let&#8217;s look at how we can use them in our application.<\/p>\n<h2>IStringLocalizer Interface for Localization<\/h2>\n<p>ASP.NET Core provides us with an easy-to-use interface for making our applications localized, <code>IStringLocalizer&lt;T&gt;<\/code>. This interface uses two classes, <code>ResourceReader<\/code> and <code>ResourceManager<\/code> which provides access to culture-specific resources at run-time. We can use <a href=\"https:\/\/code-maze.com\/dependency-injection-aspnet\/\" target=\"_blank\" rel=\"noopener\">dependency injection<\/a> to gain access to this interface to make the localization of our applications much more straightforward.<\/p>\n<p>Let&#8217;s look at how to use this interface in our application.<\/p>\n<h2>Controller Localization<\/h2>\n<p>Now that we have our resource files created, let&#8217;s create the accompanying controller:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class LocalizationController : Controller\r\n{\r\n    private readonly IStringLocalizer&lt;LocalizationController&gt; _localizer;\r\n\r\n    public LocalizationController(IStringLocalizer&lt;LocalizationController&gt; localizer)\r\n    {\r\n        _localizer = localizer;\r\n    }\r\n\r\n    public IActionResult Index()\r\n    {\r\n        ViewData[\"Greeting\"] = _localizer[\"Greeting\"];\r\n        return View();\r\n    }\r\n}<\/pre>\n<p>We start by injecting the <code>IStringLocalizer&lt;LocalizationController&gt;<\/code> interface, which will give us access to our English and Spanish resource files.<\/p>\n<p>In the <code>Index()<\/code> method, we set the <code>ViewData<\/code> dictionary value for <code>Greeting<\/code> from our resource file, which will be determined based on the culture of the user.\u00a0<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">If you would like to learn more about ViewData, check out our article on <a href=\"https:\/\/code-maze.com\/state-management-in-asp-net-core-mvc\/\" target=\"_blank\" rel=\"noopener\">State Management in ASP.NET Core MVC<\/a>.<\/div>\n<p>Finally, we return to our view, which we&#8217;ll create next.<\/p>\n<p>In the Views folder, let&#8217;s create a new folder called <code>Localization<\/code> for our new controller, and create our Index view:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">@{\r\n    ViewData[\"Title\"] = \"IStringLocalizer\";\r\n}\r\n\r\n&lt;div class=\"text-center\"&gt;\r\n    &lt;p&gt;@ViewData[\"Greeting\"]&lt;\/p&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>Here, we simply access the\u00a0<code>Greeting<\/code> key of the <code>ViewData<\/code> dictionary.<\/p>\n<p>If we run our application and navigate to <code>\/Localization<\/code>, given that our culture is set to English, we will see the English variation of our <code>Greeting<\/code> message.<\/p>\n<p>Let&#8217;s look at a couple of different methods for changing the culture so we can test whether our localization is working correctly.<\/p>\n<h3>Request Culture with Query String<\/h3>\n<p>We can manually specify the culture we wish to use by using the <code>culture<\/code> query string parameter. By default in ASP.NET Core, the <code>QueryStringRequestCultureProvider<\/code> is registered, allowing us to use this query string parameter in our application.<\/p>\n<p>Let&#8217;s try it out. If we navigate to the Localization controller and pass the <code>culture<\/code> query parameter with the value set to <code>es<\/code>, we will see the Spanish variation of our greeting:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-query-param-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75832\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-query-param-2.png\" alt=\"culture query parameter\" width=\"548\" height=\"167\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-query-param-2.png 548w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-query-param-2-300x91.png 300w\" sizes=\"auto, (max-width: 548px) 100vw, 548px\" \/><\/a><\/p>\n<h3>Accept-Language Request Header\u00a0<\/h3>\n<p>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Accept-Language\" target=\"_blank\" rel=\"nofollow noopener\">Accept-Language<\/a> header is another method for specifying the locale the user wishes to use. This is set at a browser level and allows users to set multiple languages, which are weighted based on a quality value from 0-1, letting the browser know which language the user would prefer to use.<\/p>\n<h2>IHtmlLocalizer Interface for HTML Localization<\/h2>\n<p>What happens if we had some HTML markup in our resource files? Well, if we continued to use the <code>IStringLocalizer<\/code> interface, we would see the HTML markup unrendered:<\/p>\n<p><a href=\"http:\/\/drafts.code-maze.com\/wp-content\/uploads\/2022\/10\/raw-html-unrendered.png\" class=\"broken_link\" rel=\"nofollow\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-76038\" src=\"http:\/\/drafts.code-maze.com\/wp-content\/uploads\/2022\/10\/raw-html-unrendered.png\" alt=\"raw-html-unrendered\" width=\"439\" height=\"24\" \/><\/a><\/p>\n<p>This is not desirable. Fortunately, ASP.NET provides us with a way to render HTML in our resource files correctly, using the <code>IHtmlLocalizer<\/code> interface.<\/p>\n<p>Let&#8217;s change our resource\u00a0files to display our greeting as an <code>h1<\/code>:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/h1-greeting.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75833\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/h1-greeting.png\" alt=\"html localization\" width=\"494\" height=\"49\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/h1-greeting.png 494w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/h1-greeting-300x30.png 300w\" sizes=\"auto, (max-width: 494px) 100vw, 494px\" \/><\/a><\/p>\n<p>We need to apply this change to both the English and Spanish resource files.<\/p>\n<p>Now, in our <code>LocalizationController<\/code>, instead of injecting <code>IStringLocalizer<\/code>, we inject an <code>IHtmlLocalizer<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3,5\">public class LocalizationController : Controller\r\n{\r\n    private readonly IHtmlLocalizer&lt;LocalizationController&gt; _localizer;\r\n\r\n    public LocalizationController(IHtmlLocalizer&lt;LocalizationController&gt; localizer)\r\n    {\r\n        _localizer = localizer;\r\n    }\r\n\r\n    public IActionResult Index()\r\n    {\r\n        ViewData[\"Greeting\"] = _localizer[\"Greeting\"];\r\n        return View();\r\n    }\r\n}<\/pre>\n<p>To use the <code>IHtmlLocalizer<\/code> interface, we need to register it in our <code>Program<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3\">builder.Services \r\n    .AddControllersWithViews()\r\n    .AddViewLocalization();<\/pre>\n<p>This time when we navigate to <code>\/Localization<\/code> we will see our greeting rendered as an <code>h1<\/code>.<\/p>\n<h2>View Localization With IViewLocalizer<\/h2>\n<p>Instead of localizing at the controller level, we may wish to do so at the View level, which we can do with the <code>IViewLocalizer<\/code> interface. We can choose to localize strings within the view, similar to how we&#8217;ve previously done, or localize the entire view, creating multiple variations for different languages.<\/p>\n<p>Let&#8217;s create a new view to demonstrate using the <code>IViewLocalizer<\/code> interface:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">@using Microsoft.AspNetCore.Mvc.Localization\r\n\r\n@inject IViewLocalizer ViewLocalizer\r\n\r\n&lt;div class=\"text-center\"&gt;\r\n    &lt;p&gt;@ViewLocalizer[\"ViewGreeting\"]&lt;\/p&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>Here, we inject the <code>IViewLocalizer<\/code> interface from the <code>Microsoft.AspNetCore.Mvc.Localization<\/code> namespace. Then we retrieve the <code>ViewGreeting<\/code> value using the <code>ViewLocalizer<\/code>, which will retrieve it from the required resource file.<\/p>\n<p>Next, we need to create new resource files, matching the name and location of this new view. Let&#8217;s create an English and Spanish resource file under the <code>Resources\/Views\/Localization<\/code> folder, called <code>LocalizedView.en.resx<\/code> and <code>LocalizedView.es.resx<\/code> respectively.<\/p>\n<p>In the English file, we&#8217;ll add the <code>ViewGreeting<\/code> entry with a value of &#8220;<em>Hello from a localized view!&#8221;<\/em>. In the Spanish file, we&#8217;ll add the same entry, using &#8220;<em>\u00a1Hola desde una vista localizada!&#8221;<\/em> for the value.<\/p>\n<p>Running our application and navigating to <code>\/Localization\/LocalizedView<\/code> we will see the English variation of our <code>ViewGreeting<\/code> message. To test the Spanish variation, we can once again append the <code>culture<\/code> query parameter with a value of <code>es<\/code>.<\/p>\n<h2>Localizing Error Messages With Data Annotations<\/h2>\n<p>When we make use of <a href=\"https:\/\/code-maze.com\/aspnetcore-modelstate-validation-web-api\/\" target=\"_blank\" rel=\"noopener\">ModelState validation<\/a> in our applications, we can provide error messages whenever a given input does not meet the property requirements. Fortunately, the ASP.NET Core Localization package accounts for this and allows us to configure localization for our error messages from the <code>Program<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"4\">builder.Services\r\n     .AddControllersWithViews()\r\n     .AddViewLocalization()\r\n     .AddDataAnnotationsLocalization();<\/pre>\n<p>Let&#8217;s create a model with some data annotations in the Models folder:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class PersonViewModel\r\n{\r\n    [Display(Name = \"FirstName\")]\r\n    [Required(ErrorMessage = \"{0} is a required field\")]\r\n    public string FirstName { get; set; }\r\n\r\n    [Display(Name = \"LastName\")]\r\n    [Required(ErrorMessage = \"{0} is a required field\")]\r\n    public string LastName { get; set; }\r\n\r\n    [Display(Name = \"Age\")]\r\n    [Range(1, 100, ErrorMessage = \"{0} must be a number between {1} and {2}\")]\r\n    public int Age { get; set; }\r\n}<\/pre>\n<p>Next, we&#8217;ll create the Spanish resource file for translating the error messages. In a new folder, <code>Resources\/Models<\/code>, let&#8217;s create <code>PersonViewModel.es.resx<\/code>:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/personvm-spanish-resource-file.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75834\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/personvm-spanish-resource-file.png\" alt=\"translating error messages\" width=\"457\" height=\"138\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/personvm-spanish-resource-file.png 457w, https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/personvm-spanish-resource-file-300x91.png 300w\" sizes=\"auto, (max-width: 457px) 100vw, 457px\" \/><\/a><\/p>\n<p>As English is the default language we used when creating the error messages, we don&#8217;t need to create an English-specific resource file.<\/p>\n<p>Now we must create the View that will display the <code>PersonViewModel<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">@model PersonViewModel\r\n@{\r\n    ViewData[\"Title\"] = \"Data Annotations\";\r\n}\r\n\r\n&lt;div class=\"card\"&gt;  \r\n    &lt;div class=\"card-body\"&gt;  \r\n        &lt;form asp-action=\"DataAnnotationView\" asp-route-culture=@ViewData[\"culture\"]&gt;  \r\n            &lt;div class=\"row\"&gt;  \r\n                &lt;div class=\"col-md-6\"&gt;  \r\n                    &lt;div class=\"form-group\"&gt;  \r\n                        &lt;label asp-for=\"FirstName\" class=\"lable-control\"&gt;&lt;\/label&gt;  \r\n                        &lt;input asp-for=\"FirstName\" class=\"form-control\" \/&gt;  \r\n                        &lt;span asp-validation-for=\"FirstName\" class=\"text-danger\"&gt;&lt;\/span&gt;  \r\n                    &lt;\/div&gt;  \r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n            &lt;div class=\"row\"&gt;\r\n                &lt;div class=\"col-md-6\"&gt;\r\n                    &lt;div class=\"form-group\"&gt;  \r\n                        &lt;label asp-for=\"LastName\" class=\"lable-control\"&gt;&lt;\/label&gt;  \r\n                        &lt;input asp-for=\"LastName\" class=\"form-control\" \/&gt;  \r\n                        &lt;span asp-validation-for=\"LastName\" class=\"text-danger\"&gt;&lt;\/span&gt;  \r\n                    &lt;\/div&gt; \r\n                &lt;\/div&gt;  \r\n            &lt;\/div&gt;\r\n            &lt;div class=\"row\"&gt;\r\n                &lt;div class=\"col-md-6\"&gt;\r\n                    &lt;div class=\"form-group\"&gt;  \r\n                        &lt;label asp-for=\"Age\" class=\"lable-control\"&gt;&lt;\/label&gt;  \r\n                        &lt;input asp-for=\"Age\" class=\"form-control\" \/&gt;  \r\n                        &lt;span asp-validation-for=\"Age\" class=\"text-danger\"&gt;&lt;\/span&gt;  \r\n                    &lt;\/div&gt; \r\n                &lt;\/div&gt;  \r\n            &lt;\/div&gt;\r\n            &lt;div class=\"form-group\"&gt;  \r\n                &lt;button type=\"submit\" class=\"btn btn-primary rounded-0 mt-2\"&gt;Submit&lt;\/button&gt;  \r\n            &lt;\/div&gt;  \r\n        &lt;\/form&gt;  \r\n    &lt;\/div&gt;  \r\n&lt;\/div&gt;<\/pre>\n<p>Here, we create a simple form that is bound to our <code>PersonViewModel<\/code>, which will submit to an endpoint we will create next. We include a <code>span<\/code> for each field with the <code>asp-validation-for<\/code> attribute, which will display the error message we configured previously if the model is not valid.<\/p>\n<p>As we are using the <code>culture<\/code> query parameter to determine the locale to use, we need to persist it in <code>ViewData<\/code> so that we return the same locale after posting the form to the server. We pass this back to the server by defining the <code>asp-route-culture<\/code> parameter on the <code>form<\/code> element.<\/p>\n<p>Finally, we need to create the new endpoints that will return this new view:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public IActionResult DataAnnotationView([FromQuery] string? culture)\r\n{\r\n    ViewData[\"culture\"] = culture;\r\n    return View();\r\n}\r\n\r\n[HttpPost]\r\n[ValidateAntiForgeryToken]\r\npublic IActionResult DataAnnotationView(PersonViewModel personViewModel, [FromQuery] string? culture)\r\n{\r\n    ViewData[\"culture\"] = culture;\r\n    if (!ModelState.IsValid)\r\n    {\r\n        return View();\r\n    }\r\n\r\n    return View();\r\n}<\/pre>\n<p>The first endpoint is a simple <code>GET<\/code> endpoint. Here we add the culture value to <code>ViewData<\/code>, so it can be sent in the form submission if present.<\/p>\n<p>Our second endpoint is a <code>POST<\/code> endpoint that will be used for form submission. Once again we pass the <code>culture<\/code> parameter to <code>ViewData<\/code>, and also check if the <code>ModelState<\/code> is valid. In this instance, we simply return the view, which will display the error messages.<\/p>\n<h3>Test Data Annotation Localization<\/h3>\n<p>Now we are ready to test this out. If we navigate to <code>\/Localization\/DataAnnotationView<\/code>, enter some invalid fields and submit our form, we will see the default, English error messages:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/invalid-form-english-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75835\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/invalid-form-english-1.png\" alt=\"invalid form english\" width=\"243\" height=\"270\" \/><\/a><\/p>\n<p>To test out the Spanish version, let&#8217;s add the <code>culture<\/code> query parameter to our URL with the value of <code>es<\/code>:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/empty-form-spanish-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75836\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/empty-form-spanish-1.png\" alt=\"empty form spanish\" width=\"234\" height=\"175\" \/><\/a><\/p>\n<p>Entering some invalid values once again and submitting, we will see the Spanish variations of our error messages:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/invalid-form-spanish-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75837\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/invalid-form-spanish-1.png\" alt=\"invalid form localized\" width=\"241\" height=\"257\" \/><\/a><\/p>\n<p>So far we have manually added the culture query parameter to determine the locale of the user. Let&#8217;s look at an alternative method using cookies.<\/p>\n<h2>Cookie-Based Localization Preferences<\/h2>\n<p>We can store a user&#8217;s locale in a <a href=\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\" target=\"_blank\" rel=\"noopener\">Cookie<\/a> which means we don&#8217;t have to pass it through the query parameter manually and allows us to set the culture programmatically. This would be the preferred method, as we can store the user&#8217;s locale between sessions, meaning they will return to the same locale each time.<\/p>\n<p>Let&#8217;s start by creating a dropdown that we will add to our navigation bar to allow the user to select a language:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">@using Microsoft.AspNetCore.Localization\r\n@using Microsoft.Extensions.Options\r\n\r\n@inject IOptions&lt;RequestLocalizationOptions&gt; LocalizationOptions\r\n\r\n@{\r\n    var requestCulture = Context.Features.Get&lt;IRequestCultureFeature&gt;();\r\n\r\n    var cultureItems = LocalizationOptions.Value.SupportedUICultures\r\n        .Select(c =&gt; new SelectListItem { Value = c.Name, Text = c.Name })\r\n        .ToList();\r\n\r\n    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) \r\n        ? \"~\/\" \r\n        : $\"~{Context.Request.Path.Value}{Context.Request.QueryString}\";\r\n}\r\n\r\n&lt;div&gt;\r\n    &lt;form asp-controller=\"Culture\" asp-action=\"SetCulture\" asp-route-returnUrl=\"@returnUrl\" \r\n          class=\"form-horizontal nav-link text-dark\"&gt;\r\n          &lt;select name=\"culture\" \r\n                onchange=\"this.form.submit();\" \r\n                asp-for=\"@requestCulture.RequestCulture.UICulture.Name\" \r\n                asp-items=\"cultureItems\"&gt;\r\n          &lt;\/select&gt;\r\n    &lt;\/form&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>First, we inject <code>IOptions&lt;RequestLocalizationOptions&gt;<\/code> which allows us to access the configured cultures for our application.<\/p>\n<p>Then, in the code block, we get these supported cultures to bind them to our dropdown. Also, we define a <code>returnUrl<\/code> route, so that whenever we change the language, we return to the same page the user was currently on, and not the default page.<\/p>\n<p>Finally, we add a form with our support languages dropdown that will submit to the <code>SetCulture<\/code> method of the\u00a0<code>Culture<\/code> controller, which we will define shortly.<\/p>\n<p>We must remember to add this partial view to <code>_Layout.cshtml<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;div class=\"navbar-collapse collapse d-sm-inline-flex justify-content-between\"&gt;\r\n    &lt;ul class=\"navbar-nav flex-grow-1\"&gt;\r\n        &lt;li class=\"nav-item\"&gt;\r\n            @await Html.PartialAsync(\"_CulturePartial\")\r\n        &lt;\/li&gt;\r\n    &lt;\/ul&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>Now it&#8217;s time to add the controller that will set the culture in the cookie. We&#8217;ll start by creating a new <code>CultureController<\/code>, along with the single method required:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class CultureController : Controller\r\n{\r\n    [HttpPost]\r\n    public IActionResult SetCulture(string culture, string returnUrl)\r\n    {\r\n        Response.Cookies.Append(\r\n            CookieRequestCultureProvider.DefaultCookieName,\r\n            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),\r\n            new CookieOptions { Expires = DateTimeOffset.UtcNow.AddDays(30) }\r\n        );\r\n\r\n        return LocalRedirect(returnUrl);\r\n    }\r\n}<\/pre>\n<p>We have a single <code>POST<\/code> method, <code>SetCulture()<\/code> which is used from our dropdown when the value changes. In this method, we add a cookie to the <code>Response<\/code> with the selected culture, setting the expiry time to 30 days in the future. Then, we redirect the user to the <code>returnUrl<\/code>, which will be the URL they were currently on.<\/p>\n<h3>Test Cookie-Based Localization<\/h3>\n<p>Our cookie-based localization is now ready to test. If we run our application, we will see the dropdown on the navigation bar:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-dropdown-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75838\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2022\/10\/culture-dropdown-1.png\" alt=\"culture select dropdown\" width=\"208\" height=\"86\" \/><\/a><\/p>\n<p>If we select <code>es<\/code> from the dropdown and navigating through the application again, we see all the language is returned in Spanish. We no longer have to manually set the culture by using a query parameter. The application remembers our preference when we navigate away from our application and return.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we&#8217;ve learned what Localization is in an ASP.NET application. We understood how to make our application multi-lingual by using resource files and various interfaces ASP.NET Core provides us. Localization is a powerful tool that enables us to reach a wider audience with our applications, providing each culture with a personalized experience suited to them. We&#8217;ve covered a lot of MVC features in this article.<\/p>\n<p>If you&#8217;d like to learn more about MVC, check out our <a href=\"https:\/\/code-maze.com\/asp-net-core-mvc-series\/\" target=\"_blank\" rel=\"noopener\">ASP.NET Core MVC Series<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Making websites multi-lingual allows users from around the globe to use our applications in their native language. In this article, we are going to see how ASP.NET Core provides us with the ability to enable localization to support different languages and cultures.\u00a0 Let&#8217;s get started. The Difference Between Globalization and Localization Globalization and Localization are [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":62187,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[12],"tags":[10,443,1460,811,810],"class_list":["post-75826","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-csharp","tag-net","tag-asp-net-core-mvc","tag-feature","tag-globalization","tag-localization","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Localization in ASP.NET Core - Code Maze<\/title>\n<meta name=\"description\" content=\"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/aspnetcore-localization\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Localization in ASP.NET Core - Code Maze\" \/>\n<meta property=\"og:description\" content=\"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/aspnetcore-localization\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2022-10-18T06:00:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-31T14:38:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Code Maze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Code Maze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/\"},\"author\":{\"name\":\"Code Maze\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\"},\"headline\":\"Localization in ASP.NET Core\",\"datePublished\":\"2022-10-18T06:00:49+00:00\",\"dateModified\":\"2024-01-31T14:38:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/\"},\"wordCount\":2008,\"commentCount\":11,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"keywords\":[\".NET\",\"ASP.NET Core MVC\",\"Feature\",\"Globalization\",\"Localization\"],\"articleSection\":[\"C#\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/aspnetcore-localization\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/\",\"url\":\"https:\/\/code-maze.com\/aspnetcore-localization\/\",\"name\":\"Localization in ASP.NET Core - Code Maze\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"datePublished\":\"2022-10-18T06:00:49+00:00\",\"dateModified\":\"2024-01-31T14:38:10+00:00\",\"description\":\"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/aspnetcore-localization\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"width\":1100,\"height\":620,\"caption\":\"ASP.NET Core\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/aspnetcore-localization\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Localization in ASP.NET Core\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\",\"name\":\"Code Maze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"caption\":\"Code Maze\"},\"description\":\"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/codemaze\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/codemazecontributor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Localization in ASP.NET Core - Code Maze","description":"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/aspnetcore-localization\/","og_locale":"en_US","og_type":"article","og_title":"Localization in ASP.NET Core - Code Maze","og_description":"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.","og_url":"https:\/\/code-maze.com\/aspnetcore-localization\/","og_site_name":"Code Maze","article_published_time":"2022-10-18T06:00:49+00:00","article_modified_time":"2024-01-31T14:38:10+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","type":"image\/png"}],"author":"Code Maze","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Code Maze","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/"},"author":{"name":"Code Maze","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04"},"headline":"Localization in ASP.NET Core","datePublished":"2022-10-18T06:00:49+00:00","dateModified":"2024-01-31T14:38:10+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/"},"wordCount":2008,"commentCount":11,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","keywords":[".NET","ASP.NET Core MVC","Feature","Globalization","Localization"],"articleSection":["C#"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/aspnetcore-localization\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/aspnetcore-localization\/","url":"https:\/\/code-maze.com\/aspnetcore-localization\/","name":"Localization in ASP.NET Core - Code Maze","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","datePublished":"2022-10-18T06:00:49+00:00","dateModified":"2024-01-31T14:38:10+00:00","description":"Localization enables us to target specific user audiences. In this article, we will look at how to localize ASP.NET Core applications.","breadcrumb":{"@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/aspnetcore-localization\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","width":1100,"height":620,"caption":"ASP.NET Core"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/aspnetcore-localization\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Localization in ASP.NET Core"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04","name":"Code Maze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","caption":"Code Maze"},"description":"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.","sameAs":["https:\/\/www.linkedin.com\/company\/codemaze\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/codemazecontributor\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/75826","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=75826"}],"version-history":[{"count":5,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/75826\/revisions"}],"predecessor-version":[{"id":75876,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/75826\/revisions\/75876"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/62187"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=75826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=75826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=75826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}