C# 获取所有可用语言的编程方式(在附属程序集中)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/553244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Programmatic way to get all the available languages (in satellite assemblies)
提问by Matías
I'm designing a multilingual application using .resx files.
我正在设计一个使用 .resx 文件的多语言应用程序。
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.
我有几个文件,如 GlobalStrings.resx、GlobalStrings.es.resx、GlobalStrings.en.resx 等。当我想使用它时,我只需要设置 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.
没有任何成功。还尝试了 CultureTypes 中的所有元素,但我只得到一个包含更多我没有使用的语言的大列表,或者一个空列表。
Is there any way to get only the supported languages?
有没有办法只获得支持的语言?
采纳答案by Matías
Using what Rune Grimstad said I end up with this:
使用 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)
{
}
}
or another way
或其他方式
int pathLenght = executablePath.Length + 1;
foreach (string s in directories)
{
try
{
cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(s.Remove(0, pathLenght)));
}
catch (Exception)
{
}
}
I still don't think that this is a good idea ...
我仍然不认为这是一个好主意......
回答by Rune Grimstad
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.
我不确定如何获取语言,也许您可以扫描安装文件夹中的 dll 文件,但是将语言设置为不受支持的语言应该不是问题。
.NET will fallback to the culture neutral resources if no culture specific files can be found so you can safely select unsupported languages.
如果找不到特定于文化的文件,.NET 将回退到文化中性资源,以便您可以安全地选择不受支持的语言。
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"
只要您自己控制应用程序,您就可以将可用语言存储在某个应用程序设置中。只是一个带有文化名称的逗号分隔的字符串就足够了:“en, es”
回答by Hans Holzbart
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.");
}
}
回答by George Birbilis
based on answer by @hans-holzbart but fixed to not return the InvariantCulture too and wrapped into a reusable method:
基于@hans-holzbart 的回答,但已修复为不返回 InvariantCulture 并包装为可重用的方法:
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:
使用该方法,您可以使用以下内容获取要添加到某些 ComboBox 的字符串列表:
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;
}
回答by Ankush Madankar
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.
这将是基于以下声明的解决方案之一:
特定语言的每个附属程序集都具有相同的名称,但位于以特定文化命名的子文件夹中,例如 fr 或 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)));
}
回答by Tiago Freitas Leal
@"Ankush Madankar" presents an interesting starting point but it has two problems: 1) Finds also resource folders for resources of refrenced assemblies 2) Doesn find the resource for the base assembly language
@"Ankush Madankar" 提出了一个有趣的起点,但它有两个问题:1) 还查找引用程序集资源的资源文件夹 2) 找不到基本汇编语言的资源
I won't try to solve issue 2) but for issue 1) the code should be
我不会尝试解决问题 2) 但对于问题 1) 代码应该是
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();
}
回答by crokusek
A generic answer where the resource type to search is specified. Uses reflection but is cached.
指定要搜索的资源类型的通用答案。使用反射但被缓存。
Usage:
用法:
List<string> comboBoxEntries = CommonUtil.CulturesOfResource<GlobalStrings>()
.Select(cultureInfo => cultureInfo.NativeName)
.ToList();
Implementation (Utility Class):
实现(实用程序类):
static ConcurrentDictionary<Type, List<CultureInfo>> __resourceCultures = new ConcurrentDictionary<Type, List<CultureInfo>>();
/// <summary>
/// Return the list of cultures that is supported by a Resource Assembly (usually collection of resx files).
/// </summary>
static public List<CultureInfo> CulturesOfResource<T>()
{
return __resourceCultures.GetOrAdd(typeof(T), (t) =>
{
ResourceManager manager = new ResourceManager(t);
return CultureInfo.GetCultures(CultureTypes.AllCultures)
.Where(c => !c.Equals(CultureInfo.InvariantCulture) &&
manager.GetResourceSet(c, true, false) != null)
.ToList();
});
}
It may suffer the same issue with the accepted answer in that all the language resources will probably be loaded.
它可能会遇到与接受的答案相同的问题,因为可能会加载所有语言资源。