DateTime time zone conversion with .NET 3.5

Some time ago I wrote a blog post about Timezone conversion and handling within .NET which sucked at that time.

With .NET 3.5 its better, in fact much better, its actually usable :)

In .NET 1.1 and 2.0 there were not way to convert DateTime objects between different time zones to handle all the hassle of adding minutes, handling summer winter time, etc.

There is now. Its not perfect, but it does the job.

Its pretty straightforward.

I will provide an example, which should give you an idea of how to use in real life.

The example below takes two DateTime objects. One UTC Datetime, and one Danish DateTime.

Both DateTime object are created with the same numbers, one is just specified as UTC, the other one as local time.

//Create DateTime with UTC Kind specified, and with Current time in UTC
DateTime utcNow = new DateTime(2008, 8, 16, 21, 42, 32, DateTimeKind.Utc);

//Create danish local DateTime
DateTime dkNow = new DateTime(2008, 8, 16, 21, 42, 32, DateTimeKind.Local); ;
//Find timezone info for egypt
TimeZoneInfo egypt = TimeZoneInfo.FindSystemTimeZoneById("Egypt Standard Time");
//Convert danish local time to egypt time
DateTime egyptTime1 = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dkNow, "Egypt Standard Time");
//Convert utc time to egypt local time
DateTime egyptTime2 = TimeZoneInfo.ConvertTimeFromUtc(utcNow, egypt);

//Write out initial DateTime objects
Console.WriteLine("{0} {1}", dkNow, dkNow.ToString("%K"));
//Writes out 16-08-2008 21:42:32 +02:00
Console.WriteLine("{0} {1}", utcNow, utcNow.ToString("%K"));
//Writes out 16-08-2008 21:42:32 Z
//Write out the results
Console.WriteLine("Danish NOW converted to Eqypt time:{0} {1}", egyptTime1,

DateTime.SpecifyKind(egyptTime1, DateTimeKind.Local).ToString("%K"));
//Writes out Danish NOW converted to Eqypt time:16-08-2008 22:42:32 +02:00
Console.WriteLine("UTC NOW converted to Eqypt time:{0} {1}", egyptTime2,
DateTime.SpecifyKind(egyptTime2, DateTimeKind.Local).ToString("%K"));
//Writes out UTC NOW converted to Eqypt time:16-08-2008 00:42:32 +02:00

As you can clearly see of the example it is fairly easy to convert DateTime's between timezones, but there is just one question that springs to mind.

Where do you get the list of Timezone ID's?

Well I will provide you with one here, but its a crappy solution Microsoft have chosen for timezone names.


