SoFunction
Updated on 2025-03-07

Share two solutions to implement multilingual support for Winform programs

Due to the company's business needs, the original ERP system needs to be added to support traditional languages, but the original encoding method cannot be changed, that is, ordinary programmers cannot feel the difference in encoding. After repeated communication with several colleagues, I determined the following two solutions:

Plan 1:Every time a form is loaded and displayed in the form base class, the control containing text display will be automatically recursively traversed (Button, CheckBox, GroupBox, Label, LinkLabel, TextBox, StatusStrip, TabPage, ToolStrip, RadioButton, DateTimePicker, DataGridView, CheckedListBox, TreeView, MenuStrip), and the simple and traditional conversion method is called according to the text attributes of different control types to convert and reset the content of the new corresponding text attribute (such as: Traditional Chinese content)

Advantages: Simple encoding and has no effect on the encoding of ordinary programmers (except for the base class of the form class to change from Form class to MyStyleFormBase class);

Disadvantages: Because each time you open a form, you need to traverse the controls and perform simple and traditional conversions, if there are many controls on the interface, it may lead to slow opening of the form, affecting the user experience. The text content of the sub-control needs to be manually notified by the programmer, and it cannot be automatically perceived and converted.

The specific implementation ideas are as follows:

1. Secondary encapsulation (inheritance) of the Form class, define a MyStyleFormBase class, and add it to it every time the form type is loaded and displayed, it will automatically traverse the control containing text display, and call the simplified and traditional Chinese conversion method according to the text properties of different control types to convert and reset the content of the new corresponding text attributes. In this way, when all forms inherit the MyStyleFormBase class, the traversal and conversion process is implemented by default. Programmers do not need to encode again, or even know that there is a traversal and conversion process, thereby improving the reusability of the code. The specific code is as follows:

public class MyStyleFormBase : Form

{

 public MyStyleFormBase()

 {

 if (!("zh-CHS", )) //If it is simplified, no conversion is required
 {

  += MyStyleFormBase_TextChanged;

  += MyStyleFormBase_Shown;

 }

 }

 

 private void MyStyleFormBase_TextChanged(object sender, EventArgs e)

 {

  = ();

 }

 

 private void MyStyleFormBase_Shown(object sender, EventArgs e)

 {

 (this);

  += MyStyleFormBase_ControlAdded;

 }

 

 private void MyStyleFormBase_ControlAdded(object sender, ControlEventArgs e)

 {

 ();

 }

 

 /// <summary>

 /// Force notification of child control changes message
 /// </summary>

 /// <param name="target"></param>

 protected virtual void PerformChildrenChange(Control target)

 {

 (target);

 }

 

 /// <summary>

 /// pop-up message box
 /// </summary>

 /// <param name="text"></param>

 /// <param name="caption"></param>

 /// <param name="buttons"></param>

 /// <param name="icon"></param>

 /// <param name="defaultButton"></param>

 /// <returns></returns>

 protected DialogResult MessageBoxShow(string text, string caption, MessageBoxButtons buttons = , MessageBoxIcon icon = , MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)

 {

 return ((text), (caption), buttons, icon, defaultButton);

 }

} 

Brief description of code logic:

1. When the current UI cultural area is not Chinese simplified (because this program itself is developed based on simplified Chinese), subscribe to the form display event Shown and form title change event TextChanged. Function: When the form is displayed, the control will be traversed and converted to traditional Chinese, and when the title text changes, it will be automatically converted to traditional Chinese;

2. When the form is displayed, the controls that subscribe to the form add event ControlAdded. Function: When the form is displayed, if there is subsequent code to add controls, the control and its subcontrols will be automatically converted into traditional Chinese to ensure that no one is missing;

3. Add a message prompt box method, with the purpose of converting simplified text into traditional text before popping up the message window;

