C# 应用程序中的本地化

Localization in C# Application

提问人:RobertPitt 提问时间:7/14/2010 最后编辑:TylerHRobertPitt 更新时间:5/3/2016 访问量:11174

问:

我正在创建一个基于 WinForms / KryptonForms 的 C# 应用程序,由于该应用程序处于开发中途,我心想我最好对本地化进行整理。

作为一个土生土长的PHP程序员(我知道C#是一个全新的水平),我会创建一个类来检测语言,并自动将语言包分配给应用程序。然后使用 Language 对象访问这些值。

我想知道我是否可以获得一些关于最简单/最佳方法的例子。

我个人想要一些类似于应用程序设置的东西

例如,我通常会做的地方,我希望有一个和。MyApplication.Properties.Settings.Default.SomeKeyMyApplication.Languages.Current.ApplicationTitleMyApplication.Languages.en.ApplicationTitle

此外,通过仅加载每个语言文件的单个资源来提高速度也是有益的。

因此,语言以英语加载,西班牙语用户被提升为此应用程序是英语的,他是否想将其更改为西班牙语,他单击“是”,设置得到更新,应用程序重新启动并加载单个西班牙语语言包。

您对此有何看法?


编辑:

该应用程序基于 XMPP 协议并使用 agsXMPP 库。据我了解,每个向我发送其状态的用户也应该发送其系统所在的语言。

因此,基本上,如果有任何方法可以“掌握”存储单个单词并在我的应用程序中使用 的事实,但与此同时,我只是在查看 GUI 文本。__("some string")

C# 本地 国际化

评论

0赞 garik 7/14/2010
你指的是什么“来自Windows的语言资源”?
0赞 RobertPitt 7/14/2010
好吧,假设 Windows 通常会将语言行存储在系统上的 dll 文件中,我是否可以将它们导入我的应用程序,以便节省写作时间,只需,,,等一般格式文本。这可行吗?FileHelpOptionsError
1赞 garik 7/15/2010
我认为这没有意义。您将花费更多时间来调查所有 Windows 资源以及原因?客户端有自己的框架(英语、西班牙、德国等),框架使用本地化消息显示其系统消息(警告、错误)。应用程序有自己的文本资源。因此,请准备好将它们全部翻译。没有魔法,只有工作。工作。。工作。。:).
1赞 Run CMD 7/15/2010
我认为伊戈尔是对的。本地化的整个想法是,最终,您有一个可以发送给翻译人员的文件,您的整个应用程序将被翻译成新语言。因此,我们的代码效率低下。:-)

答:

8赞 Christian 7/14/2010 #1

我们进行本地化的方式是:

  • 将 WinForm 的 “Localizable” 属性设置为 true(这将为该 Form 生成一个新的资源文件,例如包含标签、按钮的文本,以及 z 顺序等)
  • 创建一个 FormName.de.resx 文件(“de”,因为我们是德语),然后将需要本地化的字符串存储在其中(通过 ResourceManager 类访问此资源文件)
  • 对于需要本地化的非 WinForms 代码,我们只需创建单独的资源文件

编译应用后,将创建 AppName.resources.dll。此 dll 包含应用程序的所有资源,然后可以与 Visual Localize 等工具一起使用,将字符串翻译成另一种语言,如英语或西班牙语等。

评论

0赞 RobertPitt 7/14/2010
好的,但是如果可能的话,我不想加载所有语言资源,只需要导入一种语言,那么我可以拥有并且女巫将从设置命名空间中的语言加载吗?或者通过这样做不会对应用程序速度产生任何影响?lang.en.dlllang.de.dll
0赞 Christian 7/14/2010
只会加载一个资源 dll。在我的德语机器上,AppName.de.dll 将在英语机器上加载 AppName.en.dll。
0赞 RobertPitt 7/14/2010
看起来很有趣,在这种情况下,我看不出我能用它做什么。感谢您的帮助。
0赞 Mustafa Magdy 12/19/2011
我们是否可以在应用程序级别而不是表单级别实现这一点,如果是这样,有没有办法跨表单使用通用的;例如,如果我们有“保存”这个词,我们可以用它来做所有的事情吗?
1赞 Christian 1/16/2012
@MustafaMagdy:是的,您可以通过使用资源文件并直接访问它们,或者通过您想要的任何类(包括表单)的 ResourceManager 类在应用程序级别实现这一点(对不起,我迟到了,我从 :) 年 12 月 19 日开始在度假)
1赞 Run CMD 7/14/2010 #2