Timezone IDUTC offset offset
Morocco Standard Time 0:0
GMT Standard Time 0:0
Greenwich Standard Time 0:0
W. Europe Standard Time 1:0
Central Europe Standard Time 1:0
Romance Standard Time 1:0
Central European Standard Time 1:0
W. Central Africa Standard Time 1:0
Jordan Standard Time 2:0
GTB Standard Time 2:0
Middle East Standard Time 2:0
Egypt Standard Time 2:0
South Africa Standard Time 2:0
FLE Standard Time 2:0
Israel Standard Time 2:0
E. Europe Standard Time 2:0
Namibia Standard Time 2:0
Arabic Standard Time 3:0
Arab Standard Time 3:0
Russian Standard Time 3:0
E. Africa Standard Time 3:0
Georgian Standard Time 3:0
Iran Standard Time 3:30
Arabian Standard Time 4:0
Azerbaijan Standard Time 4:0
Caucasus Standard Time 4:0
Armenian Standard Time 4:0
Afghanistan Standard Time 4:30
Ekaterinburg Standard Time 5:0
Pakistan Standard Time 5:0
West Asia Standard Time 5:0
India Standard Time 5:30
Sri Lanka Standard Time 5:30
Nepal Standard Time 5:45
N. Central Asia Standard Time 6:0
Central Asia Standard Time 6:0
Myanmar Standard Time 6:30
SE Asia Standard Time 7:0
North Asia Standard Time 7:0
China Standard Time 8:0
North Asia East Standard Time 8:0
Singapore Standard Time 8:0
W. Australia Standard Time 8:0
Taipei Standard Time 8:0
Tokyo Standard Time 9:0
Korea Standard Time 9:0
Yakutsk Standard Time 9:0
Cen. Australia Standard Time 9:30
AUS Central Standard Time 9:30
E. Australia Standard Time 10:0
AUS Eastern Standard Time 10:0
West Pacific Standard Time 10:0
Tasmania Standard Time 10:0
Vladivostok Standard Time 10:0
Central Pacific Standard Time 11:0
New Zealand Standard Time 12:0
Fiji Standard Time 12:0
Tonga Standard Time 13:0
Azores Standard Time -1:0
Cape Verde Standard Time -1:0
Mid-Atlantic Standard Time -2:0
E. South America Standard Time -3:0
Argentina Standard Time -3:0
SA Eastern Standard Time -3:0
Greenland Standard Time -3:0
Montevideo Standard Time -3:0
Newfoundland Standard Time -3:-30
Atlantic Standard Time -4:0
SA Western Standard Time -4:0
Central Brazilian Standard Time -4:0
Pacific SA Standard Time -4:0
Venezuela Standard Time -4:-30
SA Pacific Standard Time -5:0
Eastern Standard Time -5:0
US Eastern Standard Time -5:0
Central America Standard Time -6:0
Central Standard Time -6:0
Central Standard Time (Mexico) -6:0
Mexico Standard Time -6:0
Canada Central Standard Time -6:0
US Mountain Standard Time -7:0
Mountain Standard Time (Mexico) -7:0
Mexico Standard Time 2 -7:0
Mountain Standard Time -7:0
Pacific Standard Time -8:0
Pacific Standard Time (Mexico) -8:0
Alaskan Standard Time -9:0
Hawaiian Standard Time -10:0
Samoa Standard Time -11:0
Dateline Standard Time -12:0


Naturally the best solution would have been to use the Zoneinfo names for timezones since they are a lot more intuitive, and a lot of websites already use them out there, and oh btw all unix/linux/macos out there as well :)

ASP.NET http authentication header rewrites

I were recently a victim of's browser detection and on the fly content change.

The story is:

I work for a company called ZYB, and for a new feature we are developing we have created some HttpModules, which basically provides means of authenticating our users against their usual ZYB account using either Bacic Authentication or Digest Authentication.

This is all fine, and since both Basic Authentication and Digest Authentication are pretty straightforward to implement we were done in a few days.

We tested the modules, simply by invoking the urls that were protected by the web.config sections:

<deny users="?" />
<authentication mode="None" />

Please note that when developing your own authentication modules, you have to allow Anonymous users in IIS, and remove all other authentication options, and in the web.config, you have to set the

<authentication mode="None" />

Otherwise your modules wont kick in.

But back on track, this is not the reason why I am writing this blog post, its simply because we suddenly discovered that for some user agents, was modifying the HTTP 401 Unauthorized status code to 200 OK, but still sent the WWW-Authenticate header anyway.

This does seem like a bug, and I traveled many paths before finding out that it was the user-agent header that triggered the Status rewrite.

I am pretty sure should never rewrite the status codes, at least not for authentication, since it pretty much screws up authentication.

Since changing the User-Agent was not an option, I tried to change the Request headers, but microsoft have made that impossible with a recent fix to .NET.

So I was getting desperate, and I tried to use some of the .browser files you can place in the App_Browsers directory, but I could not find any options for "Do not fuck up my status http headers", so no luck there.

In a desperate measure, I looked at the clientTarget xml elements you can put into the web.config, but no luck there as well, so my last try before rewriting the entire feature, to use in place authentication within the http body, was the

browserCaps section in system.web in the web.config.

I found that if I added the following section:

      <result type="System.Web.HttpBrowserCapabilities"/>
      <use var="HTTP_USER_AGENT"/>
    </browserCaps> stopped fucking up my headers, and returned the proper 401 status code.

The user agent that fucked everything up, was more or less any mobile device out there, and ZYB being a mobile company, its damn hard to just ignore that.

So this blog post is hopefully a help for people stuck in the same situation.


Extension methods

As promised way back in 2007 I will try to show some of the coolness of extension methods.

Extension methods are simply said, methods that can extend existing classes whether or not you have access to the original code.

You cannot access private member variables etc, but from all other views and use it will look as it was a method that was created originally in the class it self.

