Language.cs 10.2 KB
using System;
using System.Xml;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace Asa.FaceControl
{
    /// <summary>
    /// 多语言类
    /// </summary>
    public static class Language
    {
        private static XmlDocument xmlDoc;
        private static string[] filePath;    //XML文件的路径
        private static int nameIndex = -1;
        private static readonly Dictionary<string, string> dialogText = new();
        private static readonly List<ClsLangForm> langForm = new();

        /// <summary>
        /// 语言名称
        /// </summary>
        public static string[] Name { private set; get; } = null;



        /// <summary>
        /// 加载语言路径
        /// </summary>
        /// <param name="path"></param>
        public static void LoadPath(string path)
        {
            if (!System.IO.Directory.Exists(path))
                System.IO.Directory.CreateDirectory(path);
            filePath = System.IO.Directory.GetFiles(path, "*.xml");

            xmlDoc = new XmlDocument();
            Name = new string[filePath.Length];
            for (int i = 0; i < filePath.Length; i++)
            {
                xmlDoc.Load(filePath[i]);
                Name[i] = xmlDoc.LastChild.Attributes["Name"].Value;
            }
        }

        /// <summary>
        /// 加载语言
        /// </summary>
        /// <param name="name"></param>
        public static void LoadLanguage(string name)
        {
            nameIndex = Array.FindIndex(Name, s => s == name);
            if (nameIndex == -1) return;
            LoadLanguage();
            foreach (Form frm in Application.OpenForms)
            {
                if (frm is FormBase @base)
                    SetLanguage(@base);
            }
        }

        /// <summary>
        /// 对话框
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Dialog(string key,string defaulttxt="")
        {
            if (nameIndex == -1) return "";
            if (dialogText.TryGetValue(key, out string value))
                return value;
            else
            {
                SetNoLangXML("Dialog", key, defaulttxt);
                return defaulttxt;
            }
        }

        /// <summary>
        /// 设置语言
        /// </summary>
        /// <param name="frm"></param>
        public static void SetLanguage(FormBase frm)
        {
            if (nameIndex == -1) return;
            int langIdx = langForm.FindIndex(s => s.FormLang.Name == frm.Name);
            if (langIdx == -1) return;
            frm.Text = langForm[langIdx].FormLang.Text;
            frm.TitleFont = langForm[langIdx].FormLang.Font;
            SetLang(langIdx, frm);
        }

        /// <summary>
        /// 设置语言
        /// </summary>
        /// <param name="ctl"></param>
        public static void SetLanguage(Control ctl)
        {
            if (nameIndex == -1) return;
            int langIdx = langForm.FindIndex(s => s.FormLang.Name == ctl.Name);
            if (langIdx == -1) return;
            SetLang(langIdx, ctl);
        }





        ///// <summary>
        ///// 语言索引
        ///// </summary>
        //public static int Index
        //{
        //    set
        //    {
        //        if (value > -1 && value < _file.Length)
        //        {
        //            _index = value;
        //            LoadLanguage();
        //            foreach (Form frm in Application.OpenForms)
        //            {
        //                if (frm is FormBase)
        //                    SetLanguage((FormBase)frm);
        //            }
        //        }
        //    }
        //    get
        //    {
        //        return _index;
        //    }
        //}

        ///// <summary>
        ///// 加载语言
        ///// </summary>
        ///// <param name="name"></param>
        //public static void Load(string name)
        //{
        //    int idx = Array.FindIndex(Name, s => s == name);
        //    Index = idx;
        //}





        ///// <summary>
        ///// 设置语言
        ///// </summary>
        ///// <param name="frm"></param>
        //public static void SetLanguage(Form frm)
        //{
        //    int langIdx = langForm.FindIndex(s => s.FormLang.Name == frm.Name);
        //    if (langIdx == -1) return;
        //    //frm.Text = langForm[langIdx].FormLang.Text;
        //    //frm.TitleFont = langForm[langIdx].FormLang.Font;
        //    SetLang(langIdx, frm);
        //}






        private static void LoadLanguage()
        {
            xmlDoc.Load(filePath[nameIndex]);
            XmlNode root = xmlDoc.LastChild;
            langForm.Clear();
            dialogText.Clear();

            foreach (XmlNode node in root.ChildNodes)
            {
                if (node.Name == "Dialog")
                {
                    foreach (XmlNode tt in node.ChildNodes)
                    {
                        if (!dialogText.ContainsKey(tt.Name))
                            dialogText.Add(tt.Name, tt.InnerText);
                    }
                }
                else
                {
                    ClsLangForm lang = new();
                    lang.FormLang.Name = node.Name;
                    if (node.Attributes["Text"] != null) lang.FormLang.Text = node.Attributes["Text"].Value;
                    if (node.Attributes["Font"] != null) lang.FormLang.Font = ConvFont(node.Attributes["Font"].Value);
                    //if (node.Attributes["Tag"] != null) lang.FormLang.Tag = node.Attributes["Tag"].Value;
                    foreach (XmlNode tt in node.ChildNodes)
                    {
                        if (tt.NodeType != XmlNodeType.Element)
                            continue;

                        ClsLangText ll = new()
                        {
                            Name = tt.Name
                        };
                        if (tt.Attributes["Text"] != null) ll.Text = tt.Attributes["Text"].Value;
                        if (tt.Attributes["Font"] != null) ll.Font = ConvFont(tt.Attributes["Font"].Value);
                        //if (tt.Attributes["Tag"] != null) ll.Tag = tt.Attributes["Tag"].Value;
                        lang.ControlLang.Add(ll);
                    }
                    langForm.Add(lang);
                }
            }

        }

        private static void SetLang(int langIndex, Control ctl)
        {
            foreach (Control cc in ctl.Controls)
            {
                if (cc.Name == "") continue;
                
                int idx = langForm[langIndex].ControlLang.FindIndex(s => s.Name == cc.Name);
                if (idx > -1)
                {
                    //Debugger.Break();
                    cc.Text = langForm[langIndex].ControlLang[idx].Text;
                    if (cc is FacePanel)
                        ((FacePanel)cc).TitleFont = langForm[langIndex].ControlLang[idx].Font;
                    else
                        cc.Font = langForm[langIndex].ControlLang[idx].Font;
                    //cc.Tag = langForm[langIndex].ControlLang[idx].Tag;
                }
                else {
                    if (!string.IsNullOrWhiteSpace(cc.Text) && HasChinese(cc.Text))
                    {
                        if (cc.Tag == null || cc.Tag.ToString() != "not")
                        {
                            SetNoLangXML(langForm[langIndex].FormLang.Name, cc.Name, cc.Text);
                        }
                    }
                }
                if (cc.HasChildren)
                    SetLang(langIndex, cc);
            }
        }
        static void SetNoLangXML(string formname,string controlname,string text) {
            xmlDoc.Load(filePath[nameIndex]);
            XmlNode root = xmlDoc.LastChild;
            var n=root.SelectSingleNode(formname);
            if (n.SelectSingleNode(controlname) != null)
                return;
            var cc = xmlDoc.CreateComment("原文:"+text);
            var ln = xmlDoc.CreateElement(controlname);
            if (formname == "Dialog") {
                ln.InnerText = text;
            }
            else
            {
                ln.SetAttribute("Text", text);
                ln.SetAttribute("Font", "微软雅黑,12,,");
            }
            n.AppendChild(cc);
            n.AppendChild(ln);
            xmlDoc.Save(filePath[nameIndex]);
        }
        static bool HasChinese(string txt)
        {

            //for (int i = 0; i < txt.Length; i++)
            //{
            if (Regex.IsMatch(txt.ToString(), @"[\u4E00-\u9FA5]+"))
                return true;
            //}
            return false;
        }
        /// <summary>
        /// 转换字体
        /// </summary>
        /// <param name="s">格式:字体,字号,粗体,斜体</param>
        /// <returns></returns>
        private static Font ConvFont(string s)
        {
            string[] t = s.Split(',');
            float emSize = Convert.ToSingle(t[1]);
            FontStyle style = FontStyle.Regular;
            if (t[2] == "B") style |= FontStyle.Bold;
            if (t[3] == "I") style |= FontStyle.Italic;
            Font font = new(t[0], emSize, style);
            return font;
        }

        ///// <summary>
        ///// 转换字体
        ///// </summary>
        ///// <param name="f">字体</param>
        ///// <returns></returns>
        //private static string ConvFont(Font f)
        //{
        //    string[] s = new string[4];
        //    s[0] = f.Name;
        //    s[1] = f.Size.ToString();
        //    if (f.Bold) s[2] = "B";
        //    if (f.Italic) s[3] = "I";
        //    return string.Join(",", s);
        //}

        private class ClsLangForm
        {
            public ClsLangText FormLang;
            public List<ClsLangText> ControlLang;

            public ClsLangForm()
            {
                FormLang = new ClsLangText();
                ControlLang = new List<ClsLangText>();
            }
        }

        private class ClsLangText
        {
            public string Name = "";
            public string Text = "";
            public Font Font = null;
            //public static string Tag = "";
        }
    }
}