In this article I am going to describe how you can implement Localization with dotnet MVC, but can be implemented with any dotnet project.
First, create a new dotnet MVC project.
Add a new folder in the solution for localization files name it Localization, inside this folder create a new class named DependencyInjection where we will declare the injected services, this step can be ignore and service injection can be added directly in the Program.cs file.
Inside DependencyInjection class first we need to create a function to add localization services named AddLocalizationServices and then add the resources folder path where the translation files are stored:
services.AddLocalization(options => options.ResourcesPath = "Resources");
Then we need to add the MVC and Views localization configuration with the options and available languages:
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { "en", "ar" };
options.DefaultRequestCulture = new RequestCulture(supportedCultures.First());
options.SetDefaultCulture(supportedCultures.First())
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
});
Also, we should add another function named AddLocalizationMiddleware in order to add the localization service in the middleware:
public static void AddLocalizationMiddleware(this WebApplication app)
{
app.UseRequestLocalization();
}
Full code for DependencyInjection.cs
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
namespace Localization.Localization
{
public static class DependencyInjection
{
public static void AddLocalizationServices(this IServiceCollection services)
{
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { "en", "ar" };
options.DefaultRequestCulture = new RequestCulture(supportedCultures.First());
options.SetDefaultCulture(supportedCultures.First())
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
});
}
public static void AddLocalizationMiddleware(this WebApplication app)
{
app.UseRequestLocalization();
}
}
}
Important Note: you should call these functions in the Program.cs in order to register the localization service.
Program.cs full code:
using Localization.Localization;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddLocalizationServices();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.AddLocalizationMiddleware();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Important Note: Create an empty class in the root folder name SharedResource.cs, which will be used later in configuration and resources files should hold same name to work.
Next step, create a new folder in the root app folder named Resources, then add 2 resource files named as following SharedResource.ar.resx and SharedResource.en.resx, these files will contain the translations for Arabic and English languages.
Now, we need to add a function in the Home Controller that will be used to set selected language:
[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);
}
After that, add a new partial view in the Shared Views folder named _SelectLanguagePartial.cshtml, this view will be the select dropdown that will contain the previously configured languages. Note that the form will submit on option select and call the action SetLanguage we created in Home Controller.
@using Microsoft.AspNetCore.Builder;
@using Microsoft.AspNetCore.Localization;
@using Microsoft.Extensions.Localization;
@using Microsoft.Extensions.Options;
@inject IStringLocalizer<SharedResource> Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = LocOptions?.Value?.SupportedCultures?
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList();
var url = Context.Request;
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString.Value}";
}
<div>
<form asp-controller="Home"
asp-action="SetLanguage"
asp-route-returnUrl="@returnUrl"
method="post">
<select name="culture"
asp-for="@requestCulture!.RequestCulture.UICulture.Name"
asp-items="cultureItems"
onchange="this.form.submit()">
</select>
</form>
</div>
In order to display the language dropdown list, you should add the partial view in your view, for me as an example I add it to the top bar in the main layout view. Go to Shared folder in Views and select _Layout.cshtml and insie the navbar call the partial view as below:
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Localization</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
<li class="nav-item">
@await Html.PartialAsync("_SelectLanguagePartial")
</li>
</ul>
</div>
</div>
</nav>
Finally, you should insert some translations text in the resources files.
Go to SharedResource.en.resx and fill as example with:
Name: welcome and Value: WELCOME
for arabic in SharedResource.ar.resx fill the data:
Name: welcome and Value: مرحبا
NOTE: if you are using visual studio code, download ResX Editor extension to edit resource files.
In order to use localization in all views it is important to import Localizer in _ViewImports.cshtml instead of importing it in each view:
@using Localization
@using Localization.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<SharedResource> Localizer
For testing, go to Index.cshtml under Views/Home and add the below using Localizer:
<div class="text-center">
<h1 class="display-4">@Localizer["welcome"]</h1>
<p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
That’s All !!!
https://github.com/MohammadElKhatib/dotnet_localization
Visit my youtube channel