To use an extension method, you have to import the namespace that contains the class with the method, and have a variable of the type the method works on.

Lets say you always wanted a Reverse() method on a string because you always use that nice feature in some obscure project you are the maintainer of.

No sweat.

The principles of extension methods are simple. Just create a static class, put a static method in that class, with a special signature, and voilá you can access that method in your other class as it was natively written for that.

Let me give you an example with the Reverse() method on string.

    /// <summary>
    /// Class with useful extensions to System.String
    /// </summary>
    public static class StringExtensions
        /// <summary>
        /// Reverses the specified string
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        public static string Reverse(this string s)
            StringBuilder sb = new StringBuilder(s.Length);
            char[] chars = s.ToCharArray();
            for (int x = chars.Length - 1; x > -1; x--)
            return sb.ToString();
Please note the use of this in the method signature, the this signifies that its should be interpreted as an extension method, and then you just use the parameter as it was a normal method.

To use the method above, just create a string variable and call Reverse() on it. Just as easy as:

string s = "OMG";
And its really as simple as that.

Another example could be System.DateTime which sometimes can be a bitch to get to know the different string formats for outputting. Why not just create an extension method with your favorite format:

 /// <summary>
 /// Class with useful extensions to System.DateTime
 /// </summary>
 public static class DateTimeExtensions
     /// <summary>
     /// Returns an ISO8601 string representation of the date time object
     /// as used in e.g. VEVENT
     /// </summary>
     /// <param name="dt">The dt.</param>
     /// <returns></returns>
     public static string ToISO8601String(this DateTime dt)
         if (dt.Kind == DateTimeKind.Utc)
             return dt.ToString("yyyyMMddThhmmssZ");
             return dt.ToString("yyyyMMddThhmmss");
Which in turn is used as easily as:

DateTime dt = DateTime.Now;
See how easy it is :-)

Extension methods can naturally have parameters just like normal methods, and its as simple as creating normal parameters, the only rule is to have the class that the method should be an extension to as the first parameter, i.e. public static bool MatchModulus(this int x, int modulus).

A more elaborate example could be another string extention method called Slice:

        /// <summary>
        /// Slices the specified string into the specified number of parts
        /// </summary>
        /// <param name="s">The string to slice into parts</param>
        /// <param name="parts">The number of parts</param>
        /// <returns></returns>
        public static string[] Slice(this string s, int parts)
            if (string.IsNullOrEmpty(s))
                throw new ArgumentException("String to be sliced cannot be null or empty");
            if (parts < 1)
                throw new ArgumentException("Number of parts to slice into must be greater than 0");
            string[] slices = new string[parts];
            int charsInSlice = (int)s.Length / parts;
            int charsRemoved = 0;
            for (int x = 0; x < parts; x++)
                slices[x] = s.Substring(charsRemoved, charsInSlice);
                charsRemoved += charsInSlice;
            if (charsRemoved != s.Length)
                slices[parts - 1] += s.Substring(charsRemoved);
            return slices;
Which in this example slices the string into the specified number of parts. The example is not a perfect method, because if you specify more parts than characters in the string it will return a string array with only the last element of the string array containing the entire string. Feel free to rewrite the method, its very simple to change :-p.

I hope this gave a little insight into extension methods and that they can in fact be useful.

first glance at lambda functions in c# 3.0

When I first heard about lambda functions in c# 3.0, I were a bit sceptical, since the syntax is like nothing else I have seen.

I am still sceptical, but I can see places where they have their use, like in very simple selects from lists, simple string manipulations etc.

	    string[] abs = new string[] { "Ab", "ab", "aB", "AB" };

            var abSelected = abs.Where(str => str == "ab");

            foreach (string p in abSelected)

            var allAbs = abs.Where(str => str.ToLower() == "ab");
            foreach (string p in allAbs)
Which shows an array of strings, where we first select those that matches "ab", lowercase, and then writes each one found out. Then it selects the same again, but ignores the case, and more or less selects everything.

Or a simple string manipulation:

	    var allCAPS = abs.Select(cap => cap.ToUpper());
            Console.WriteLine("ab all upper case\r\n");
            foreach (string p in allCAPS)
Which basically converts all the strings to uppercase. In this example pretty useless, but it could be other string manipulations done.