我们使用 Resources.MyResources.SomeString,它会自动翻译成正确的语言。资源文件名为 MyResources.de-DE.resx、MyResources.nl-BE.resx 等。 方法基本上与项目属性相同。

示例翻译代码:

public void TranslateForm()
{
        menuItem11.Text = Resources.MyResources.Nieuw;
        menuItem12.Text = Resources.MyResources.Verwijderen;
        menuItem13.Text = Resources.MyResources.Kopieren;
}

或者您可以手动完成,例如:

menuItem11.Text = Translator.GetString("New", "de-DE" );

...

    public static string GetString( string varname )
    {
        string resourceName = typeof(Vertaling).Namespace + ".Resources.MyResources";
        ResourceManager rm = new ResourceManager(resourceName, Assembly.GetExecutingAssembly());
        return rm.GetString(varname);
    }

    public static string GetString( string varname, string taalCode )
    {
        string resourceName = typeof(Vertaling).Namespace + ".Resources.MyResources";
        ResourceManager rm = new ResourceManager(resourceName, Assembly.GetExecutingAssembly());
        return rm.GetString(varname, new CultureInfo(taalCode) );
    }

评论

0赞 RobertPitt 7/14/2010
如果我有很多元素需要翻译,这对我来说是没有效率的,基本上我想要在我的设计器代码中,这样我就不必担心事情,因为系统会加载所需的语言?this.LoginLabel.Text = Language.Current.LoginLabel;
0赞 Run CMD 7/14/2010
我不明白。这有什么区别。LoginLabel.Text = Language.Current.LoginLabel;和 menuItem11.Text = Resources.MyResources.Nieuw; ??我们不再在设计器中进行翻译,因为这会带来很多(可怕的)设计器错误。
0赞 RobertPitt 7/14/2010
好吧,问题不在于代码的方式,我只想用语言包中的文本加载文本标签,而不是让我创建一个新方法并单独为所有元素分配新的文本值。
2赞 garik 7/14/2010 #3

您应该使用资源。

您可以动态更改语言:

1) 在控制台应用程序中:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
double a = 100.12;
Console.WriteLine("{0} - {1}", Thread.CurrentThread.CurrentCulture, a);

Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
Console.WriteLine("{0} - {1}", Thread.CurrentThread.CurrentCulture, a);
Console.ReadLine();

2)在WinForms应用程序中,我们可以重新打开表单以应用本地化资源 (在表单设计器中使用 LocalizableLanguage 属性为每种语言自动生成资源):

if (Thread.CurrentThread.CurrentCulture.Name == "en-US")
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");
}
else
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}

double a = 100.12;
textBox1.Text = a.ToString(Thread.CurrentThread.CurrentCulture);

Form1 f = new Form1();
f.ShowDialog();

3)使用许多具有自己本地化的线程

private void button1_Click(object sender, EventArgs e)
{
    // for example main thread language is en-US        

    Thread t = new Thread(StartForm);
    t.CurrentUICulture = new CultureInfo("ru-RU");
    t.Start();
    //t.Join();
}

public static void StartForm()
{
    Form1 f = new Form1();
    f.ShowDialog();
}

评论

0赞 RobertPitt 7/14/2010
您如何自动检测用户的区域设置,我可以从 Windows 本身使用语言资源吗?
0赞 garik 7/14/2010
当应用程序启动时,Thread.CurrentThread.CurrentCulture 会根据 Windows 设置(我的操作系统具有乌克兰语 uk-UA)的值,但我可以更改 Thread.CurrentThread.CurrentCulture 值,然后,例如,我可以将此值保存到某个应用程序设置中,以便在下一个会话中使用。
0赞 garik 7/14/2010
3)使用许多具有自己本地化的线程(请参阅我更新的答案)

上一个:PHP中的国际化

下一个:使用 Node.JS