Enterprise App Development Travel

Implementation of Localizing App for different cultures

localizing-App-min

What is Globalization and localization?

Globalization is the process of designing the application in such a way that it can be used by users from across the globe i.e. in multiple cultures. 

The CultureInfo class holds culture-specific information, such as the associated language, sub-language, country/region, calendar, and cultural conventions. The cultures have a hierarchy, such that the parent of a specific culture is a neutral culture and the parent of a neutral culture is the InvariantCulture.

Neutral culture is a culture that is associated with a language but not with a country or region. A specific culture is a culture that is associated with both a language and a country or region. We specify the invariant culture by name by using an empty string (” “) in the call to a CultureInfo instantiation method.

Localization is the process of customization of a product or service to meet the needs of a particular language, culture.

These two things go together.

Why is localization important?

Localization of product or service improves customer satisfaction, increases customer base, and helps to enter a new market.

The key point of making your application localizable is to separate the page content from your logic implementation.

When something needs to be displayed on a web page, never put them directly on the page file or in the backend logic. By giving the content a key, which can be linked to the real content for the proper language setting.

Localization in ASP.NET MVC:

ASP.NET MVC was built on top of the ASP.NET runtime so all features provided by ASP.NET can be used in MVC such as caching, session state, and localization. 

In traditional ASP.NET Webforms application resource files are used to store the content of the application with different cultures and using the ResourceManager class to retrieve them which can be generated by Visual Studio automatically.

To understand Localization let’s have an example:

Here is the example of having a web page supported by two languages:

  • English
  • Hindi

Steps to follow:

1. Go to Add

First put all content out of the pages and the controllers. ASP.NET provides a special folder named App_GlobalResources which contains the resource files for the content of all cultures. Just right-click the project in the solution explorer window and create the folder under the Add > Add ASP.NET Folders menu.

Implementation of Localizing App for different cultures

2. In App_GlobalResources add two resource files for 2 languages: English and Hindi

  • English language would be the default language of this application to create a Global.resx file firstly, then Global.hi-IN.resx. The middle name ‘hi-IN’ is the culture name of this language.
  • The Visual Studio will help us to generate the accessing class for them.

Important! Make sure to change the access modifier of each resource file you create to the public. The Properties section also checks that resource files Custom Tool property value is “PublicResXFileCodeGenerator” and the build is “Embedded Resource”. Otherwise resource files won’t be compiled and won’t be accessible.

3. Adding Model and Attribute to Properties:

Add a model with the name “UserDetails.cs” and then add a display attribute with the name similar to the resource “Name” column.

using System;
using System.Collections.Generic;  
using System.ComponentModel.DataAnnotations;  
using System.Linq;  
using System.Web;  
using MvcLocalization.LocalResource;  
  
namespace MvcLocalization.Models  
{  
    public class UserDetails  
    {  
  
        [Display(Name = "FirstName", ResourceType = typeof(Resource))]  
        [Required(ErrorMessageResourceType = typeof(Resource),  
                  ErrorMessageResourceName = "FirstNameRequired")]  
        [StringLength(50, ErrorMessageResourceType = typeof(Resource),  
                          ErrorMessageResourceName = "VldFirstNameLength")]  
        public string FirstName { get; set; }  
        [Display(Name = "LastName", ResourceType = typeof(Resource))]  
        [Required(ErrorMessageResourceType = typeof(Resource),  
                  ErrorMessageResourceName = "LastNameRequired")]  
        [StringLength(50, ErrorMessageResourceType = typeof(Resource),  
                          ErrorMessageResourceName = "VldLastNameLength")]  
        public string LastName { get; set; }  
        [Display(Name = "Salary", ResourceType = typeof(Resource))]
        [Required(ErrorMessageResourceType = typeof(Resource),
                  ErrorMessageResourceName = "SalaryFormat")]
        public double Salary { get; set; }
 
    }  
}

4. Adding custom class:

Add a Helper class to set the Cultures. 

using System;  
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using System.Threading;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
using MvcLocalization.LocalResource;