objects are more or less the same syntax. Consider the following simple classes:

 public enum Sex

 public class Person
     public string Name

     public int Age

     public Sex Sex

And the following snippets of code:

 List<Person> people = new List<Person>();
 Person person = new Person();
 person.Name = "Bjørn Smith";
 person.Age = 34;
 person.Sex = Sex.Male;

 person = new Person();
 person.Name = "Female beauty hungry for sex";
 person.Age = 35;
 person.Sex = Sex.YesPlease;

 person = new Person();
 person.Name = "Female beauty";
 person.Age = 18;
 person.Sex = Sex.Female;


 person = new Person();
 person.Name = "Female blonde";
 person.Age = 25;
 person.Sex = Sex.Female;


 person = new Person();
 person.Name = "Female brunette";
 person.Age = 38;
 person.Sex = Sex.Female;

First a simple setup, to get some data to work with. I know the dataset is sparse, but it should be enough to show some ways of using lambda.

And then some simple queries to the list:

 Console.WriteLine("Female of all ages");
 var females = people.Where(a => a.Sex == Sex.Female || a.Sex == Sex.YesPlease);
 foreach (Person sexpartner in females)
     Console.WriteLine(string.Format("{0}, {1} years", sexpartner.Name, sexpartner.Age));

 Console.WriteLine("Order by age ascending"); females = people.Where(a => a.Sex == Sex.Female || a.Sex == Sex.YesPlease).OrderBy(a => a.Age); foreach (Person sexpartner in females) { Console.WriteLine(string.Format("{0}, {1} years", sexpartner.Name, sexpartner.Age)); } //For those really hungry we only want objects with name and sex var hungry = people.Where(a => a.Sex == Sex.YesPlease).Select(hu => new { hu.Name, hu.Age }); Console.WriteLine("Hungry only"); foreach (var femalehungry in hungry) { Console.WriteLine(string.Format("{0}, {1} years", femalehungry.Name, femalehungry.Age)); }

First query is just selecing all Person objects that have Sex as Female or YesPlease.

Please note the "strange" syntax of creating the "query" object by doing a: a => a.Sex ==  Sex.Female, which is exately the same as an anonymous delegate like delegate(string a) {return a.Sex == Sex.Female;}. I tend to like the last anonymous delegate more, since in my eyes its obvious what it does, but I'm sure that in time, I will embrace lambda functions where they make sense.

Second query is basically the same as the first one, but with the twist that we are ordering the list by Age ascending, just by doing a .OrderBy(a => a.Age), thats quite nifty I think, and if you compare to anonymous delegates, you would have had to do something like the following to have the same result:

 List<Person> femalePeople = people.FindAll(delegate(Person p)
     return p.Sex == Sex.Female;
 }).Sort(delegate(Person ps1, Person ps2)
     return ps1.Age.CompareTo(ps2.Age);
So when you compare the two blocks of code, I see the benefit of lambda functions, but I still think they clutter the code, anonymous delegates easier to understand, but then again, it might just need some getting used to :)

The last select to the people list is basically the same, but we only select those that have YesPlease as Sex, and we create a new class on the fly with only two Properties, Name and Sex. Thats less usefull if you ask me, since you cannot return an object to the caller of a method, and get the type safety etc. But naturally you can manipulate the newly created objects, and you get intellisense and all the works, thats quite nice :)

This was my first glance at lambda functions, and it might be useful, I still need to see the definitive proof of their usefullness, in particular the feature to create anonymous types on the fly, but I am open to enlightenment :)

VS 2008 released

A few days ago Microsoft released Visual Studio 2008.

Thats great news, since with the release of VS 2008, c# 3.0 and .NET 3.5 is released as well.

.NET have some really exiting new features, like

Extension methods
and lambda functions

I will take a look at them and make a few examples on how to use each of the those items above.

.NET TimeZone

Everyone working with .NET and TimeZones have at one point thought, why the #%&#&% can't I instantiate another TimeZone than the current one, i.e. why is it not possible to create a .NET TimeZone object in the following simple way.

TimeZone zone = new TimeZone("Europe/Copenhagen");

TimeZone zone = new TimeZone("CET");