4. Add a method that forces the subcontrol to change messages PerformChildrenChange. When the text content of a control or the addition of subcontrol occurs, the form itself cannot be captured, so the method needs to be called to traverse and convert the text content of the subcontrol; (I feel that it is not good here, but there is no better way at present. If you have a better way, please leave a message and comment)

2. LanguageHelper: LanguageHelper converts public classes (currently only supports simplified and traditional Chinese conversion, depending on:) The code is as follows:

Because the code is too long, pleaseClick to download

The logic of this class is very simple, starting from a parent control, traversing all child controls, and converting the corresponding text content of the control into simplified or traditional Chinese according to different control types. Call method: SetControlLanguageText

The above two steps have implemented the support of multilingual languages ​​(to be precise, simple and traditional Chinese conversion). It is very simple to apply to the project. Just change the default base class Form of the form to: MyStyleFormBase, such as: public partial class FormTest: MyStyleFormBase

Plan 2:The control directly implements the conversion of each control by itself based on the current area information + cached language dictionary.

Advantages: No traversal is required, and each control converts itself according to the region information, so it is more efficient and has no effect on the encoding of ordinary programmers (except for the base class of the form class to change from Form class to MyStyleFormBase class, it is also necessary to use multilingual controls. These controls are encapsulated by ordinary controls twice, retaining all original attributes and events);

Disadvantages: All controls with text display (such as: Button, CheckBox, GroupBox, Label, LinkLabel, TextBox, StatusStrip, TabPage, ToolStrip, RadioButton, DateTimePicker, DataGridView, CheckedListBox, TreeView) need to be secondary encapsulated, and the control is uniformly named as: MyStyleXXX

There are many controls involved and the encoding is relatively complex;

The specific implementation ideas are as follows:

1. Secondary encapsulation (inheritance) of the Form class and define a MyStyleFormBase class. When modifying the form title, it can automatically perform multilingual conversion functions. The specific code is as follows:

public partial class MyStyleFormBase : Form

{ 
 public MyStyleFormBase()
 {
  += MyStyleFormBase_TextChanged;
 } 
 private void MyStyleFormBase_TextChanged(object sender, EventArgs e)

 {
 if (!())
 {  = (); }
 }
 /// <summary>
 /// pop-up message box /// </summary>
 /// <param name="text"></param>
 /// <param name="caption"></param>
 /// <param name="buttons"></param>
 /// <param name="icon"></param>
 /// <param name="defaultButton"></param>
 /// <returns></returns>
 protected DialogResult MessageBoxShow(string text, string caption = "hint", MessageBoxButtons buttons = , MessageBoxIcon icon = , MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)

 {
 if (!())

 {

 text = (text);
 caption = (caption);
 }
 return (text, caption, buttons, icon, defaultButton);
 }
} 

The code logic is very simple, it is to subscribe to an event so that when it is judged that it is not simplified based on IsChsLanguage (judging whether it is simplified mode), it needs to be converted.

2. Define multi-language support for ordinary controls and container control interfaces (IMultiLanguageControl, IMultiLanguageContainerControl). The specific code is as follows: (This is just for the purpose of making a specification, and supports manual setting of the text content of the conversion control)

/// <summary>
/// Supports multilingual ordinary controls (childless controls)/// </summary>
public interface IMultiLanguageControl
{
 string DefaultLangText { get; } 
 string CurrentLangText { get; set; }
}
/// <summary>
/// Support multilingual container controls (including child controls)/// </summary>
public interface IMultiLanguageContainerControl
{
 Dictionary<object, string> DefaultLangTexts { get; } 
 Dictionary<object, string> CurrentLangTexts { get; set; } 
 Control this[string ctrlName] { get; set; }
 void SetItemCurrentLangText(string ctrlName, string langText);
event EventHandler<ChildrenAddedEventArgs> ChildrenChanged;
}
public class ChildrenAddedEventArgs : EventArgs

{
 public Dictionary<object, string> LangTexts { get; private set; }
 public ChildrenAddedEventArgs()
 {
 LangTexts = new Dictionary<object, string>();

 }
 public ChildrenAddedEventArgs(Dictionary<object, string> langTexts)

