我希望我的应用程序支持多种UI语言(又名i18n)。为此,我在下面构建了静态类,以便自动将表单及其所有内容转换为所需的语言。它查看用户的区域性的资源文件,并将控件的.Text属性替换为它在那里找到的字符串,或者返回到初始字符串,即英语。
用法是从每个表单的构造函数调用TranslateForm(this)。
关于我的代码有两个关注点:
*“翻译”方法超载。我没有找到任何办法来克服这一切。
*特别处理不同的管制措施,这似乎是不必要的。
我不是一个专业的程序员,所以任何纠正/增强/修复我的代码都是非常受欢迎的!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Globalization;
using System.Resources;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections;
namespace blahblah
{
static class TranslationHelper
{
static private ResourceManager rm = null;
static private CultureInfo default_ci = null;
static private CultureInfo lang_ci = null;
/// <summary>
/// translate control into the specific lang, or leave it untranslated if no translation string found
/// </summary>
/// <param name="ctrl"></param>
/// <param name="lang"></param>
static private void Translate(Control ctrl, string lang)
{
string str = TranslateString(ctrl.Name, lang);
if (str != null)
ctrl.Text = str;
}
static private void Translate(ToolStripMenuItem o, string lang)
{
string str = TranslateString(o.Name, lang);
if (str != null)
o.Text = str;
}
static private void Translate(ToolStripItem o, string lang)
{
string str = TranslateString(o.Name, lang);
if (str != null)
o.Text = str;
}
static private void Translate(Form o, string lang)
{
string str = TranslateString(o.Name, lang);
if (str != null)
o.Text = str;
}
/// <summary>
/// returns the <c>name</c> string from the <c>lang</c> resource
/// </summary>
/// <param name="name">string/key name</param>
/// <param name="lang">the language to translate to</param>
/// <returns>a translated string for <c>name</c></returns>
static public string TranslateString(string name, string lang)
{
if (lang_ci == null || !lang_ci.TwoLetterISOLanguageName.Equals(lang))
lang_ci = new CultureInfo(lang);
try
{
return rm.GetString(name, lang_ci);
}
catch (Exception)
{
// no translation yet
try
{
return rm.GetString(name, default_ci);
}
catch (Exception)
{
return null;
//MessageBox.Show(ex.Message.ToString(), name);
//System.Console.WriteLine(ex.Message.ToString());
}
}
}
static public void TranslateForm(string lang, Form parent)
{
if (rm == null)
rm = new ResourceManager("etimet.i18nResources.i18n", Assembly.GetExecutingAssembly(), null);
if (default_ci == null)
default_ci = new CultureInfo("en");
// handle direction
if (Program.conf.CurrentLang.Equals("he") || Program.conf.CurrentLang.Equals("ar") || Program.conf.CurrentLang.Equals("fa"))
{
parent.RightToLeft = RightToLeft.Yes;
}
else
{
parent.RightToLeft = RightToLeft.No;
}
// translate the form itself
Translate(parent, lang);
// translate all the children controls, recursively
Control.ControlCollection c = parent.Controls;
foreach (Control o in c)
{
// special handling for the menu
if (o.GetType() == typeof(MenuStrip))
{
foreach (ToolStripMenuItem it in ((MenuStrip)o).Items)
{
Translate(it, lang);
//MessageBox.Show(it.Text);
foreach (ToolStripItem f in it.DropDownItems)
{
if (typeof(ToolStripSeparator) != f.GetType())
Translate(f, lang);
}
}
}
RecursiveTranslateCtrl(lang, o);
}
}
static private void RecursiveTranslateCtrl(string lang, Control ctrl)
{
Translate(ctrl, lang);
foreach (Control c in ctrl.Controls)
{
RecursiveTranslateCtrl(lang, c);
}
}
}
}发布于 2011-02-11 14:40:18
有内置的机制可以自动切换整个表单以使用区域性特定资源文件中的文本,而且它比仅仅设置text属性(例如ToolTips)更强大。您需要手动从资源文件加载的唯一时间是消息框之类的东西,但是除非您需要在显示警报的同时阻止应用程序,否则最好使用同样可本地化的气球提示。这是一个容易开始的地方。它也将更有效,因为控件本身是本地化的,因此不需要遍历任何东西。
发布于 2011-02-10 19:51:43
您可以通过在ToolStripItem上使用公共超类来避免重载:
static private void Translate(ToolStripItem o, string lang)
{
string str = TranslateString(o.Name, lang);
if (str != null)
c.Text = str;
}不幸的是,这只适用于这两种组件类型,因为它看起来像Component没有Name和Text属性。
https://codereview.stackexchange.com/questions/721
复制相似问题