Magelia WebStore

  • Summary

How to Manage Localization

Overview: Localization

Download the code sample of this tutorial:
How to manage localization - ZIP - 28.2 mo

When you limit your product's availability to only one language, you limit your potential customer base to a fraction of our world’s 6.5 billion people. If you want your applications to reach a global audience, cost-effective localization of your product is one of the best and most economical ways to reach more customers. Localization is the translation of application resources into localized versions for the specific cultures that the application supports.

Manage Localization

FYI: In Magelia WebStore, it is necessary to specify and configure the different languages available via the administration console. For more information, you can watch the video Localize product names and descriptions with Magelia WebStore.

There are several fundamental concepts to take into account during the localization of your Magelia WebStore online boutique:

Culture: The concept of “culture” takes into account the linguistic differences between several countries or within one country. A culture is most often defined by a geographic area (=country or region) and a language (for example: American English vs. British English), but can also be defined just by a language, such as English. Magelia WebStore has replicated the 300 cultures that already exist in Microsoft .NET into a database in order to have a consistency with the .NET Framework. The creation of these cultures in the database ensures coherence in the .Net Framework and the translation elements found in Magelia WebStore (countries, regions, taxes, products, catalogs, and categories). /documentation/adminconsole/Administration.Platform.Cultures.List?help=true
Currency: In economics, currency is a generally accepted medium of exchange. Magelia comes with a group of currencies already configured.
Country: The concept of countries is particularly important for e-commerce because for each country there are assigned currencies, taxes, etc. Magelia comes with a group of countries that are already configured in the software /documentation/adminconsole/Administration.Platform.Countries.List?help=true
Region: Depending on the country, the concept of regions has important aspects for e-commerce. In certain countries, taxes are managed by region. In other countries, certain regions are exceptions in terms of taxes or delivery. Magelia comes with a group of regions already configured in the software /documentation/adminconsole/Administration.Platform.Regions.List?help=true
Continent: To access a country more quickly, it is useful to group the countries together by continent. To do this, Magelia allows you to define continents, and while defining countries, to assign a country to a continent.
Language: Magelia comes with a group of languages already configured (referenced language list by Microsoft/NET framework). These languages were created in a database to ensure consistency in the .Net Framework and the translation elements found in Magelia WebStore (countries, regions, taxes, products, catalogs, and categories). Only the translation of a given language is able to be modified. The combination of a language and of a geographic area defines the concept of culture.

The Magelia WebStore context by default provides you with methods to facilitate localization of your application:

public class WebStoreContext : WebStoreContext<CatalogServiceClient, CustomerServiceClient, StoreServiceClient>
{
    // ...
 
    public virtual CatalogServiceClient CatalogClient
    {
        get
        {
            return this.GetCatalogClient(this.Culture.LCID, this.Currency.CurrencyId, this.Location.CountryId, this.Location.RegionId, this.Location.ZipCode);
        }
    }
 
    public virtual CultureInfo Culture
    {
        get
        {
            if (HttpContext.Current.Session["CultureId"] != null)
            {
                return new CultureInfo((Int32)HttpContext.Current.Session["CultureId"]);
            }
            else
            {
                StoreContext storeContext = this.GetStoreContext(CultureInfo.CurrentCulture);
                Int32 defaultCultureId = storeContext.AvailableCultures.First(ac => ac.IsDefault).LCID;
                HttpContext.Current.Session["CultureId"] = defaultCultureId;
                return new CultureInfo(defaultCultureId);
            }
        }
    }
 
    public virtual Currency Currency
    {
        get
        {
            StoreContext storeContext = this.GetStoreContext(CultureInfo.CurrentCulture);
            IEnumerable<Currency> currencies = storeContext.AvailableCurrencies;
            if (HttpContext.Current.Session["CurrencyId"] != null)
            {
                Int32 currencyId = (Int32)HttpContext.Current.Session["CurrencyId"];
                currencies = currencies.Where(c => c.CurrencyId == currencyId);
            }
            else
            {
                currencies = currencies.Where(c => c.IsDefault);
            }
            return currencies.FirstOrDefault();
        }
    }
 
