Локализация WinForms. Как изменить язык меню - PullRequest
0 голосов
/ 05 сентября 2018

РЕДАКТИРОВАТЬ: хотя это полезно, «дубликат» вопрос не дает ответа на этот вопрос. Во-первых, основной темой здесь является Меню , поэтому, пожалуйста, не отмечайте этот вопрос как дубликат вопроса, который не является.

Я пытался правильно понять, как локализовать приложение. Прямо сейчас у меня есть форма с меткой, меню и списком. Я локализовал форму так, что теперь у меня есть три resx файла.

Я использовал Z.R.T. ответ , чтобы реализовать список для изменения языка во время выполнения. Вместо его реализации ApplyLocalization я использовал

 public void ApplyLocalization(CultureInfo ci)
   {
    //button1.Text = Properties.Resources.button;
    ComponentResourceManager componentResourceManager = new ComponentResourceManager(this.GetType());

    foreach (Control c in this.Controls)
      {
       componentResourceManager.ApplyResources(c, c.Name, ci);
       }

    }

С этим я могу только успешно перевести этикетку.

Отладка процесса Я вижу, что есть три элемента управления: (список, метка и меню). Для списка ApplyResources ничего не делать. Для метки это меняет язык метки. Проблема в меню. Когда c является menuStrip, ApplyResources применяет его только к menuStrip, но не к тем пунктам меню, которые необходимо перевести. (На самом деле то же самое происходит со списком, так как содержимое списка тоже не переводится)

Мой вопрос: как я могу применить ресурсы к внутренним элементам (подменю) меню , чтобы содержимое меню также переводилось?

1 Ответ

0 голосов
/ 05 сентября 2018

В вашей функции есть несколько проблем:

  • Ваша функция находится в цикле над прямыми дочерними элементами управления формы. Это не проверка всех элементов управления в иерархии элементов управления. Например, элементы управления, которые размещены в контейнерах, таких как панель, не находятся в Controls коллекции формы.

  • В вашей функции также отсутствуют такие компоненты, как ContextMenu, которых нет в Controls коллекции формы.

  • Функция обрабатывает все элементы управления одинаково, в то время как для некоторых элементов управления требуется пользовательская логика. Проблема не ограничивается Menu или ListBox. Вам нужна специальная логика для ComboBox, ListBox, ListView, TreeView, DataGridView, ToolStrip, ContextMenuStrip, MenuStrip, StatusStrip и, возможно, некоторых других элементов управления, которые я забыл упомянуть , Например, вы можете найти логику для ComboBox в этой записи .

Важное примечание: Я считаю, что сохранение выбранной культуры в настройке и затем закрытие и повторное открытие формы или всего приложения и применение культуры перед показом формы или в методе Main лучший вариант.

В любом случае, здесь я поделюсь решением здесь. Имейте в виду, что решение не решит все проблемы, которые я упомянул выше, но решит проблему для MenuStrip и ToolStrip.

Хотя вы можете узнать что-то новое из следующего фрагмента кода, я предполагаю, что это просто для целей обучения. В общем, советую еще раз прочитать Важную заметку!

Шаг 1 - Найти все предметы из MenuStrip или ToolStrip:

using System.Collections.Generic;
using System.Windows.Forms;
public static class ToolStripExtensions
{
    public static IEnumerable<ToolStripItem> AllItems(this ToolStrip toolStrip)
    {
        return toolStrip.Items.Flatten();
    }
    public static IEnumerable<ToolStripItem> Flatten(this ToolStripItemCollection items)
    {
        foreach (ToolStripItem item in items)
        {
            if (item is ToolStripDropDownItem)
                foreach (ToolStripItem subitem in 
                    ((ToolStripDropDownItem)item).DropDownItems.Flatten())
                        yield return subitem;
            yield return item;
        }
    }
}

Шаг 2 - Создать метод для получения всех элементов управления:

using System.Collections.Generic;
using System.Windows.Forms;
public static class ControlExtensions
{
    public static IEnumerable<Control> AllControls(this Control control)
    {
        foreach (Control c in control.Controls)
        {
            yield return c;
            foreach (Control child in c.Controls)
                yield return child;
        }
    }
}

Шаг 3 - Создайте метод ChangeLanguage и добавьте логику для различных элементов управления, например, в следующем фрагменте кода я добавил логику для MenuStrip, которая является производной от ToolStrip

private void ChangeLanguage(string lang)
{
    var rm = new ComponentResourceManager(this.GetType());
    var culture = CultureInfo.CreateSpecificCulture(lang);
    Thread.CurrentThread.CurrentCulture = culture;
    Thread.CurrentThread.CurrentUICulture = culture;
    foreach (Control c in this.AllControls())
    {
        if (c is ToolStrip)
        {
            var items = ((ToolStrip)c).AllItems().ToList();
            foreach (var item in items)
                rm.ApplyResources(item, item.Name);
        }
        rm.ApplyResources(c, c.Name);
    }
}

Шаг 4 - Вызовите метод ChangeLanguage:

ChangeLanguage("fa-IR");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...