It seems like Microsoft did not think of, or decided not to implement multi timezone support in .NET, and thats too bad, because Timezone handling, Daylight savings are just a bitch to work with.

Timezones are not so bad, since its pretty easy to identify what timezone a given country is in. There are numerous sources for this on the internet, such as, and with a little manual work, or a little screen scraping you can have a combined country/timezone list in no time.

The real problems occurs when you want to find out whether or not a given TimeDate object is within the Daylight savings time for a given country and timezone, and in that, the timezone are of no use, since it says nothing about the daylight savings of the date.

I have tried some solutions where I try to identify the daylight savings time for the most used countries, for a few years in advance, but that won't help me with dates in the past, and is really not a good solution, since the completeness of the solution is at best lacking.

I have searched a lot of places on the internet for a proper solution, and someone have made a solution for retrieving the timezones from the windows registry combined with some dll imports fromt he win32 API, but those are not perfect either.

So having almost tossed the towel into the ring, I stumpled upon another page on the internet, and I thought, hmm, another crappy implementation, but no, its a full .NET implementation of the tz database I had looked at that timezone database myself a few times, but the sheer size and format of the database was just such a daunting task, that I have never fathomed to even be able to read that into a sensible .NET format.

The .NET library called PublicDomain is very easy to work with, much intuitive, and handles timezones and daylight savings very nice.

Its as simple as:

// Get the local computer's time zone
TzTimeZone dkZone = TzTimeZone.GetTimeZone("Europe/Copenhagen");

TzTimeZone ausZone = TzTimeZone.GetTimeZone("Australia/Adelaide");

DateTime dkNow = DateTime.UtcNow; //When in danish timezone

DateTime auzNow = ausZone.ToLocalTime(dkNow);
Gracefully right :)

Too bad Microsoft did not implement this.

The good part is that they will in .NET 3.5. I'm not sure of the extend of the implementation, or how well the daylight saving rules for each country is implemented, but at least its good that Microsoft at least have started looking in this direction.

multi-cast delegates and Predicate<T>

Since Predicate<T> that is used for finding stuff in a generics list is in fact a multi-cast delegate, I thought it might be possible to chain several Predicates to simplify multiple requirements for the elements returned.

Consider the following code:

Predicate<int> greaterThan5 = delegate(int x) { return x > 5; };
Predicate<int> lessThan10 = delegate(int x) { return x < 10; };

It would be cool if it would be possible to chain them, by doing a simple:

Predicate<int> combined = lessThan10 + greaterThan5;

And then:

List<int> resulting = allInts.FindAll(combined);

Unfortunately it dosen't work, or more precicely, it is only the last delegate that gets invoked.

It seems like MS did not envision people wanting to use multi-cast delegates for their predicates, and when looking at the List.FindAll implementation, its very clear, since it only invokes the delegate as it were a single cast one:

public List<T> FindAll(Predicate<T> match)
    if (match == null)
    List<T> list = new List<T>();
    for (int i = 0; i < this._size; i++)
        if (match(this._items[i]))
    return list;

So unfortunately you still need to do the old fashion way:

List<int> resulting = allInts.FindAll(lessThan10).FindAll(greaterThan5);

Lets hope they change it in c# 3.0


Some years ago, when someone mentioned delegates I would shudder, and think back of all the times when I had tried to use them to something useful, and All I could think of at the time was to use them for events that other objects could subscribe to. This is also a nice feature, but when you think about it delegates is so much more.

I have started using delegates more heavily, and primarily to do Lazy Loading of data from a database. Lazy Loading is a technique where you only load the data when the application need it.  Lets say you have a class Customer, with a lot of properties, including an Orders collection. Instead of loading all orders and all other data that is related to the Customer, why not just load the data when the application makes a request for it, by invoking the get method of the Orders collection.

People would perhaps argue that it would require for the business objects to know the database structure, or if done a little more clever, need a reference to a Data Access Layer, but no, thats not neccesary, since you can use delegates for it.

consider the following delegate:

public delegate List<T> LoadDataDelegate<T>();

This delegate states that it will return a list of objects of type T.

okay then consider the following class

