Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatic way to get all the available languages (in satellite assemblies)

I'm designing a multilingual application using .resx files.

I have a few files like GlobalStrings.resx, GlobalStrings.es.resx, GlobalStrings.en.resx, etc. When I want to use this, I just need to set Thread.CurrentThread.CurrentCulture.

The problem: I have a combobox with all the available languages, but I'm loading this manually:

comboLanguage.Items.Add(CultureInfo.GetCultureInfo("en"));
comboLanguage.Items.Add(CultureInfo.GetCultureInfo("es"));

I've tried with

cmbLanguage.Items.AddRange(CultureInfo.GetCultures(CultureTypes.UserCustomCulture));

without any success. Also tried with all the elements in CultureTypes, but I'm only getting a big list with a lot more languages that I'm not using, or an empty list.

Is there any way to get only the supported languages?

like image 804
Tute Avatar asked Feb 16 '09 13:02

Tute


4 Answers

You can programatically list the cultures available in your application

// Pass the class name of your resources as a parameter e.g. MyResources for MyResources.resx
ResourceManager rm = new ResourceManager(typeof(MyResources));

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
foreach (CultureInfo culture in cultures)
{
    try
    {
        ResourceSet rs = rm.GetResourceSet(culture, true, false);
        // or ResourceSet rs = rm.GetResourceSet(new CultureInfo(culture.TwoLetterISOLanguageName), true, false);
        string isSupported = (rs == null) ? " is not supported" : " is supported";
        Console.WriteLine(culture + isSupported);
    }
    catch (CultureNotFoundException exc)
    {
        Console.WriteLine(culture + " is not available on the machine or is an invalid culture identifier.");
    }
}
like image 193
Hans Holzbart Avatar answered Oct 14 '22 17:10

Hans Holzbart


based on answer by @hans-holzbart but fixed to not return the InvariantCulture too and wrapped into a reusable method:

public static IEnumerable<CultureInfo> GetAvailableCultures()
{
  List<CultureInfo> result = new List<CultureInfo>();

  ResourceManager rm = new ResourceManager(typeof(Resources));

  CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
  foreach (CultureInfo culture in cultures)
  {
    try
    {
      if (culture.Equals(CultureInfo.InvariantCulture)) continue; //do not use "==", won't work

      ResourceSet rs = rm.GetResourceSet(culture, true, false);
      if (rs != null)
        result.Add(culture);
    }
    catch (CultureNotFoundException)
    {
      //NOP
    }
  }
  return result;
}

using that method, you can get a list of strings to add to some ComboBox with the following:

public static ObservableCollection<string> GetAvailableLanguages()
{
  var languages = new ObservableCollection<string>();
  var cultures = GetAvailableCultures();
  foreach (CultureInfo culture in cultures)
    languages.Add(culture.NativeName + " (" + culture.EnglishName + " [" + culture.TwoLetterISOLanguageName + "])");
  return languages;
}
like image 5
George Birbilis Avatar answered Oct 14 '22 16:10

George Birbilis


This would be one of solution on basis of following statement:
Each satellite assembly for a specific language is named the same but lies in a sub-folder named after the specific culture e.g. fr or fr-CA.

public IEnumerable<CultureInfo> GetSupportedCulture()
{
    //Get all culture 
    CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures);

    //Find the location where application installed.
    string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path));

    //Return all culture for which satellite folder found with culture code.
    return culture.Where(cultureInfo => Directory.Exists(Path.Combine(exeLocation, cultureInfo.Name)));
}
like image 4
Ankush Madankar Avatar answered Oct 14 '22 16:10

Ankush Madankar


I'm not sure about getting the languages, maybe you can scan your installation folder for dll-files, but setting your language to an unsupported language should not be a problem.

.NET will fallback to the culture neutral resources if no culture specific files can be found so you can safely select unsupported languages.

As long as you control the application yourself you could just store the available languages in a application setting somewhere. Just a comma-separated string with the culture names should suffice: "en, es"

like image 2
Rune Grimstad Avatar answered Oct 14 '22 15:10

Rune Grimstad