在軟件開發中,只要軟件的用戶涉及到不一樣的國家,則須要考慮其所使用的語言,字符集(如今可使用Unicode通用字符集),貨幣符號,日期時間格式,數字格式等等,例如,經常使用的WinRAR就有近20種語言的不一樣版本,這種技術稱做軟件的本地化。實際上,Windows系列自己提供了嚴格的本地化機制,例如各類文化(Culture)都有本身的LCID,文本都有本身的代碼頁等等,咱們在實際開發過程當中可使用Windows提供的這些內容,剩下的只是將軟件中的字符串資源進行翻譯就能夠了,這樣可簡化本地化工做,極大地提升開發效率。
爲此,我用.NET(C#)編制了一個「Windows文化信息瀏覽器」,經過該軟件能夠查閱任何語言和任何國家(語言相同但國家不一樣的不一樣文化)的詳細文化信息,程序不是很複雜,註釋至關詳實,有必定經驗的開發者均可以做爲參考。
這是軟件截圖:
瀏覽器
這是程序的核心代碼:架構
- using System;
- using System.Collections;
- using System.Globalization;
- using System.Text;
- using System.Windows.Forms;
- namespace Mengliao.CSharp.C21.S01
- {
- public partial class FormCulture : Form
- {
- public FormCulture()
- {
- InitializeComponent();
- AddCulturesToTree();
- }
- // 添加全部文化(不變的文化、中立文化、特定文化)到TreeView中
- public void AddCulturesToTree()
- {
- // 添加一個頂層根節點
- treeViewCulture.Nodes.Add("全部區域");
- // 取得中立文化和不變的文化
- CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
- // 插入全部中立文化和不變的文化
- for (int i = 0; i < cultures.Length; i++)
- {
- TreeNode tempNode = new TreeNode(); // 創建臨時節點
- tempNode.Text = cultures[i].DisplayName; // 爲節點提供名稱(文化的顯示名稱)
- tempNode.Tag = cultures[i]; // 使用屬性節點的附加數據屬性,存儲文化對象,以便未來在用戶點擊時,顯式該文化的信息及使用該文化
- treeViewCulture.Nodes[0].Nodes.Add(tempNode); // 在頂層根節點下的節點集合中插入節點
- }
- // 取得特定文化
- cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
- // 插入全部特定文化
- for (int i = 0; i < cultures.Length; i++)
- {
- // 取得TreeView中的頂層根節點下的第1個子節點(頂層根節點下標爲0,即"全部區域"節點,其下的第1個子節點即第2層節點中的第1個)
- TreeNode nextRootNode = treeViewCulture.Nodes[0].FirstNode;
- while (nextRootNode != null) //迭代全部根節點,總能夠找到該特定文化的父文化
- {
- // 特定文化必定有父文化存在,判斷該特定文化是否屬於該中立文化或不變的文化
- if (cultures[i].Parent.LCID == ((CultureInfo)nextRootNode.Tag).LCID)
- {
- TreeNode tempNode = new TreeNode(); // 創建臨時節點
- tempNode.Text = cultures[i].DisplayName; // 爲節點提供名稱(文化的顯示名稱)
- tempNode.Tag = cultures[i]; // 使用屬性節點的附加數據屬性,存儲文化對象,以便未來在用戶點擊時,顯式該文化的信息及使用該文化
- nextRootNode.Nodes.Add(tempNode); // 插入節點,做爲查找到的節點的子節點
- break; // 已經爲當前特定文化節點找到了父節點,退出循環
- }
- nextRootNode = nextRootNode.NextNode; //獲取下一個同級節點(即下一個根節點,中立文化或不變的文化)
- }
- }
- // 分配IComparer接口對象,實現自定義排序
- treeViewCulture.TreeViewNodeSorter = new CompareCultureName();
- // 對TreeView中的內容(即全部文化)進行排序,以方便閱讀
- treeViewCulture.Sort();
- // 利用樹節點數量及層次統計非特定區域:即中立文化(語言相關區域)+不變的文化(固定區域);特定區域:特定文化
- // 也可利用cultures.Length在取得每類文化後分別進行統計
- treeViewCulture.Nodes[0].Text += String.Format("({0}非特定區域/{1}特定區域)",
- treeViewCulture.Nodes[0].GetNodeCount(false), treeViewCulture.Nodes[0].GetNodeCount(true) - treeViewCulture.Nodes[0].GetNodeCount(false));
- //展開"全部區域"下的一個層次的節點
- treeViewCulture.Nodes[0].Expand();
- }
- // 用戶點選TreeView中的節點後的事件處理方法
- private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
- {
- // 清空全部顯示內容
- // 由於不變的文化沒有區域信息,中立文化沒有示例和區域信息
- // 另外,戶點選"全部區域"時一樣須要清除全部顯示內容
- ClearAllFields(this);
- // 判斷是否點選了"全部區域"節點,其所在層次(level)爲0
- // 當選中"全部區域"時,將文化信息、文本信息置爲不可用,不然置爲可用,示例、區域信息是否可用在後面處理
- groupBoxCulture.Enabled = groupBoxText.Enabled = e.Node.Level != 0;
- if (e.Node.Level == 0)
- {
- // 將示例、區域信息置爲不可用
- groupBoxSamples.Enabled = groupBoxRegionInfo.Enabled = false;
- return;
- }
- // 從用戶點選的節點對象中獲取保存在Tag屬性中的CultureInfo對象
- CultureInfo ci = (CultureInfo)e.Node.Tag; // Object類型顯式轉換
- textBoxName.Text = ci.Name; // 文化名稱(文化的字符串表示)
- checkBoxIsNeutral.Checked = ci.IsNeutralCulture; // 是否中立文化
- textBoxNativeName.Text = ci.NativeName; // 本地名稱
- textBoxEnglishName.Text = ci.EnglishName; // 英文名稱
- // 默認日曆,將日曆對象轉換爲字符串(即日曆名稱),移除前面的21個字符(命名空間字符串System.Globalization.)
- // 再移除末尾的字符串Calendar
- textBoxCalendar.Text = ci.Calendar.ToString().Remove(0, 21).Replace("Calendar", "");
- // 處理可選日曆
- comboBoxCalendars.Items.Clear(); // 清空下拉列表
- foreach (Calendar optCal in ci.OptionalCalendars) // 枚舉可選日曆集合
- {
- // 使用StringBulider類處理字符串以加快速度
- // 等價爲:string calName = optCal.ToString().Remove(0, 21).Replace("Calendar", "");
- StringBuilder calName = new StringBuilder(50);
- calName.Append(optCal.ToString());
- calName.Remove(0, 21);
- calName.Replace("Calendar", "");
- // 因爲格里曆(公曆)包含了多種語言版本,因此須要爲每種不一樣語言的格里曆添加類型信息描述,以便區分
- GregorianCalendar gregCal = optCal as GregorianCalendar; // 嘗試將可選日曆轉換爲格里曆
- if (gregCal != null) // 轉換結果爲null,說明可選日曆不是格里曆
- {
- // 添加格里曆的類型信息(語言本版信息)
- // 如不使用StringBuilder,可寫爲:calName += " " + gregCal.CalendarType.ToString();
- calName.AppendFormat(" {0}", gregCal.CalendarType.ToString());
- }
- // 添加到ComboBox中
- // 如不使用StringBuilder可寫爲:comboBoxCalendars.Items.Add(calName);
- comboBoxCalendars.Items.Add(calName.ToString());
- }
- comboBoxCalendars.SelectedIndex = 0; // 顯示可選日曆中的第1項
- textBoxKeyboard.Text = ci.KeyboardLayoutId.ToString(); // 輸入法ID
- textBoxLCID.Text = ci.LCID.ToString(); // LCID
- textBoxWinAPILangID.Text = ci.ThreeLetterWindowsLanguageName; // Windows API語言
- textBoxISO639_1.Text = ci.TwoLetterISOLanguageName; // ISO 639-1語言
- textBoxISO639_2.Text = ci.ThreeLetterISOLanguageName; // ISO 639-2語言
- // 文本信息
- textBoxANSI.Text = ci.TextInfo.ANSICodePage.ToString(); // ANSI代碼頁
- checkBoxIsRightToLeft.Checked = ci.TextInfo.IsRightToLeft; // 是否從右到左
- if (ci.TextInfo.IsRightToLeft) //設定本地名稱和貨幣本地名稱爲從右到左或者從左到右顯示
- textBoxNativeName.RightToLeft = textBoxSampleNumber.RightToLeft = textBoxSampleDate.RightToLeft =
- textBoxSampleTime.RightToLeft = textBoxCurrencyNativeName.RightToLeft = textBoxCurrencySymbol.RightToLeft = RightToLeft.Yes;
- else
- textBoxNativeName.RightToLeft = textBoxSampleNumber.RightToLeft = textBoxSampleDate.RightToLeft =
- textBoxSampleTime.RightToLeft = textBoxCurrencyNativeName.RightToLeft = textBoxCurrencySymbol.RightToLeft = RightToLeft.No;
- textBoxEBCDIC.Text = ci.TextInfo.EBCDICCodePage.ToString(); // EBCDIC代碼頁
- textBoxMacintosh.Text = ci.TextInfo.MacCodePage.ToString(); // Macintosh代碼頁
- textBoxOEM.Text = ci.TextInfo.OEMCodePage.ToString(); // OEM代碼頁
- // 顯示示例和區域信息
- if (!ci.IsNeutralCulture) // 不是中立文化
- {
- // 顯示示例
- groupBoxSamples.Enabled = true;
- ShowSamples(ci);
- // ISO 639-2定義了三個字母表示的語言名稱,以此判斷該非中立文化是不是不變的文化
- if (ci.LCID == CultureInfo.InvariantCulture.LCID) // 是不變的文化
- {
- groupBoxRegionInfo.Enabled = false; // 不包含區域信息
- }
- else // 是特定的文化
- {
- // 包含區域信息
- groupBoxRegionInfo.Enabled = true;
- ShowRegionInformation(ci.Name);
- }
- }
- else // 中立文化既沒有示例、也沒有區域信息
- groupBoxSamples.Enabled = groupBoxRegionInfo.Enabled = false;
- }
- // 清空全部顯示內容
- private void ClearAllFields(Control control)
- {
- // 若是該控件包含有子控件,則枚舉全部子控件,對每一個子控件遞歸調用該方法,直至控件不包含子控件
- if (control.HasChildren)
- foreach (Control childControl in control.Controls)
- ClearAllFields(childControl);
- else if (control is TextBox) //該控件是TextBox,清除內容
- ((TextBox)control).Text = "";
- else if (control is CheckBox) //該控件是CheckBox,將其置爲未選中
- ((CheckBox)control).Checked = false;
- else if (control is ComboBox) //該控件是ComboBox,清空項目
- ((ComboBox)control).Items.Clear();
- }
- // 顯式示例中的內容
- private void ShowSamples(CultureInfo ci)
- {
- // 使用指定的文化信息格式化標準數字(Double)
- textBoxSampleNumber.Text = 9876543.21D.ToString("N5", ci);
- // 使用指定的文化信息格式化長日期和長時間
- textBoxSampleDate.Text = DateTime.Today.ToString("D", ci);
- textBoxSampleTime.Text = DateTime.Now.ToString("T", ci);
- }
- // 顯式區域信息中的內容
- private void ShowRegionInformation(string culture)
- {
- // 使用指定的文化信息字符串實例化一個區域信息對象
- RegionInfo ri = new RegionInfo(culture);
- textBoxGeoID.Text = ri.GeoId.ToString(); // GeoID
- checkBoxIsMetric.Checked = ri.IsMetric; // 是否公制單位
- textBoxCurrencyNativeName.Text = ri.CurrencyNativeName; // 貨幣本地名稱
- textBoxCurrencyEnglishName.Text = ri.CurrencyEnglishName; // 貨幣英文名稱
- textBoxCurrencySymbol.Text = ri.CurrencySymbol; // 貨幣符號
- textBoxISOCurrencySymbol.Text = ri.ISOCurrencySymbol; // ISO 4217貨幣符號
- textBoxISO3166_2.Text = ri.TwoLetterISORegionName; // ISO 3166(2字母)
- textBoxISO3166_3.Text = ri.ThreeLetterISORegionName; // ISO 3166(3字母)
- textBoxWinRegionName.Text = ri.ThreeLetterWindowsRegionName; // Windows API代碼
- }
- // 自定義TreeView的排序IComparer接口
- class CompareCultureName : IComparer
- {
- int IComparer.Compare(Object x, Object y) // 實現該接口的惟一方法
- {
- // 須要使用CultureInfo類的Name屬性(內部名稱)排序(字符串)
- // 傳入的x、y是兩個TreeNode對象,其Tag屬性中保存着相應的CultureInfo對象
- return ((CultureInfo)(((TreeNode)x).Tag)).Name.CompareTo(((CultureInfo)(((TreeNode)y).Tag)).Name);
- }
- }
- }
- }
下面的連接和附件中連接是同樣的,都是本軟件的完整源碼,包含了一個已編譯的.exe文件,至少須要.NET 3.5架構支持:
http://mengliao.blog.51cto.com/p_w_upload/201101/876134_1294719610.raride