    public virtual Location Location
    {
        get
        {
            Location location = new Location();
 
            if (HttpContext.Current.Session["Location"] != null)
            {
                String[] serializedLocation = ((String)HttpContext.Current.Session["Location"]).Split('|');
                location.CountryId = Int32.Parse(serializedLocation[0]);
                location.RegionId = String.IsNullOrEmpty(serializedLocation[1]) ? new Nullable<Guid>() : Guid.Parse(serializedLocation[1]);
                location.ZipCode = String.IsNullOrEmpty(serializedLocation[2]) ? null : serializedLocation[2];
            }
            else
            {
                StoreContext storeContext = this.GetStoreContext(CultureInfo.CurrentCulture);
                location.CountryId = storeContext.AvailableCountries.Where(c => c.IsDefault).First().CountryId;
            }
 
            return location;
        }
    }
 
    public void SetCulture(Int32 cultureId)
    {
        HttpContext.Current.Session["CultureId"] = cultureId;
    }
    public void SetCurrency(Int32 currencyId)
    {
        HttpContext.Current.Session["CurrencyId"] = currencyId;
    }
    public void SetLocation(Int32 countryId)
    {
        this.SetLocation(countryId, null, null);
    }
    public void SetLocation(Int32 countryId, Nullable<Guid> regionId)
    {
        this.SetLocation(countryId, regionId, null);
    }
    public void SetLocation(Int32 countryId, String zipCode)
    {
        this.SetLocation(countryId, null, zipCode);
    }
    public void SetLocation(Int32 countryId, Nullable<Guid> regionId, String zipCode)
    {
        HttpContext.Current.Session["Location"] = String.Join("|", new String[] { countryId.ToString(), regionId.ToString(), zipCode });
    }
 
    // ...
}

These different concepts linked to localization are very important. As we can notice in the preceeding example, to retrieve a catalog, we must specify:

• A culture identifier
• A currency identifier
• A country identifier
• A region identifier
• A postal code

The information retrieved for our catalog will thus be linked to these different settings. A product can thus be defined for France but not for England. It is thus necessary to grasp these mechanisms in order to correctly define your products.

How to set localization

