【问题标题】:Localization in C# ApplicationC# 应用程序中的本地化
【发布时间】:2011-03-15 17:41:08
【问题描述】:

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

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

我想知道是否可以获取一些关于执行此操作的最简单/最佳方法的示例。

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

例如,我通常会在MyApplication.Properties.Settings.Default.SomeKey 的地方使用MyApplication.Languages.Current.ApplicationTitleMyApplication.Languages.en.ApplicationTitle

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

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

您对此有何看法?


编辑:

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

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

【问题讨论】:

  • 你的意思是什么“来自windows的语言资源”?
  • 假设 Windows 通常会在系统上的 dll 文件中存储语言行,我可以将它们导入到我的应用程序中,这样我就可以节省写作时间,只是一般的表单文本,例如 File,@ 987654326@,Options,Error 等。这样可行吗?
  • 我认为这没有意义。您将花费更多时间调查所有 Windows 资源,为什么?客户有自己的框架(英语、西班牙、德国...),框架通过使用本地化消息显示他们的系统消息(警告、错误)。您的应用程序有自己的文本资源。所以请准备好翻译它们。没有魔法,只有工作..工作..工作.. :)。
  • 我认为伊戈尔是对的。本地化的整个想法是,最后,你有一个文件可以发送给翻译,你的整个应用程序将被翻译成新的语言。因此我们的非高效代码。 :-)

标签: c# localization internationalization


【解决方案1】:

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

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

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

【讨论】:

  • 好的,但我不想加载所有语言资源,如果可能的话,只需要导入一种语言,所以我可以有lang.en.dlllang.de.dll 女巫将从中加载设置名称空间中的语言?或者通过这种方式对应用程序速度没有任何影响?
  • 只会加载一个资源dll。在我的德语机器上,AppName.de.dll 将被加载,在英语机器上,AppName.en.dll 将被加载。
  • 看起来很有趣,在这种情况下,我看看我能用它做什么。感谢您的帮助。
  • 我们可以在应用程序级别而不是表单级别实现这一点,如果可以,有没有办法跨表单使用通用的?例如,如果我们有“保存”这个词,我们可以用它来做所有事情吗?
  • @MustafaMagdy:是的,您可以通过使用资源文件并直接访问它们或通过 ResourceManager 类从任何类(包括表单)访问它们,从而在应用程序级别实现这一点(对不起,我迟到的回复,我从 12 月 19 日开始休假。:))
【解决方案2】:

你应该使用资源。

您可以动态更改语言:

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();
}

【讨论】:

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

我们使用 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) );
    }

【讨论】:

  • 如果我有很多需要翻译的元素,这对我来说并不高效,基本上我想要在我的设计器代码中 this.LoginLabel.Text = Language.Current.LoginLabel; 所以我不必担心系统会加载需要的语言?
  • 我不明白。 this.LoginLabel.Text = Language.Current.LoginLabel; 有什么区别?和 menuItem11.Text = Resources.MyResources.Nieuw; ??我们不再在设计器中进行翻译,因为这会产生很多(可怕的)设计器错误。
  • 好吧,问题不在于代码的方式,我只想用语言包中的文本加载文本标签,而不是让我创建一个新方法并单独分配所有元素新的文本值。
猜你喜欢
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 2014-03-26
相关资源
最近更新 更多