1. 程式人生 > >c# 程式多語言切換嘗試

c# 程式多語言切換嘗試

劃重點:在網上查了很多資料,一個很重要的點基本上沒有人提出來,要使用.net4.0及以上啊。。。否則都是扯淡。

程式碼還是那個程式碼,.net4.0以下根本就不起作用。

1. 學習過程:修改視窗的localizable=true; Language=你要新增的語言。VS會幫我們自動新增一個對應的語言資原始檔。

這時候修改窗體的text為繁體,開啟Fom1.zh_TW.resx, 會發現裡面有一條 名稱和值的對應資訊:$this.Text: 測試視窗。
 

檢視建構函式:           

System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));


resources.ApplyResources(this, "$this");  

原先的this.Text='測試視窗',變成了resources.ApplyResources(this, "$this");  

這個是一個很合理的邏輯,我在開始查資料,知道會形成多個資原始檔的時候,就想應該是存在一種快速切換資源的做法。

網上的很多程式碼是這樣的:

        public Form_實驗管理()
        {
            InitializeComponent();
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

            ApplyResource();  //修改控制元件的語言顯示
        }

        private void ApplyResource()
        {
            System.ComponentModel.ComponentResourceManager res = new ComponentResourceManager(typeof(Form_實驗管理));
            foreach (Control ctl in Controls)
            {

                res.ApplyResources(ctl, ctl.Name);
            }
            this.ResumeLayout(false);
            this.PerformLayout();
            res.ApplyResources(this, "$this");
        }

這個我隱隱覺得不對勁,還需要自己每個視窗去寫迴圈?但是因為一開始我用的.net2.0, 上面的方法不起作用,我以為是我沒弄對,後來使用下面程式碼的時候也不起作用,我就覺得應該要使用更高版本的框架,改為.net4.0後,生效了。

兩種方法都生效,但是上面這個程式碼明顯比較繁瑣。

反覆強調:在網上看到使用高版本特性的方法說明時不帶版本,或者不帶引用,這點很討厭,自己也要注意這點。

2.  實際使用:這個方法很簡單,直接讓.net自己去載入對應的語言資原始檔就好了。

System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-TW");

這句話放在哪裡呢,我需要整個程式都切換語言,通過配置檔案一開始就設定好語言,不需要隨時切換語言,所以我放在了登入視窗的load事件裡面。

        private void Login_Load(object sender, EventArgs e)
        {
            string lan = "";
            if (MConfig.Language == "臺灣繁體")
            {
                lan = "zh-TW";

            }
            if (MConfig.Language == "UsEnglish")
            {
                lan = "en-US";
            }
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lan);

        }

3. 翻譯工作:一個程式有幾十個視窗,幾百幾千個控制元件,如何快速的完成其他語言錄入工作?

3.1 每一個視窗名稱,控制元件名稱都要有對應語言的翻譯,然後要加入到資原始檔。如果我們在視覺化介面上一個個控制元件進行修改,要有個翻譯坐在旁邊,不斷的翻譯,然後我們錄入,工作量龐大,效率低。

開啟資原始檔看了下。原始的resx是這樣的

可以清楚的看到,排除帶>>符號的,剩下的就是視窗和的控制元件Text,或者自定義的欄位。

在介面上將英文的視窗text改為Test,檢視en-Us.resx的內容,發現裡面的內容是這樣的。

從原始resx裡面複製button1.Text到en-Us並修改值為按鈕1button,執行結果顯示成功。

 

3.2 於是將form1.resx的檔案內容複製到excel,去除帶>>的,發給翻譯,讓翻譯對照軟體視窗,將對應的值全部改成對應的語言,完成後我們從excel直接複製到對應的資原始檔中,工作就完成了。

2018-9-10號補充:我的程式視窗巨多,工作量有點大。而且上面的方法不利於後續程式更改,控制元件有變化的話就需要重新發資原始檔進行更新。

