设为首页 收藏本站
查看: 2560|回复: 0

[经验分享] Windows本地化信息浏览器

[复制链接]

尚未签到

发表于 2018-6-15 12:54:45 | 显示全部楼层 |阅读模式
  在软件开发中,只要软件的用户涉及到不同的国家,则需要考虑其所使用的语言,字符集(现在可以使用Unicode通用字符集),货币符号,日期时间格式,数字格式等等,例如,常用的WinRAR就有近20种语言的不同版本,这种技术称作软件的本地化。实际上,Windows系列本身提供了严格的本地化机制,例如各种文化(Culture)都有自己的LCID,文本都有自己的代码页等等,我们在实际开发过程中可以使用Windows提供的这些内容,剩下的只是将软件中的字符串资源进行翻译就可以了,这样可简化本地化工作,极大地提高开发效率。
  
    为此,我用.NET(C#)编制了一个“Windows文化信息浏览器”,通过该软件可以查阅任何语言和任何国家(语言相同但国家不同的不同文化)的详细文化信息,程序不是很复杂,注释相当详实,有一定经验的开发者都可以作为参考。
  
这是软件截图:
  
DSC0000.jpg
  这是程序的核心代码:
  


  • 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.DisplayName; // 为节点提供名称(文化的显示名称)
  •                 tempNode.Tag = cultures; // 使用属性节点的附加数据属性,存储文化对象,以便将来在用户点击时,显式该文化的信息及使用该文化
  •                 treeViewCulture.Nodes[0].Nodes.Add(tempNode); // 在顶层根节点下的节点集合中插入节点
  •             }

  •             // 取得特定文化
  •             cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
  •             // 插入所有特定文化
  •             for (int i = 0; i < cultures.Length; i++)
  •             {
  •                 // 取得TreeView中的顶层根节点下的第1个子节点(顶层根节点下标为0,即&quot;所有区域&quot;节点,其下的第1个子节点即第2层节点中的第1个)
  •                 TreeNode nextRootNode = treeViewCulture.Nodes[0].FirstNode;
  •                 while (nextRootNode != null) //迭代所有根节点,总可以找到该特定文化的父文化
  •                 {
  •                     // 特定文化一定有父文化存在,判断该特定文化是否属于该中立文化或不变的文化
  •                     if (cultures.Parent.LCID == ((CultureInfo)nextRootNode.Tag).LCID)
  •                     {
  •                         TreeNode tempNode = new TreeNode(); // 建立临时节点
  •                         tempNode.Text = cultures.DisplayName; // 为节点提供名称(文化的显示名称)
  •                         tempNode.Tag = cultures; // 使用属性节点的附加数据属性,存储文化对象,以便将来在用户点击时,显式该文化的信息及使用该文化
  •                         nextRootNode.Nodes.Add(tempNode); // 插入节点,作为查找到的节点的子节点
  •                         break; // 已经为当前特定文化节点找到了父节点,退出循环
  •                     }
  •                     nextRootNode = nextRootNode.NextNode; //获取下一个同级节点(即下一个根节点,中立文化或不变的文化)
  •                 }
  •             }

  •             // 分配IComparer接口对象,实现自定义排序
  •             treeViewCulture.TreeViewNodeSorter = new CompareCultureName();
  •             // 对TreeView中的内容(即所有文化)进行排序,以方便阅读
  •             treeViewCulture.Sort();

  •             // 利用树节点数量及层次统计非特定区域:即中立文化(语言相关区域)+不变的文化(固定区域);特定区域:特定文化
  •             // 也可利用cultures.Length在取得每类文化后分别进行统计
  •             treeViewCulture.Nodes[0].Text += String.Format(&quot;({0}非特定区域/{1}特定区域)&quot;,
  •                 treeViewCulture.Nodes[0].GetNodeCount(false), treeViewCulture.Nodes[0].GetNodeCount(true) - treeViewCulture.Nodes[0].GetNodeCount(false));

  •             //展开&quot;所有区域&quot;下的一个层次的节点
  •             treeViewCulture.Nodes[0].Expand();
  •         }

  •         // 用户点选TreeView中的节点后的事件处理方法
  •         private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
  •         {
  •             // 清空所有显示内容
  •             // 因为不变的文化没有区域信息,中立文化没有示例和区域信息
  •             // 另外,户点选&quot;所有区域&quot;时同样需要清除所有显示内容
  •             ClearAllFields(this);

  •             // 判断是否点选了&quot;所有区域&quot;节点,其所在层次(level)为0
  •             // 当选中&quot;所有区域&quot;时,将文化信息、文本信息置为不可用,否则置为可用,示例、区域信息是否可用在后面处理
  •             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(&quot;Calendar&quot;, &quot;&quot;);

  •             // 处理可选日历
  •             comboBoxCalendars.Items.Clear(); // 清空下拉列表
  •             foreach (Calendar optCal in ci.OptionalCalendars) // 枚举可选日历集合
  •             {
  •                 // 使用StringBulider类处理字符串以加快速度
  •                 // 等价为:string calName = optCal.ToString().Remove(0, 21).Replace(&quot;Calendar&quot;, &quot;&quot;);
  •                 StringBuilder calName = new StringBuilder(50);
  •                 calName.Append(optCal.ToString());
  •                 calName.Remove(0, 21);
  •                 calName.Replace(&quot;Calendar&quot;, &quot;&quot;);

  •                 // 由于格里历(公历)包含了多种语言版本,所以需要为每种不同语言的格里历添加类型信息描述,以便区分
  •                 GregorianCalendar gregCal = optCal as GregorianCalendar; // 尝试将可选日历转换为格里历
  •                 if (gregCal != null) // 转换结果为null,说明可选日历不是格里历
  •                 {
  •                     // 添加格里历的类型信息(语言本版信息)
  •                     // 如不使用StringBuilder,可写为:calName += &quot; &quot; + gregCal.CalendarType.ToString();
  •                     calName.AppendFormat(&quot; {0}&quot;, 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 = &quot;&quot;;
  •             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(&quot;N5&quot;, ci);

  •             // 使用指定的文化信息格式化长日期和长时间
  •             textBoxSampleDate.Text = DateTime.Today.ToString(&quot;D&quot;, ci);
  •             textBoxSampleTime.Text = DateTime.Now.ToString(&quot;T&quot;, 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/attachment/201101/876134_1294719610.rar

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-524223-1-1.html 上篇帖子: windows phone 7 平台搭建 下篇帖子: windows2008不能使用telnet解决方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表