问题
One level up from this question, what would be the way to store all (and loop through) available resources and associated cultures, to allow user selection of a specific culture?
Further explanation:
Suppose three resource files:
- GUILanguage.resx
- GUILanguage.fr.resx
- GUILanguage.it.resx
I could have a string in each called LanguageName
. How would I be able to programmatically loop through the different LanguageName
values to list them (in say a list box)?
EDIT: WinForms project, embedded resources.
回答1:
Here is a solution I think works for 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;
}
}
And here is how you would use it for a WindowsFormsApplication1:
List<CultureInfo> cultures = new List<CultureInfo>(EnumSatelliteLanguages("WindowsFormsApplication1.GUILanguage"));
回答2:
Assuming you have a ListBox named ListBox1
and your resource files named Resource.resx
, Resource.es.resx
, etc.:
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;
}
}
}
回答3:
Here is a method to return an IEnumerable of string with the values from the resource files, with an example usage. You just pass in the command part of the resource name and the key from the resources that you want.
[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));
}
来源:https://stackoverflow.com/questions/5112828/loop-through-embedded-resources-of-different-languages-cultures-in-c-sharp