以编程方式获取所有可用语言(在卫星assembly中)

我正在使用.resx文件设计一个多语言应用程序。

我有一些文件,如GlobalStrings.resx,GlobalStrings.es.resx,GlobalStrings.en.resx等。当我想使用它时,我只需要设置Thread.CurrentThread.CurrentCulture。

问题:我有一个包含所有可用语言的combobox,但我手动加载:

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

我试过了

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

没有任何成功。 还尝试了CultureTypes中的所有元素,但是我只获得了一个包含更多我不使用的语言的大列表,或者是一个空列表。

有没有办法只获得支持的语言?

您可以以编程方式列出应用程序中可用的文化

 // Pass the class name of your resources as a parameter eg 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."); } } 

这将是基于以下声明的解决方案之一:
用于特定语言的每个附属程序集命名相同,但位于以特定文化命名的子文件夹中,例如fr或fr-CA。

 public IEnumerable 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))); } 

根据@ hans-holzbart的回答,但修复不返回InvariantCulture并包装成可重用的方法:

 public static IEnumerable GetAvailableCultures() { List result = new List(); 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; } 

使用该方法,您可以获得要添加到某些ComboBox的字符串列表,其中包含以下内容:

 public static ObservableCollection GetAvailableLanguages() { var languages = new ObservableCollection(); var cultures = GetAvailableCultures(); foreach (CultureInfo culture in cultures) languages.Add(culture.NativeName + " (" + culture.EnglishName + " [" + culture.TwoLetterISOLanguageName + "])"); return languages; } 

我不确定获取语言,也许您可​​以扫描安装文件夹中的dll文件,但将语言设置为不受支持的语言应该不是问题。

如果找不到特定于文化的文件,.NET将回退到文化中立资源,因此您可以安全地选择不受支持的语言。

只要您自己控制应用程序,您就可以将可用语言存储在某个应用程序设置中。 只需一个逗号分隔的字符串和文化名称就足够了:“en,es”

使用Rune Grimstad所说的最终我得到了这个:

 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) { } } 

或另一种方式

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

我仍然认为这不是一个好主意……

@“Ankush Madankar”提出了一个有趣的起点,但它有两个问题:1)查找refrenced程序集资源的资源文件夹2)找不到基本汇编语言的资源

我不会尝试解决问题2)但问题1)代码应该是

 public List 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(); }