Nibble

Extending Contour, multilingual countries prevalue source

A question that got my attention this week is what would be the best way to add a multilingual list of countries to a Contour form.

ContourCountries

So this post explains how you can extend contour with a custom prevalue source type

The data

Of course we need the multilingual data, after some research I found the Unicode Common Locale Data Repository http://cldr.unicode.org/ it’s basically a collection of xml files with locale data, including a list a countries

The Code

The code is pretty simply it just uses the current culture the fetch the correct xml file (falling back to English if a culture xml isn’t found) and then it loops trough the territory nodes found in the xml.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using Umbraco.Forms.Core;
 
namespace Contour.Addons.Countries
{
    public class PrevalueSource : FieldPreValueSourceType 
    {
        public PrevalueSource()
        {
            this.Id = new Guid("9ED6C6D7-16A7-4087-A75D-B936D6FAE5A9");
            this.Name = "List of countries";
            this.Description = "Multilingual list of countries (http://unicode.org/ files need to be in /app_data/countrydata/)";
        }
 
        public override List<Exception> ValidateSettings()
        {
            var ex = new List<Exception>();
 
            if (!File.Exists(HttpContext.Current.Server.MapPath("/App_Data/CountryData/common/main/en.xml")))
                ex.Add(new Exception("Unicode Common Locale Data Repository not found, please download from http://cldr.unicode.org and place in /app_data/countrydata/ directory"));
            
            return ex;
        }
 
        public override List<PreValue> GetPreValues(Field field)
        {
            var pvs = new List<PreValue>();
 
            var d = new XmlDocument();
            if (File.Exists(HttpContext.Current.Server.MapPath(
                string.Format("/App_Data/CountryData/common/main/{0}.xml",
                              CultureInfo.CurrentCulture.TwoLetterISOLanguageName))))
            {
                d.Load(HttpContext.Current.Server.MapPath(
                    string.Format("/App_Data/CountryData/common/main/{0}.xml",
                                  CultureInfo.CurrentCulture.TwoLetterISOLanguageName)));
            }
            else
            {
                d.Load(HttpContext.Current.Server.MapPath(
                  "/App_Data/CountryData/common/main/en.xml"));
            }
 
            var countries = new List<KeyValuePair<string, string>>();
            
            foreach (XmlNode c in d.SelectNodes("//territory [string-length(string(@type)) < 3]"))
                countries.Add(new KeyValuePair<string, string>(c.Attributes["type"].Value, c.InnerText));
 
            countries.Sort((firstPair, nextPair) => String.Compare(firstPair.Value, nextPair.Value, StringComparison.Ordinal));
 
            int sort = 0;
            foreach (var c in countries)
            {
                PreValue pv = new PreValue();
                pv.Id = c.Key;
                pv.Value = c.Value;
                if (field != null)
                    pv.Field = field.Id;
                pv.SortOrder = sort;
                pvs.Add(pv);
 
                sort++;
            }
 
            return pvs;
        }
 
    }
}

 

Code is available on bitbucket https://bitbucket.org/starfighter83/contour.addons.country

The package

The countries prevalue source is available as a package and can be used on your current Contour projects http://our.umbraco.org/projects/backoffice-extensions/contour-countries

4 Comments so far

  1. Yannick on November 30th, 2012

    Great! Any reason you didn’t use .NET as a country list source?
    http://www.dreamincode.net/code/snippet2879.htm

  2. Tim Geyssens on November 30th, 2012

    Yup it’s not that accurate and relies on a .net framework update…

  3. Martin Griffiths on December 7th, 2012

    How do I use this in a code first form?

  4. Martin Griffiths on December 12th, 2012

    Hi Tim

    I’ve hit a stumbling block on this….

    I created my drop down list and also added your code first suggestion to get the countries list to automatically appear. But when I submit the form I get this really odd error.

    Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

    If I remove the dropdownlist the form works and submits ok.

    What have I done wrong?

    Martin

Leave a Reply