Pregunta

Estoy diseñando una aplicación multilingüe utilizando Resx archivos.

Tengo un par de archivos como GlobalStrings.resx, GlobalStrings.es.resx, GlobalStrings.en.resx, etc. Cuando quiero usar esto, sólo hay que establecer Thread.CurrentThread.CurrentCulture.

El problema: Tengo un cuadro combinado con todos los idiomas disponibles, pero estoy cargando manualmente:

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

He tratado con

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

sin ningún éxito. También intentado con todos los elementos de CultureTypes, pero yo sólo estoy haciendo una gran lista con muchos más idiomas que no estoy utilizando, o una lista vacía.

¿Hay alguna manera de obtener sólo los idiomas soportados?

¿Fue útil?

Solución 5

Usando lo Rune Grimstad dijo 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)
    {

    }
}

Yo todavía no creo que esto es una buena idea ...

Otros consejos

Puede crear una lista programáticamente las culturas disponibles en la 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.");
    }
}

basado en la respuesta por @ Hans-holzbart pero fijo que no devuelve la InvariantCulture demasiado 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;
}

utilizando ese método, se puede obtener una lista de cadenas para agregar a algunos 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;
}

Esta sería una de solución en base a la declaración siguiente:
Cada conjunto de satélites para un idioma específico tiene el mismo nombre, pero se encuentra en una subcarpeta 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)));
}

No estoy seguro acerca de cómo obtener los idiomas, tal vez se puede escanear la carpeta de instalación de archivos dll, pero el establecimiento de su idioma a un idioma no no debería ser un problema.

.NET se replegará para los recursos neutros cultura si no hay archivos específicos de cultivo se pueden encontrar para que pueda seleccionar de forma segura idiomas no compatibles.

Mientras se controla la aplicación a sí mismo que sólo podía almacenar los idiomas disponibles en un entorno en algún lugar de la aplicación. Sólo una cadena separada por comas con los nombres de cultivo debería ser suficiente: "en, es"

@ "Ankush Madankar" presenta un punto de partida interesante pero tiene dos problemas: 1) también encuentra recursos carpetas de recursos de asambleas refrenced 2) Doesn encontrar los recursos para el lenguaje de ensamblaje de la base

No voy a tratar de resolver el problema 2), pero para su emisión 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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top