public class Customer

    /// <summary>
    /// Creates a new instance of the Customer class
    /// </summary>
    /// <param name="ordersDelegate"></param>
    public Customer(LoadDataDelegate<Order> ordersDelegate)
        this.ordersDelegate = ordersDelegate;

    private LoadDataDelegate<Order> ordersDelegate;

    private List<Order> orders;
    /// <summary>
    /// Gets a List of orders for the current Customer
    /// </summary>
    public List<Order> Orders
            if (orders == null)
                orders = ordersDelegate();
            return orders;

And the following Mock data layer

public class DAL
    public List<Order> GetAllOrdersForCustomer(long customerID)
        string sql = "select * from orders where customer_id=@customer_id";
        //load into list

        public Customer GetCustomer(long customerID)
            Customer c = new Customer(delegate() { return GetAllOrdersForCustomer(customerID); });
            //load other data from the database

            return c;

These two classes and the delegates, show a very simple way of using delegates for something intelligent and create an object that is capable of loading data from the database on demand, without knowing anything about Datalayers, SQL or anything else.

Nice right :)

Consider implementing all methods that can create, read, update and delete an object as delegates and all you would ever need to expose to your application is the business objects, and perhaps a few factory methods that could create new instances of objects with the delegates assigned to actual methods in your data layers :)

.NET culture names

I have searched the web a lot of times in need of a culture name for a specific language and culture, but I have never been able to find a complete list on the net.
I have compiled a list, and here it is for my own, and hopefully other people's use.

