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

6 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

  5. William on November 13th, 2013

    Hi, What I actually need is a multilingual (although the multilingual is a nice to have it isn’t essential) dropdown of languages, so this looked like an easy option for hacking. I have gone the easy route and installed the package but can see no way of adding the new dropdown list from within Contour.
    Im using Umbraco 6.1.6 and Contour 3.0.17 in trial mode

  6. generateur de Gemmes Clash Of Clans on November 17th, 2014

    Thanks for finally writing about > Extending Contour, multilingual countries
    prevalue source - Tim Geyssens, Umbraco developer < Liked it!

Leave a Reply