想了一個比較傻瓜化的方法,類似上面的資原始檔,在視窗載入時從資原始檔獲取對應的語言。這裡需要自定義基礎Form控制元件,在load時間中載入其他語言,其他視窗全部繼承此控制元件。

CSV檔案,客戶隨時可以新增中文和其他語言的對照關係。客戶在介面上看到某個不對的翻譯時,隨時可以對CSV檔案進行更改或者新增。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace HSJ_p
{
 
    public partial class MBaseForm : Form
    {
 
        public MBaseForm()
        {       
            InitializeComponent();
 
        }
        /// <summary>
        /// 載入的時候替換相應的語言
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MBaseForm_Load(object sender, EventArgs e)
        {
            if (HSJ_p.Data.SysParameterItem.LanguageResources == null || HSJ_p.Data.SysParameterItem.LanguageResources.Columns.Count == 0) return;
            if (HSJ_p.Data.MConfig.Language != "簡體中文")
            {
                GetLanguageText(this);
            }
        }

        private void GetLanguageText<T>(T obj)
        {
            try
            {
                if (typeof(Form) == typeof(T).BaseType
                    || typeof(Control) == typeof(T))
                {
                    Control c = (Control)(object)obj;
                    DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", c.Text), "");
                    if (drs.Length > 0)
                    {
                        c.Text = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                    }
                    if (c.Controls.Count > 0)
                    {
                        foreach (Control c1 in c.Controls)
                        {
                            GetLanguageText(c1);
                        }
                    }
                }
                //注意有些控制元件不是control型別的
                if (typeof(ToolStrip) == obj.GetType().BaseType
                    || typeof(ToolStrip) == obj.GetType())
                {
                    ToolStrip c = (ToolStrip)(object)obj;

                    DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", c.Text), "");
                    if (drs.Length > 0)
                    {
                        c.Text = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                    }
                    if (c.Items.Count > 0)
                    {
                        foreach (ToolStripItem c1 in c.Items)
                        {
                            GetLanguageText(c1);
                        }
                    }
                }

                if (typeof(MenuStrip) == obj.GetType().BaseType
                    || typeof(MenuStrip) == obj.GetType())
                {
                    MenuStrip c = (MenuStrip)(object)obj;
                    DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", c.Text), "");
                    if (drs.Length > 0)
                    {
                        c.Text = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                    }
                    if (c.Items.Count > 0)
                    {
                        foreach (ToolStripMenuItem c1 in c.Items)
                        {
                            GetLanguageText(c1);
                        }
                    }
                }
                if (typeof(ToolStripItem) == obj.GetType().BaseType
                    || typeof(ToolStripItem) == obj.GetType())
                {
                    ToolStripItem c = (ToolStripItem)(object)obj;
                    DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", c.Text), "");
                    if (drs.Length > 0)
                    {
                        c.Text = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                    }
  
                }
                if (typeof(ToolStripMenuItem) == obj.GetType().BaseType
                    || typeof(ToolStripMenuItem) == obj.GetType())
                {
                    ToolStripMenuItem c = (ToolStripMenuItem)(object)obj;
                    DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", c.Text), "");
                    if (drs.Length > 0)
                    {
                        c.Text = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                    }
                    if (c.DropDownItems.Count > 0)
                    {
                        foreach (ToolStripItem c1 in c.DropDownItems)
                        {
                            GetLanguageText(c1);
                        }
                    }
                }
                if (typeof(DataGridView) == obj.GetType().BaseType
                    || typeof(DataGridView) == obj.GetType())
                {
                    DataGridView c = (DataGridView)(object)obj;
                    foreach (DataGridViewColumn col in c.Columns )
                    {
                        DataRow[] drs = HSJ_p.Data.SysParameterItem.LanguageResources.Select(string.Format("簡體中文='{0}'", col.HeaderText), "");
                        if (drs.Length > 0)
                        {
                            col.HeaderText = drs[0][HSJ_p.Data.MConfig.Language].ToString();
                        }

                    }
                }

            }
            catch(Exception ex)
            {

            }

        }


}