Language/countryCulture name
Afrikaans (South Africa) af-ZA
Albanian (Albania) sq-AL
Arabic (Algeria) ar-DZ
Arabic (Bahrain) ar-BH
Arabic (Egypt) ar-EG
Arabic (Iraq) ar-IQ
Arabic (Jordan) ar-JO
Arabic (Kuwait) ar-KW
Arabic (Lebanon) ar-LB
Arabic (Libya) ar-LY
Arabic (Morocco) ar-MA
Arabic (Oman) ar-OM
Arabic (Qatar) ar-QA
Arabic (Saudi Arabia) ar-SA
Arabic (Syria) ar-SY
Arabic (Tunisia) ar-TN
Arabic (U.A.E.) ar-AE
Arabic (Yemen) ar-YE
Armenian (Armenia) hy-AM
Azeri (Cyrillic, Azerbaijan) az-AZ-Cyrl
Azeri (Latin, Azerbaijan) az-AZ-Latn
Basque (Basque) eu-ES
Belarusian (Belarus) be-BY
Bosnian (Cyrillic, Bosnia and Herzegovina) bs-BA-Cyrl
Bosnian (Latin, Bosnia and Herzegovina) bs-BA-Latn
Bulgarian (Bulgaria) bg-BG
Catalan (Catalan) ca-ES
Chinese (Hong Kong S.A.R.) zh-HK
Chinese (Macao S.A.R.) zh-MO
Chinese (People's Republic of China) zh-CN
Chinese (Singapore) zh-SG
Chinese (Taiwan) zh-TW
Croatian (Bosnia and Herzegovina) hr-BA
Croatian (Croatia) hr-HR
Czech (Czech Republic) cs-CZ
Danish (Denmark) da-DK
Divehi (Maldives) div-MV
Dutch (Belgium) nl-BE
Dutch (Netherlands) nl-NL
English (Australia) en-AU
English (Belize) en-BZ
English (Canada) en-CA
English (Caribbean) en-CB
English (Ireland) en-IE
English (Jamaica) en-JM
English (New Zealand) en-NZ
English (Republic of the Philippines) en-PH
English (South Africa) en-ZA
English (Trinidad and Tobago) en-TT
English (United Kingdom) en-GB
English (United States) en-US
English (Zimbabwe) en-ZW
Estonian (Estonia) et-EE
Faroese (Faroe Islands) fo-FO
Filipino (Philippines) fil-PH
Finnish (Finland) fi-FI
French (Belgium) fr-BE
French (Canada) fr-CA
French (France) fr-FR
French (Luxembourg) fr-LU
French (Principality of Monaco) fr-MC
French (Switzerland) fr-CH
Frisian (Netherlands) fy-NL
Galician (Galician) gl-ES
Georgian (Georgia) ka-GE
German (Austria) de-AT
German (Germany) de-DE
German (Liechtenstein) de-LI
German (Luxembourg) de-LU
German (Switzerland) de-CH
Greek (Greece) el-GR
Gujarati (India) gu-IN
Hebrew (Israel) he-IL
Hindi (India) hi-IN
Hungarian (Hungary) hu-HU
Icelandic (Iceland) is-IS
Indonesian (Indonesia) id-ID
Inuktitut (Latin, Canada) iu-CA-Latn
Irish (Ireland) ga-IE
Italian (Italy) it-IT
Italian (Switzerland) it-CH
Japanese (Japan) ja-JP
Kannada (India) kn-IN
Kazakh (Kazakhstan) kk-KZ
Kiswahili (Kenya) sw-KE
Konkani (India) kok-IN
Korean (Korea) ko-KR
Kyrgyz (Kyrgyzstan) ky-KG
Latvian (Latvia) lv-LV
Lithuanian (Lithuania) lt-LT
Luxembourgish (Luxembourg) lb-LU
Macedonian (Former Yugoslav Republic of Macedonia) mk-M K
Malay (Brunei Darussalam) ms-BN
Malay (Malaysia) ms-MY
Maltese mt-MT
Maori mi-NZ
Mapudungun (Chile) arn-CL
Marathi (India) mr-IN
Mohawk (Mohawk) moh-CA
Mongolian (Cyrillic, Mongolia) mn-MN
Norwegian, Bokmål (Norway) nb-NO
Norwegian, Nynorsk (Norway) nn-NO
Persian (Iran) fa-IR
Polish (Poland) pl-PL
Portuguese (Brazil) pt-BR
Portuguese (Portugal) pt-PT
Punjabi (India) pa-IN
Quechua (Bolivia) quz-BO
Quechua (Ecuador) quz-EC
Quechua (Peru) quz-PE
Romanian (Romania) ro-RO
Romansh (Switzerland) rm-CH
Russian (Russia) ru-RU
Sami, Inari (Finland) smn-FI
Sami, Lule (Norway) smj-NO
Sami, Lule (Sweden) smj-SE
Sami, Northern (Finland) se-FI
Sami, Northern (Norway) se-NO
Sami, Northern (Sweden) se-SE
Sami, Skolt (Finland) sms-FI
Sami, Southern (Norway) sma-NO
Sami, Southern (Sweden) sma-SE
Sanskrit (India) sa-IN
Serbian (Cyrillic, Bosnia and Herzegovina) sr-BA-Cyrl
Serbian (Cyrillic, Serbia and Montenegro) sr-SP-Cyrl
Serbian (Latin, Bosnia and Herzegovina) sr-BA-Latn
Serbian (Latin, Serbia and Montenegro) sr-SP-Latn
Sesotho sa Leboa (South Africa) ns-ZA
Setswana (South Africa) tn-ZA
Slovak (Slovakia) sk-SK
Slovenian (Slovenia) sl-SI
Spanish (Argentina) es-AR
Spanish (Bolivia) es-BO
Spanish (Chile) es-CL
Spanish (Colombia) es-CO
Spanish (Costa Rica) es-CR
Spanish (Dominican Republic) es-DO
Spanish (Ecuador) es-EC
Spanish (El Salvador) es-SV
Spanish (Guatemala) es-GT
Spanish (Honduras) es-HN
Spanish (Mexico) es-MX
Spanish (Nicaragua) es-NI
Spanish (Panama) es-PA
Spanish (Paraguay) es-PY
Spanish (Peru) es-PE
Spanish (Puerto Rico) es-PR
Spanish (Spain) es-ES
Spanish (Uruguay) es-UY
Spanish (Venezuela) es-VE
Swedish (Finland) sv-FI
Swedish (Sweden) sv-SE
Syriac (Syria) syr-SY
Tamil (India) ta-IN
Tatar (Russia) tt-RU
Telugu (India) te-IN
Thai (Thailand) th-TH
Turkish (Turkey) tr-TR
Ukrainian (Ukraine) uk-UA
Urdu (Islamic Republic of Pakistan) ur-PK
Uzbek (Cyrillic, Uzbekistan) uz-UZ-Cyrl
Uzbek (Latin, Uzbekistan) uz-UZ-Latn
Vietnamese (Vietnam) vi-VN
Welsh cy-GB
Xhosa xh-ZA
Zulu zu-ZA