8

I'm working with an API that returns some information about audio streams in a file, more specifically the audio language in its three-letter ISO name (ISO 639-2) representation.

I would like to parse this information into a new CultureInfo object, but there is no constructor that takes a three-letter code. I could of course write an enormous select statement (switch for you C# people), but I figured it would be more cost-efficient to ask around for a better way first. So am I out of luck or is there a secret way to create a CultureInfo object using three letter names?

Steven Liekens
  • 13,266
  • 8
  • 59
  • 85
  • I don't think there is a good way to go in the opposite direction. For example, **eng** can range anywhere from **en-029** to **en-ZW**. How would you expect this to behave if you read **eng**? – myermian Mar 23 '12 at 15:00

4 Answers4

10

EDIT: sorry, I've used the wrong property:

public static CultureInfo FromISOName(string name)
{
    return CultureInfo
        .GetCultures(CultureTypes.NeutralCultures)
        .FirstOrDefault(c => c.ThreeLetterISOLanguageName == name);
}

However, there are still duplicates in the list and no support for "dut".

Balazs Tihanyi
  • 6,659
  • 5
  • 23
  • 24
  • Close, but no cigar. :( It fails when there is more than one letter code for the same language (example: both "dut" and "nld" are used for Dutch, the framework doesn't recognise "dut"). Apparently Microsoft chose to include only one letter code per language, very unfortunate. – Steven Liekens Mar 23 '12 at 15:23
  • I'll mark this as the answer as it's the closest it will get with the current framework implementation of ISO 639-2 codes. – Steven Liekens Mar 23 '12 at 16:28
  • I've discovered that there are only 21 languages that have both a bibliographic code and a terminology code. It's not too much effort to convert between the two and this method works fine after conversion. – Steven Liekens Mar 23 '12 at 16:45
2

I would go for Balazs solution, but it would be better in your case to use CultureTypes.NeutralCultures as you don't seem to be concerned with region/country data.

It would always return a single CultureInfo with no need of FirstOrDefault

user484189
  • 191
  • 5
0

Here is an extension method for the Silverlight System.Globalization.CultureInfo class, that gets the ISO 639-2 three-letter code for the language of the current System.Globalization.CultureInfo object. It uses ISO-639-2 table, that is retrieved via Utils.GetResourceStream() custom method.

The implementation also relies on a custom String.NthIndexOf() method.

public static string ThreeLetterISOLanguageName(this CultureInfo cultureInfo)
{
    const string separator = "|";

    using (var reader = new StreamReader(Utils.GetResourceStream("ISO-639-2_utf-8.txt")))
    {
        while (!reader.EndOfStream)
        {
            string line = reader.ReadLine();
            //two-letter ISO code is in the third column, i.e. after the second separator character
            string twoLetterISOCode = line.Substring(line.NthIndexOf(separator, 1) + separator.Length, 2);
            if (!twoLetterISOCode.Equals(cultureInfo.TwoLetterISOLanguageName)) continue;
            return line.Substring(0, 3);
        }
    }

    return null;
}

Full Gist

s.ermakovich
  • 2,641
  • 2
  • 26
  • 24
0

There is nothing built in that will help with such parsing.

Instead of a select, you can create a Dictionary(Of string, CultureInfo) to map from one to the other. This is more as an ease of use suggestion.

Oded
  • 489,969
  • 99
  • 883
  • 1,009