我正在使用.resx文件设计多语言应用程序。
我有一些文件,如GlobalStrings.resx,GlobalStrings.es.resx,GlobalStrings.en.resx等。 当我想使用它时,我只需要设置Thread.CurrentThread.CurrentCulture。
问题: 我有一个包含所有可用语言的组合框,但我手动加载:
comboLanguage.Items.Add(CultureInfo.GetCultureInfo("en"));
comboLanguage.Items.Add(CultureInfo.GetCultureInfo("es"));
我试过
cmbLanguage.Items.AddRange(CultureInfo.GetCultures(CultureTypes.UserCustomCulture));
没有任何成功。还尝试了CultureTypes中的所有元素,但我只是得到了一个包含更多我不使用的语言的大列表,或者是一个空列表。
有没有办法只获得支持的语言?
答案 0 :(得分:47)
您可以以编程方式列出应用程序中可用的文化
// 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.");
}
}
答案 1 :(得分:4)
基于@ 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;
}
使用该方法,您可以获得要添加到某个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;
}
答案 2 :(得分:4)
这将是基于以下陈述的解决方案之一:
特定语言的每个附属程序集都命名相同,但位于以特定文化命名的子文件夹中,例如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)));
}
答案 3 :(得分:2)
我不确定获取语言,也许您可以扫描安装文件夹中的dll文件,但是将语言设置为不受支持的语言应该不是问题。
如果找不到特定于文化的文件,.NET将回退到文化中性资源,因此您可以安全地选择不受支持的语言。只要您自己控制应用程序,就可以将可用语言存储在某个应用程序设置中。只需一个逗号分隔的字符串和文化名称就足够了:“en,es”
答案 4 :(得分:2)
使用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)
{
}
}
我仍然认为这不是一个好主意......
答案 5 :(得分:0)
@“Ankush Madankar”提出了一个有趣的起点,但它有两个问题: 1)还查找refrenced程序集资源的资源文件夹 2)找不到基本汇编语言的资源
我不会尝试解决问题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();
}
答案 6 :(得分:0)
一个通用答案,其中指定了要搜索的资源类型。使用反射但已缓存。
用法:
List<string> comboBoxEntries = CommonUtil.CulturesOfResource<GlobalStrings>()
.Select(cultureInfo => cultureInfo.NativeName)
.ToList();
实施(实用程序类):
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();
});
}
接受的答案可能会遇到相同的问题,因为可能会加载所有语言资源。
答案 7 :(得分:0)
1. 获取用户首选的语言集,按偏好顺序排列:
Windows.System.UserProfile.GlobalizationPreferences.Languages;
2. 获取或设置此上下文(应用程序)的语言限定符:
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Languages;
两者都是 List<string>
。