Loop through embedded resources of different languages/cultures in C#

ε祈祈猫儿з 提交于 2019-12-04 05:44:24

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"));

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;
        }
    }
}

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));
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!