Custom Language Selector in Sitecore

Posted by

I’d like to share my knowledge about some Sitecore functionality I’ve recently worked on with the hope it could be helpful to any other Sitecore aspirants for sharpening their skills and keeping us all motivated to craft better Sitecore solutions.

I received a requirement from one of my clients to create a Country selector where a visitor can select any country to view the website in a specific language.

all country

We’ve got an architecture where we need to redirect visitors to different URLs depending on the country they choose, so we need a way to associate content with countries inside Sitecore to make this work. The country list already exists in Sitecore, but we just need to find an easy way to associate it with content.

To make it easy for content editors we created a custom dropdown field that shows the sitecore language items currently created for the solution.
In this dropdown, we want the language followed by the country name.

language dropdown

To add a new language the content editor follows the normal Sitecore procedure of adding a new language under /sitecore/system/Languages location. They just create a country item and then select the language through the language dropdown as they usually would.

With the help of this feature content editor can select directly language followed by the country name without remembering the country-language code.
Following is the sitecore content architecture under global (/sitecore/content/site item/global):-

sitecore architecture

These are the following steps to create the language-country dropdown in the core database:-

  1. Create Custom field:-

    a. Create folder with the name custom types under /sitecore/system/Field types

b.Create Unbound Droplist item under custom types folder with /sitecore/templates/System/Templates/Template field type template.

Core file system

c. In the control field of this item : Enter command “prefix: [class name]”  example:- custom: unbounddroplist.

Core field

2. Create a class file in class library project.

 

Now this class will contain a code to make the custom field as drop list and also to fetch all the language codes convert it into language name with country.

Following is the code:-

public class UnboundDroplist :Control
  {
    public UnboundDroplist()
    {
      Class = "scContentControl";
      Activation = true;
    }

    public string ItemId { get; set; }

    public string Source { get; set; }

    public bool HasPostData { get; set; }

    protected override void DoRender(System.Web.UI.HtmlTextWriter output)
    {
      string error = null;
      output.Write("<select" + GetControlAttributes() + ">");
      output.Write("<option value = \"\"></option>");

      if (String.IsNullOrEmpty(Source))
      {
        bool valueFound = String.IsNullOrEmpty(Value);
        Sitecore.Data.Database dbMaster = Sitecore.Data.Database.GetDatabase("master");
        var languagefolder = dbMaster.GetItem("/sitecore/system/Languages");
        var allLanguage = languagefolder.Axes.GetDescendants();
        foreach (var language in allLanguage)
        {
          string languagename = language.Name;
          System.Globalization.CultureInfo cultureInfo = Language.CreateSpecificCulture(languagename);
          string displayname = cultureInfo.DisplayName;
          string value = language.ID.ToString();
          valueFound = valueFound || displayname == Value;
          output.Write(String.Format(@"<option value=""{1}"" {2}>{0}</option>", displayname,value, Value == value ? "selected=\"selected\"" : String.Empty));

        }
      }
      else
      {
        bool valueFound = String.IsNullOrEmpty(Value);
          foreach (string s in Source.Split('|'))
          {
          valueFound = valueFound || s == Value;

          output.Write(String.Format(@"<option value=""{0}"" {1}>{0}</option>", s,Value == s ? " selected=\"selected\"" : String.Empty));
           }

          if (!valueFound)
          {
          error = "Value not in the selection list.";
           }
      }
      if (error != null)
      {
        output.Write("<optgroup label=\"" + error + "\">");
        output.Write("<option value=\"" + Value + "\" selected=\"selected\">" + Value + "</option>");
        output.Write("</optgroup>");
      }
output.Write("");

            if (error != null)
            {
                output.Write("{0}", error);
            }

            
        }

        protected override bool LoadPostData(string value)
        {
            HasPostData = true;

            if (value == null)
            {
                return false;
            }

            Log.Info(this + " : Field : " + GetViewStateString("Field"), this);
            Log.Info(this + " : FieldName : " + GetViewStateString("FieldName"), this);

            if (GetViewStateString("Value") != value)
            {
                SetModified();
            }

            SetViewStateString("Value", value);
            return true;
        }

        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            base.OnLoad(e);

            if (!HasPostData)
            {
                LoadPostData(string.Empty);
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            base.OnPreRender(e);
            ServerProperties["Value"] = ServerProperties["Value"];
        }

        private static void SetModified()
        {
            Sitecore.Context.ClientPage.Modified = true;
        }
    }

 

3. Create a configuration file to read your custom prefix such as:-

<configuration>
<sitecore>
<controlsources>
<source mode="on" namespace="[Namespace]" assembly="[Assembaly]" prefix="custom"></source>
</controlsources>
</sitecore>
<configuration>

4. Create an item which has an unbounddroplist as a field.

It will contain all the language names as you can see below:-

language dropdown

To fetch the value from custom language droplist field and add url:-

  Sitecore.Data.Fields.LinkField linkField = itm.Fields["Link"];
                    string language = itm["LanguageDropdown"];
                    if (!string.IsNullOrEmpty(language))
                    {
                        Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
                        urlOptions.SiteResolving = true;
                        urlOptions.LanguageEmbedding = Sitecore.Links.LanguageEmbedding.Never;
                        Item id = Sitecore.Context.Database.GetItem(language);
                        string culture = id.Fields["Regional Iso Code"].Value;
                        var link = LinkManager.GetItemUrl(linkField.TargetItem, urlOptions);
                        if (string.IsNullOrEmpty(culture))
                        {
                            string Iso = id.Fields["Iso"].Value;
                            hlLink.NavigateUrl = "/" + Iso + link;
                        }
                        else
                        {
                            hlLink.NavigateUrl = "/" + culture + link;
                        } 
                    }
                    else
                    {
                        UrlOptions urlOptions = new UrlOptions();
                        urlOptions.SiteResolving = true;
                        urlOptions.LanguageEmbedding = LanguageEmbedding.Always;
                        var str = LinkManager.GetItemUrl(linkField.TargetItem, urlOptions);
                        hlLink.NavigateUrl = str;
                    }

 

If you find yourself in a similar situation, and need to display some custom information from Sitecore items in a field, now you’ll have the code you need to make it all work.

Until next time, cheers

 

Leave a Reply