It is thus possible to easily define the localization of your shop. You may also add options that allow the user to change at any time the currency used or the language displayed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Shared
{
    public class ContextViewModel
    {
        private IEnumerable<SelectListItem> _currencies;
        private IEnumerable<SelectListItem> _countries;
        private IEnumerable<SelectListItem> _cultures;
 
        /// <summary>
        /// List of available cultures
        /// </summary>
        public IEnumerable<SelectListItem> Cultures
        {
            get
            {
                if (this._cultures == default(IEnumerable<SelectListItem>))
                {
                    this._cultures = Enumerable.Empty<SelectListItem>();
                }
                return this._cultures;
            }
            set
            {
                this._cultures = value;
            }
        }
 
        /// <summary>
        /// List of available currencies
        /// </summary>
        public IEnumerable<SelectListItem> Currencies
        {
            get
            {
                if (this._currencies == default(IEnumerable<SelectListItem>))
                {
                    this._currencies = Enumerable.Empty<SelectListItem>();
                }
                return this._currencies;
            }
            set
            {
                this._currencies = value;
            }
        }
 
        /// <summary>
        /// List of available countries
        /// </summary>
        public IEnumerable<SelectListItem> Countries
        {
            get
            {
                if (this._countries == default(IEnumerable<SelectListItem>))
                {
                    this._countries = Enumerable.Empty<SelectListItem>();
                }
                return this._countries;
            }
            set
            {
                this._countries = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Shared.ContextViewModel
<script type="text/javascript">
    //<![CDATA[
    $(document).ready(
        function () {
            $('#ddlCultures').change(
                function () {
                    document.location.href = '@Url.Action("SetCulture", "Shared")/' + $(this).val();
                }
            );
            $('#ddlCountries').change(
                function () {
                    document.location.href = '@Url.Action("SetCountry", "Shared")/' + $(this).val();
                }
            );
            $('#ddlCurrencies').change(
                function () {
                    document.location.href = '@Url.Action("SetCurrency", "Shared")/' + $(this).val();
                }
            );
        }
    );
    //]]>      
</script>
<section class="context">
    <div>
        <label for="ddlCultures">
            @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Shared.Context.CultureLabelText
        </label>
        @Html.DropDownList("culture", this.Model.Cultures, new { id = "ddlCultures" })
        <label for="ddlCountries">
            @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Shared.Context.CountryLabelText
        </label>
        @Html.DropDownList("country", this.Model.Countries, new { id = "ddlCountries" })
        <label for="ddlCurrencies">
            @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Shared.Context.CurrencyLabelText
        </label>
        @Html.DropDownList("currency", this.Model.Currencies, new { id = "ddlCurrencies" })
    </div>
</section>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Shared;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
 
public class SharedController : BaseController
{
    public SharedController(SampleSiteContext sampleSiteContext)
        : base(sampleSiteContext)
    { }
 
    [ActionName("Catalogs")]
    public PartialViewResult CatalogsAction()
    {
        return this.PartialView(new CatalogsViewModel { Catalogs = this.SampleSiteContext.Catalogs });
    }
 
    public ActionResult SetCatalog(Guid id)
    {
        this.SampleSiteContext.SetCatalog(id);
        return this.RedirectToAction("Index", "Home");
    }
 
    public PartialViewResult Context()
    {
        return this.PartialView(
            new ContextViewModel
            {
                Cultures = this.SampleSiteContext.StoreContext.AvailableCultures.Select(c => new SelectListItem { Text = c.Name, Value = c.LCID.ToString(), Selected = c.LCID == Thread.CurrentThread.CurrentCulture.LCID }),
                Currencies = this.SampleSiteContext.StoreContext.AvailableCurrencies.Select(c => new SelectListItem { Text = c.Name, Value = c.CurrencyId.ToString(), Selected = c.CurrencyId == this.SampleSiteContext.Currency.CurrencyId }),
                Countries = this.SampleSiteContext.StoreContext.AvailableCountries.Select(c => new SelectListItem { Text = c.Name, Value = c.CountryId.ToString(), Selected = c.CountryId == this.SampleSiteContext.Location.CountryId })
            }
        );
    }
 
    public ActionResult SetCulture(Int32 id)
    {
        this.SampleSiteContext.SetCulture(id);
        if (this.Request.UrlReferrer == default(Uri))
        {
            return this.RedirectToAction("Index", "Home");
        }
        else
        {
            return this.Redirect(this.Request.UrlReferrer.ToString());
        }
    }
 
    public ActionResult SetCountry(Int32 id)
    {
        this.SampleSiteContext.SetLocation(id);
        return this.RedirectToAction("Index", "Home");
    }
 
    public ActionResult SetCurrency(Int32 id)
    {
        this.SampleSiteContext.SetCurrency(id);
        return this.RedirectToAction("Index", "Home");
    }
}

We can then, for example, display different options to allow the user to define the different localization elements, such as language, currency, etc.

<footer>
    @{Html.RenderAction("Context", "Shared");}
    <!-- ... -->
</footer>

When you limit your product's availability to only one language

Warning! It is possible that products appear in a language, a currency, or a region but not in another. This is generally due to a lack of configuration of your product in the administration console. Indeed, if you wish, for example, that a product be available in French and in English, you must have defined all information in each of the two languages. For more information, you can view the video Localize product names and descriptions with Magelia WebStore.

Download the code sample of this tutorial:
How to manage localization - ZIP - 28.2 mo