Цикл по встроенным ресурсам разных языков / культур в C # - PullRequest
7 голосов
/ 25 февраля 2011

На один уровень выше в этом вопросе , каким будет способ хранения всех (и циклически проходящих) доступных ресурсов и связанных культур, чтобы позволить пользователю выбрать конкретную культуру?

Дальнейшее объяснение:

Предположим, три файла ресурсов:

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

Я мог бы иметь строку в каждом названную LanguageName. Как бы я мог программно перебирать различные значения LanguageName для их перечисления (скажем, в списке)?

РЕДАКТИРОВАТЬ: проект WinForms, встроенные ресурсы.

Ответы [ 3 ]

8 голосов
/ 04 марта 2011

Вот решение, которое, я думаю, работает для 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"));
4 голосов
/ 25 февраля 2011

Предполагая, что у вас есть ListBox с именем ListBox1 и ваши файлы ресурсов с именами 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;
        }
    }
}
1 голос
/ 03 марта 2011

Вот метод, возвращающий 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));
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...