Forma programática de obtener todos los idiomas disponibles (en ensamblajes satelitales)


Estoy diseñando una aplicación multilingüe usando .archivos resx.

Tengo algunos archivos como GlobalStrings.resx, GlobalStrings.es.resx, GlobalStrings.en.resx, etc. Cuando quiero usar esto, solo necesito establecer el hilo.Hilo actual.Cultura actual.

El problema: Tengo un combobox con todos los idiomas disponibles, pero estoy cargando esto manualmente:

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

He intentado con

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

Sin ningún éxito. También probado con todos los elementos en CultureTypes, pero estoy solo obtener una lista grande con muchos más idiomas que no estoy usando, o una lista vacía.

¿Hay alguna forma de obtener solo los idiomas soportados?

Author: Peter Mortensen, 2009-02-16

6 answers

Puede listar programáticamente las culturas disponibles en su aplicación

// 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.");
    }
}
 40
Author: Hans Holzbart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-15 09:21:16

Esto sería uno de solución sobre la base de la siguiente declaración:
Cada ensamblaje de satélite para un lenguaje específico se denomina igual, pero se encuentra en una subcarpeta con el nombre de la cultura específica, por ejemplo, fr o 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)));
}
 4
Author: Ankush Madankar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 07:20:59

Basado en la respuesta de @ hans-holzbart pero arreglado para no devolver la cultura invariante también y envuelto en un método reutilizable:

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;
}

Usando ese método, puede obtener una lista de cadenas para agregar a algún ComboBox con lo siguiente:

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;
}
 3
Author: George Birbilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-22 22:57:02

No estoy seguro de obtener los idiomas, tal vez pueda escanear su carpeta de instalación en busca de archivos dll, pero configurar su idioma en un idioma no compatible no debería ser un problema.

. NET recurrirá a los recursos neutrales de cultura si no se pueden encontrar archivos específicos de cultura para que pueda seleccionar de forma segura idiomas no compatibles.

Siempre que controle la aplicación usted mismo, podría almacenar los idiomas disponibles en una configuración de aplicación en algún lugar. Sólo un la cadena separada por comas con los nombres de la cultura debería ser suficiente:"en, es"

 2
Author: Rune Grimstad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-16 13:12:35

Usando lo que dijo Rune Grimstad termino con esto:

string executablePath = Path.GetDirectoryName(Application.ExecutablePath);
string[] directories = Directory.GetDirectories(executablePath);
foreach (string s in directories)
{
    try
    {
        DirectoryInfo langDirectory = new DirectoryInfo(s);
        cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(langDirectory.Name));
    }
    catch (Exception)
    {

    }
}

O de otra manera

int pathLenght = executablePath.Length + 1;
foreach (string s in directories)
{
    try
    {
        cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(s.Remove(0, pathLenght)));
    }
    catch (Exception)
    {

    }
}

Todavía no creo que esto sea una buena idea ...

 1
Author: Matías,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-16 21:46:08

@ "Ankush Madankar" presenta un punto de partida interesante pero tiene dos problemas: 1) Encuentra también carpetas de recursos para recursos de ensamblados refrenados 2) Encuentra el recurso para el lenguaje ensamblador base

No intentaré resolver el problema 2) pero para el problema 1) el código debería ser

public List<CultureInfo> GetSupportedCultures()
{
    CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures);

    // get the assembly
    Assembly assembly = Assembly.GetExecutingAssembly();

    //Find the location of the assembly
    string assemblyLocation =
        Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(assembly.CodeBase).Path));

    //Find the file anme of the assembly
    string resourceFilename = Path.GetFileNameWithoutExtension(assembly.Location) + ".resources.dll";

    //Return all culture for which satellite folder found with culture code.
    return culture.Where(cultureInfo =>
        assemblyLocation != null &&
        Directory.Exists(Path.Combine(assemblyLocation, cultureInfo.Name)) &&
        File.Exists(Path.Combine(assemblyLocation, cultureInfo.Name, resourceFilename))
    ).ToList();
}
 0
Author: Tiago Freitas Leal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-05 12:12:45