Nowadays all web application are built for multiple geography, where we expect visitors from different culture, to make the application more local to them we need to create different type to content for different region, and that’s where globalization and localization in Asp.net Core framework is helpful.
In this tutorial you will learn how to implement Globalization and Localization in Asp.Net Core application.
Asp.net Core Globalization is the process of making a globalised web application, which means there will be different content for different geography, means localised content.
Localization is the process of setting up content for local geography, continuation process of globalization.
Asp.net core provides mechanism of adding local culture info into middleware
using Microsoft.AspNetCore.Localization; using System.Globalization; IList<CultureInfo> supportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fi-FI"), }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-US"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures });
To setup localization in controller you need to add following code.
Things to notice
Here is how localization can be implemented in controller level, also have a provision to change the current culture by user from UI through query string
using Microsoft.Extensions.Localization; using Microsoft.AspNetCore.Mvc; using System.Globalization; public class welcomeController : Controller { private readonly IStringLocalizer<welcomeController> _localizer; public welcomeController(IStringLocalizer<welcomeController> localizer) { _localizer = localizer; } public IActionResult index() { return View(); } public IActionResult hello() { string currentCulture = Request.Query["culture"]; if (!string.IsNullOrEmpty(currentCulture)) { CultureInfo.CurrentCulture = new CultureInfo(currentCulture); } ViewData["WelcomeMessage"] = _localizer["WelcomeMessage"]; return View(); } }
Here is the complete localization implementation with working code (you can straight away use the code in your project)
Right click on your project then "Manage NuGet Packages", and then add following two packages in your solution
Microsoft.AspNetCore.Localization Microsoft.AspNetCore.Localization.Routing
Install NuGet package "Askmethat.Aspnet.JsonLocalizer"
Open your Startup.cs
file and add following code in "ConfigureServices" method.
public void ConfigureServices(IServiceCollection services) { #region Localization services.AddSingleton<IdentityLocalizationService>(); services.AddLocalization(o => { // We will put our translations in a folder called Resources o.ResourcesPath = "Resources"; }); services.AddSingleton<IStringLocalizerFactory, JsonStringLocalizerFactory>(); services.AddSingleton<IStringLocalizer, JsonStringLocalizer>(); services.AddMvc() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; }) .AddDataAnnotationsLocalization(options => { }); CultureInfo.CurrentCulture = new CultureInfo("en-US"); #endregion }
Notice how default culture has been set using CultureInfo.CurrentCulture
Now add the following code in "Configure" method of same startup.cs file
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { #region Localization IList<CultureInfo> supportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("en-IN"), new CultureInfo("fr-FR"), }; var localizationOptions = new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }; app.UseRequestLocalization(localizationOptions); var requestProvider = new RouteDataRequestCultureProvider(); localizationOptions.RequestCultureProviders.Insert(0, requestProvider); var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>(); app.UseRequestLocalization(locOptions.Value); #endregion }
You need to write following custom classes for localization in Json format. Let's create a class with name "JsonLocalization"
using Microsoft.Extensions.Localization; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; namespace WebTrainingRoom { class JsonLocalization { public string Key { get; set; } public Dictionary<string, string> LocalizedValue = new Dictionary<string, string>(); } public class JsonStringLocalizerFactory : IStringLocalizerFactory { public IStringLocalizer Create(Type resourceSource) { return new JsonStringLocalizer(); } public IStringLocalizer Create(string baseName, string location) { return new JsonStringLocalizer(); } } public class JsonStringLocalizer : IStringLocalizer { List<JsonLocalization> localization = new List<JsonLocalization>(); public JsonStringLocalizer() { //read all json file JsonSerializer serializer = new JsonSerializer(); localization = JsonConvert.DeserializeObject<List<JsonLocalization>>(File.ReadAllText(@"Resources/localization.json")); } public LocalizedString this[string name] { get { var value = GetString(name); return new LocalizedString(name, value ?? name, resourceNotFound: value == null); } } public LocalizedString this[string name, params object[] arguments] { get { var format = GetString(name); var value = string.Format(format ?? name, arguments); return new LocalizedString(name, value, resourceNotFound: format == null); } } public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) { return localization.Where(l => l.LocalizedValue.Keys.Any(lv => lv == CultureInfo.CurrentCulture.Name)).Select(l => new LocalizedString(l.Key, l.LocalizedValue[CultureInfo.CurrentCulture.Name], true)); } public IStringLocalizer WithCulture(CultureInfo culture) { return new JsonStringLocalizer(); } private string GetString(string name) { var query = localization.Where(l => l.LocalizedValue.Keys.Any(lv => lv == CultureInfo.CurrentCulture.Name)); var value = query.FirstOrDefault(l => l.Key == name); return value.LocalizedValue[CultureInfo.CurrentCulture.Name]; } } }
Notice in above code, we have specified the json file location at File.ReadAllText(@"Resources/localization.json")
.
Means in root of the application there is a folder called “Resources” , then there is a file called "localization.json"
Now create a class with name “IdentityLocalizationService”. Now create a class with name “IdentityLocalizationService”, in this class we have methods that will allow us to access localized string based on key
using Microsoft.Extensions.Localization; using System.Reflection; namespace WebTrainingRoom.Resources { public class IdentityLocalizationService { private readonly IStringLocalizer _localizer; public IdentityLocalizationService(IStringLocalizerFactory factory) { var type = typeof(IdentityResource); var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName); _localizer = factory.Create("IdentityResource", assemblyName.Name); } public LocalizedString GetLocalizedHtmlString(string key) { return _localizer[key]; } public LocalizedString GetLocalizedHtmlString(string key, string parameter) { return _localizer[key, parameter]; } } public class IdentityResource { } }
If you want multiple-localization to be implemented, then you need to add multiple json file with same key values.
en-US.json { "WelcomeMessage": "Welcome to my World." } en-IN.json { "WelcomeMessage": "Namaskar! Apne Ghar Ayyea" }
You also can write all in one json file
[ { "Key": "WelcomeMessage", "LocalizedValue" : { "fr-FR": "Bienvenue dans mon monde.", "en-US": "Welcome to my Home.", "en-IN": "Swagatam! Apne Ghar Ayyea." } } ]
You may need to provide an option of changing current culture to your web page visitor, so in case they want to change the current culture, they can easily switch to their native culture
Changing current culture in asp.net core application is very easy
CultureInfo.CurrentCulture = new CultureInfo("en-IN"); string currentCulture = Request.Query["culture"]; if (!string.IsNullOrEmpty(currentCulture)) CultureInfo.CurrentCulture = new CultureInfo(currentCulture);
Here are few lines of code can get you the list of all culture info, so you can set the right culture for your required geography, remember you need to use the right culture name; otherwise it may get you error.
using System; using System.Globalization; using System.Collections.Generic; List<string> list = new List<string>(); foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures)) { list.Add(String.Format("{0} / {1}", ci.Name, ci.EnglishName)); } list.Sort(); // sort by name