问题
EDIT: Although useful, the "duplicate" question does not give an answer to this question. First, the main theme here is Menus, so please don't mark this question duplicate to a question that is not.
I have been trying to understand correctly how to localize an application.
Right now I have a form with a label, a menu and a listbox.
I have localized the form so that now I have three resx
files.
I used Z.R.T. answer to implement the listbox to change the language on runtime. Instead of his implementation of ApplyLocalization
I used
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);
}
}
With that I can succesfully translate the label only.
Debugging the process I can see that there are three Controls: (The listbox, the label and the menu). For the listbox ApplyResources do nothing. For the label it does change the language of the label. The problem is for the menu. When c
is the menuStrip, ApplyResources
only applies it to the menuStrip, but not the menu options that are the ones that needs to be translated. (Actually the same thing happens to the listbox since the contents of the listbox are not translated either)
My question is how can I apply the resources to the internals (submenus) of a menu so that the menu contents also gets translated?
回答1:
There are a few problems in your function:
Your function is just loop over the direct child controls of the form. It's not checking all the controls in controls hierarchy. For example controls which are hosted in containers like panel are not in
Controls
collection of the form.Your function is also missing components like
ContextMenu
which are not inControls
collection of the form.The function is treating all controls in the same way, while some controls need a custom logic. The problem is not limited to
Menu
orListBox
. You need specific logic forComboBox
,ListBox
,ListView
,TreeView
,DataGridView
,ToolStrip
,ContextMenuStrip
,MenuStrip
,StatusStrip
and maybe some other controls which I forget to mention. For example you can find the logic forComboBox
in this post.
Important Note: I believe saving the selected culture in a setting and then closing and reopening the form or the whole application and applying culture before showing the form or in Main method is a better option.
Anyway, here I'll share a solution here. Be informed that the solution will not solve all the problems that I mentioned above, but solves theproblem for MenuStrip
and ToolStrip
.
While you may learn new things from the following piece of code, I assume it's just for learning purpose. In general I advise you to read the Important note again!
Step 1 - Find all items of the MenuStrip
or 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;
}
}
}
Step 2 - Create a method to get all controls:
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;
}
}
}
Step 3 - Create the ChangeLanguage
method and add the logic for different controls, for example in the following piece of code, I've added the logic for MenuStrip
which is deriving from 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);
}
}
Step 4 - Call the ChangeLanguage
method:
ChangeLanguage("fa-IR");
来源:https://stackoverflow.com/questions/52178064/winforms-localization-how-to-change-the-language-of-a-menu