在C#中循环使用不同语言/文化的嵌入式资源

从这个问题的一个层面来看,存储所有(并循环)可用资源和相关文化的方式是什么,以允许用户选择特定文化?

进一步说明:

假设有三个资源文件:

  • GUILanguage.resx
  • GUILanguage.fr.resx
  • GUILanguage.it.resx

我可以在每个名为LanguageName的字符串中有一个字符串。 我如何能够以编程方式循环遍历不同的LanguageName值以列出它们(例如列表框)?

编辑:WinForms项目,嵌入式资源。

这是我认为适用于Winforms的解决方案:

 // get cultures for a specific resource info public static IEnumerable 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 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 cultures = new List(EnumSatelliteLanguages("WindowsFormsApplication1.GUILanguage")); 

假设您有一个名为ListBox1的ListBox,并且您的资源文件名为Resource.resxResource.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 listItems = installedCultures.Select(cultInfo => new ListItem(Resource.ResourceManager.GetString("LanguageName", cultInfo), cultInfo.Name)); ListBox1.Items.AddRange(listItems.ToArray()); } } public IEnumerable 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; } } } 

这是一个使用示例用法返回带有资源文件中的值的IEnumerable字符串的方法。 您只需从您想要的资源传入资源名称的命令部分和密钥。

 [Test] public void getLanguageNames() { var names = GetResourceLanguageNames(Assembly.GetExecutingAssembly(), "GUILanguage", "LanguageName"); Console.WriteLine(string.Join("-",names)); } public IEnumerable 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)); }