 {  = langTexts; }

 public string this[object key]
 {get
 {
return LangTexts[key];
 }
set
 {
 LangTexts[key] = value;
 } }} 

3. Implement support for multilingual ordinary controls: secondary encapsulation is performed based on the original standard controls (Button, CheckBox, GroupBox, Label, LinkLabel, TextBox, RadioButton, DateTimePicker), and implement the IMultiLanguageControl interface. The codes of each control are as follows:

The following is the MyStyleButton definition code. The implementation codes in MyStyleCheckBox, MyStyleGroupBox, MyStyleLabel, MyStyleLinkLabel, MyStyleTextBox, and MyStyleRadioButton are the same.

public partial class MyStyleButton : MyButton, IMultiLanguageControl

 {
 static Dictionary<string, string> LanDict = new Dictionary<string, string>();
 public MyStyleButton()
 { }

 public override string Text

 {

 get

 {

 if (!DesignMode &&  != "zh-CHS")
 {
 if ((DefaultLangText))

 {
 return CurrentLangText;

 }
else
 {
 string langText = ();
 LanDict[] = langText;
return langText;
 }

 }
 return ;

 }
set
 {
  = value;
 }
 }
 [Browsable(false)]

 [DesignerSerializationVisibility()]

 public string DefaultLangText

 {

 get

 {

 return ;

 }
 }

 [Browsable(false)]

 [DesignerSerializationVisibility()]

 public string CurrentLangText

 {
 get
 {
try
 {

 return LanDict[DefaultLangText];

 }
 catch (Exception)
 {

 return "";
 }
 }

set
 {

 if ( != "zh-CHS")

 {

 if ((DefaultLangText))

 {

 LanDict[DefaultLangText] = value;

 }

 else

 {

 (DefaultLangText, value);

 }

 }

 }

 }

 } 

The purpose of secondary encapsulation of these controls is: 1. Expose unified attributes to facilitate direct traversal and assignment (there is a situation where the text content language needs to be manually changed); 2. When the text content changes, the dictionary can be cached according to the language, and the self-simplified and traditional Chinese conversion is quickly and directly, without traversal again;

4. Implement support for multilingual container controls: Secondary encapsulation is performed based on the original standard controls (StatusStrip, TabPage, ToolStrip, DataGridView, CheckedListBox, TreeView), and implement the IMultiLanguageContainerControl interface. The codes of each control are as follows:

MyStyleDataGridView:

Because the code is too long, pleaseClick to download

MyStyleTabControl:

Because the code is too long, pleaseClick to download

The purpose of secondary encapsulation of these controls is: 1. Expose unified attributes to facilitate direct traversal and assignment of values ​​(only required when directly changing the text content language); 2. When the text content or sub-control text content or new sub-controls are changed, the dictionary can be cached according to the language, and the self-simplified and traditional Chinese conversion is quickly and directly, without traversal again;

5. LanguageHelper: The language side conversion public class is the same as Scheme 1, but it is much simpler than Scheme 1. The code is as follows:

Because the code is too long, pleaseClick to download

The method is defined as follows:

public static bool IsChsLanguage()

{

 return ("zh-CHS", );

} 

The difficulty in implementing container-like controls supported by multilinguals is to capture changes in the text content of the child control. Since there are no ready-made events or methods, other ways are needed to achieve the ability to process the text content changes.

The above is the entire content of this article. Some people may say why they do not use the form of resource files. The reason is explained at the beginning of the article that it is on the original system and cannot change the original coding style. Therefore, it took so much effort to realize the function of simplified and traditional Chinese conversion. Our company confirmed by the leaders that the final adoption of solution 2. If there are any shortcomings in the article, please feel free to communicate, thank you!

Note: The implementation code of the control has been posted. If you need it, you can go directly. In addition, for system security, I will not post the screenshots of the Simplified Traditional Chinese system. You can test it yourself.