namespace MvcLocalization.Helper
{
public class CultureHelper
{
protected HttpSessionState session;

//constructor
public CultureHelper(HttpSessionState httpSessionState)
{
session = httpSessionState;
}
//Enum
public enum Language
{
[Display(Name = "en-GB", ResourceType = typeof(Resource))]
English = 0,
[Display(Name = "hi-IN", ResourceType = typeof(Resource))]
Hindi = 1
}

// Properties
public Language cultureLang;
public Language CurrentCulture
{

get
{
return cultureLang;
}

set
{
switch (value)
{
case "English":
cultureLang = Language.English;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureLang);
break;
case "Hindi":
cultureLang = Language.Hindi;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureLang);
break;
default:
cultureLang = Language.English;
break;
}
}

}
}
}

5. Adding Controller

BaseController

BaseController in MVC that is inherited by all other controllers. In BaseController, common code is written which can be used in all the pages.

E.g.: by setting the language in the current thread for a multilingual site.

using Localization.Helper;  

using System;  

using System.Collections.Generic;  

using System.Linq;  

using System.Web;  

using System.Web.Mvc;  

  

namespace Localization.Controllers  

{  

    public class BaseController : Controller  

    {  

        protected override void ExecuteCore()  

        {  

            int culture = 0;  

            if (this.Session == null || this.Session["CurrentCulture"] == null)  

            {  

  

                int.TryParse(System.Configuration.ConfigurationManager.AppSettings["Culture"], out culture);  

                this.Session["CurrentCulture"] = culture;  

            }  

            else  

            {  

                culture = (int)this.Session["CurrentCulture"];  

            }  

            // calling CultureHelper class properties for setting    

            CultureHelper.CurrentCulture = culture;  

  

            base.ExecuteCore();  

        }  

  

        protected override bool DisableAsyncSupport  

        {  

            get { return true; }  

        }    

    }  

}  

HomeController

Home Controller will inherit BaseController. To add a Controller just right-click on the Controller folder and select Add then inside that select Controller.

using Localization.Helper;  

using Localization.Models;  

using System;  

using System.Collections.Generic;  

using System.Linq;  

using System.Web;  

using System.Web.Mvc;  

  

namespace Localization.Controllers  

{  

    public class HomeController : Controller  

    {  

        public ActionResult Index()  

        {  

            return View(new UserDetails());  

        }  

  

        public ActionResult ChangeCurrentCulture(string id)  

        {  

            //    

            // Change the current culture for this user.    

            //    

            CultureHelper.CurrentCulture = id;  

            //    

            // Cache the new current culture into the user HTTP session.     

            //    

            Session["CurrentCulture"] = id;  

            //    

            // Redirect to the same page from where the request was made!     

            //    

            return Redirect(Request.UrlReferrer.ToString());  

        }    

    }  

}  

6. Add a link button in the View

LoginPartial.cshtml page to display it on all pages of the website/application.

@{  

    Layout = null;  

}  

  

<!DOCTYPE html>  

  

<html>  

<head>  

    <meta name="viewport" content="width=device-width" />  

    <title></title>  

</head>  

<body>  

    <div>  

    @using System.Globalization  

    @using Localization  

    @using System.Threading;  

    @if (Request.IsAuthenticated)  

    {  

        <p>  

            Hello, @Html.ActionLink(User.Identity.Name, "ChangePassword", "Account",  

        routeValues: null,  

        htmlAttributes: new { @class = "username", title = "Change password" })!  

  

            @Html.ActionLink("Log off", "LogOff", "Account")  

        </p>  

    }  

    else  

    {  

        <ul>  

            <li>  

                @Html.ActionLink("Register", "Register", "Account",  

        routeValues: null, htmlAttributes: new { id = "registerLink" })  

        </li>  

  

        <li>  

            @Html.ActionLink("Log in", "Login", "Account",  

        routeValues: null, htmlAttributes: new { id = "loginLink" })  

    </li>  

</ul>  

    }  

  

    <ul style="margin-top:10px;">  

        @{  

            CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;  

  

            <li><a href="/Home/ChangeCurrentCulture/English">English</a></li>  

  

            <li><a href="/Home/ChangeCurrentCulture/Hindi">Hindi</a></li>  

        }  

    </ul>   

    </div>  

</body>  

</html> 

Here links are added from where the user will be able to change his website Language. When the user clicks on this link it will call the HomeController ChangeCurrentCulture Action result and it will pass an id to it.

According to that CultureHelper will get input and it will set the Culture for the page.

