从this question向上一级,存储所有(并循环)可用资源和相关文化的方式是什么,以允许用户选择特定文化?
进一步解释:
假设有三个资源文件:
我可以在每个名为LanguageName
的字符串中添加一个字符串。我如何能够以编程方式循环遍历不同的LanguageName
值以列出它们(在列表框中)?
编辑:WinForms项目,嵌入式资源。
答案 0 :(得分:8)
这是我认为适用于Winforms的解决方案:
// get cultures for a specific resource info
public static IEnumerable<CultureInfo> EnumSatelliteLanguages(string baseName)
{
if (baseName == null)
throw new ArgumentNullException("baseName");
ResourceManager manager = new ResourceManager(baseName, Assembly.GetExecutingAssembly());
ResourceSet set = manager.GetResourceSet(CultureInfo.InvariantCulture, true, false);
if (set != null)
yield return CultureInfo.InvariantCulture;
foreach (CultureInfo culture in EnumSatelliteLanguages())
{
set = manager.GetResourceSet(culture, true, false);
if (set != null)
yield return culture;
}
}
// determine what assemblies are available
public static IEnumerable<CultureInfo> EnumSatelliteLanguages()
{
foreach (string directory in Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory))
{
string name = Path.GetFileNameWithoutExtension(directory); // resource dir don't have an extension...
// format is XX or XX-something, we discard directories that can't match.
// could/should be replaced by a regex but we still need to catch cultures errors...
if (name.Length < 2)
continue;
if (name.Length > 2 && name[2] != '-')
continue;
CultureInfo culture = null;
try
{
culture = CultureInfo.GetCultureInfo(name);
}
catch
{
// not a good directory...
continue;
}
string resName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location) + ".resources.dll";
if (File.Exists(Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name), resName)))
yield return culture;
}
}
以下是如何将它用于WindowsFormsApplication1:
List<CultureInfo> cultures = new List<CultureInfo>(EnumSatelliteLanguages("WindowsFormsApplication1.GUILanguage"));
答案 1 :(得分:4)
假设您有一个名为ListBox1
的ListBox,以及名为Resource.resx
,Resource.es.resx
等的资源文件:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web.UI.WebControls;
using Resources;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (ListBox1.Items.Count < 1)
{
var installedCultures = GetInstalledCultures();
IEnumerable<ListItem> listItems = installedCultures.Select(cultInfo =>
new ListItem(Resource.ResourceManager.GetString("LanguageName", cultInfo), cultInfo.Name));
ListBox1.Items.AddRange(listItems.ToArray());
}
}
public IEnumerable<CultureInfo> GetInstalledCultures()
{
foreach (string file in Directory.GetFiles(Server.MapPath("~/App_GlobalResources"), "*.resx"))
{
if (!file.EndsWith(".resx"))
continue;
var endCropPos = file.Length - ".resx".Length;
var beginCropPos = file.LastIndexOf(".", endCropPos - 1) + 1;
string culture = "en";
if (beginCropPos > 0 && file.LastIndexOf("\\") < beginCropPos)
culture = file.Substring(beginCropPos, endCropPos - beginCropPos);
yield return new CultureInfo(culture);
}
}
// override to set the Culture with the ListBox1 (use AutoPostBack="True")
protected override void InitializeCulture()
{
base.InitializeCulture();
var cult = Request["ctl00$MainContent$ListBox1"];
if (cult != null)
{
Culture = cult;
UICulture = cult;
}
}
}
答案 2 :(得分:1)
这是一个使用资源文件中的值返回IEnumerable字符串的方法,以及示例用法。您只需传入资源名称的命令部分和您想要的资源中的密钥。
[Test]
public void getLanguageNames()
{
var names = GetResourceLanguageNames(Assembly.GetExecutingAssembly(), "GUILanguage", "LanguageName");
Console.WriteLine(string.Join("-",names));
}
public IEnumerable<string> GetResourceLanguageNames(Assembly assembly, string resourceName, string key)
{
var regex = new Regex(string.Format(@"(\w)?{0}(\.\w+)?", resourceName));
var matchingResources = assembly.GetManifestResourceNames()
.Where(n => regex.IsMatch(n)).Select(rn=>rn.Remove(rn.LastIndexOf(".")));
return matchingResources.Select(rn => new ResourceManager(rn, assembly).GetString(key));
}