7. Adding View for HomeController

For adding a View just right-click anywhere inside HomeController and select Add View.

After clicking Add View a new dialog will pop up with the name Add View. Inside that you need to select:

View engine: Razor.

Model Class: UserDetails.

Scaffold template: Create.

Use a layout or master page: Check this Property.

Implementation of Localizing App for different cultures
@model MvcLocalization.Models.Userdetails  

  

@{  

    ViewBag.Title = "Index";  

}  

  
<h2>User Details</h2>  

@using (Html.BeginForm()) {  

    @Html.ValidationSummary(true)  

  

    <fieldset>  

        <legend>Userdetails</legend>  

  

        <div class="editor-label">  

            @Html.LabelFor(model => model.FirstName)  

        </div>  

        <div class="editor-field">  

            @Html.EditorFor(model => model.FirstName)  

            @Html.ValidationMessageFor(model => model.FirstName)  

        </div>  

  

        <div class="editor-label">  

            @Html.LabelFor(model => model.LastName)  

        </div>  

        <div class="editor-field">  

            @Html.EditorFor(model => model.LastName)  

            @Html.ValidationMessageFor(model => model.LastName)  

        </div>  

        <div class="editor-label">

            @Html.LabelFor(model => model.Salary)

        </div>

        <div class="editor-field">

            @Html.EditorFor(model => model.Salary)

            @Html.ValidationMessageFor(model => model.Salary)

        </div>
<p> 

            <input type="submit" value="Create" onclick="ShowError" />  

        </p>  

    </fieldset>  

}  

@section Scripts { 

    @Scripts.Render("~/bundles/jqueryval")  

}  

Client-Side Validating Decimals in Non-English Cultures:

Download and install the following packages:

Globalize: https://github.com/globalizejs/globalize

Jquery-validation-globalize: https://github.com/johnnyreilly/jquery-validation-globalize

CLDR-JSON data: https://github.com/unicode-cldr/cldr-json#cldr-json

@inject Microsoft.AspNetCore.Hosting.IHostingEnvironment HostingEnvironment  

@{  

    string GetDefaultLocale()  

    {  

        const string localePattern = "lib\\cldr-data\\main\\{0}";  

        var currentCulture = System.Globalization.CultureInfo.CurrentCulture;  

        var cultureToUse = "en-GB"; //Default regionalisation to use  


        if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.Name))))  

            cultureToUse = currentCulture.Name;  

        else if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.TwoLetterISOLanguageName))))  

            cultureToUse = currentCulture.TwoLetterISOLanguageName;  


        return cultureToUse;  

    }  

}  


<script type="text/javascript">  

    var culture = "@GetDefaultLocale()";  

    $.when(  

        $.get("/lib/cldr-data/supplemental/likelySubtags.json"),  

        $.get("/lib/cldr-data/main/" + culture + "/numbers.json"),  

        $.get("/lib/cldr-data/supplemental/numberingSystems.json"),  

        $.get("/lib/cldr-data/main/" + culture + "/ca-gregorian.json"),  

        $.get("/lib/cldr-data/main/" + culture +"/timeZoneNames.json"),  

        $.get("/lib/cldr-data/supplemental/timeData.json"),  

        $.get("/lib/cldr-data/supplemental/weekData.json")  

    ).then(function () {  

        // Normalize $.get results, we only need the JSON, not the request statuses.  

        return [].slice.apply(arguments, [0]).map(function (result) {  

            return result[0];  

        });  

    }).then(Globalize.load).then(function () {  

        Globalize.locale(culture);  

    });  

</script>  
  •  Modify “_ValidationScriptsPartial.cshtml” file to include newly installed libraries

 The above code is configured for validating client-side based on culture.

Output:

It’s taking the default culture, English, when it loads the first time.

Implementation of Localizing App for different cultures
Implementation of Localizing App for different cultures

Check it by clicking on Hindi :

Implementation of Localizing App for different cultures

Conclusion:

This blog explained how to implement the localization on an ASP.NET MVC web application. 

The resource files are utilized as the container of the localization information which is provided by the ASP.NET runtime. 

The localization information can be stored in any place. Here the resource files are used which use the ASP.NET localization support classes.

parveen-shaikh

(Microsoft Practice) Sr. Software Developer