WinForms 应用程序的正确本地化

发布于 2024-07-30 08:14:28 字数 1279 浏览 8 评论 0 原文

我有一个 WinForms 应用程序,我想将其翻译成多种语言。 但是,我没有任何本地化 WinForms 应用程序的经验,并且我发现有关此主题的信息非常矛盾。

基本上,我想要的是:

  • 在源代码中,我只需要每种语言一个文件
  • 该文件在编译时编译到主应用程序中 - 构建应用程序后没有卫星程序集或外部数据文件
  • 用户可以选择语言,我愿意不需要/想要基于操作系统的自动检测
  • 这应该主要包含 stringsints,但也包含 CultureInfo

我见过的大多数解决方案可以看到每个 Form 都有一个 .resx 文件和/或外部附属程序集。

  • 我必须自己动手吗?
  • 或者框架中已经有一些东西了?

.net Framework 3.5 SP1(如果有的话)。

编辑:

在大多数情况下,Visual Studio 已经提供了对我想要的支持,但有两个问题。 当我将 Form.Localized 设置为 true 时,我获得了很好的 Designer 支持,但这会为每个 resx 生成一个 resx代码>表单。 在 InitializeComponent 中手动覆盖它的想法失败了,因为它是设计者编写的代码,会定期被覆盖。

理论上,我只想:

  • a) 重写 ComponentResourceManager 的创建,将其指向我的全局 resx
  • b) 更改对 ApplyResources 的调用> 以 CultureInfo 作为第三个参数的重载。

似乎我必须向构造函数添加一个函数调用,该函数调用在 InitializeComponent() 之后调用并覆盖其行为。 这看起来效率极低,但 Visual Studio 在警告触摸 InitializeComponent() 时是正确的。

目前,我确实正在推出自己的 WinForms 本地化框架...

I have a WinForms application which I want to translate into multiple languages. However, I do not have any experience with localizing a WinForms app, and I find very contradictory information about this subject.

Basically, what I want is:

  • In the source code, I want only one file per language
  • This file gets compiled into the main application on compilation - no satellite assemblies or external data files after building the application
  • The user can select the language, I do not need/want auto-detection based on the operating system
  • This should mainly contain strings and ints, but also a CultureInfo

Most solutions I've seen either have one .resx file per Form and/or external satellite assemblies.

  • Do I have to roll my own?
  • Or is there something in the framework already?

.net Framework 3.5 SP1 if that matters.

Edit:

For the most part, Visual Studio already offers support for what I want, but there are two issues. When I set Form.Localizable to true I have this nice Designer support, but this generates one resx per Form. The idea of manually overriding it in InitializeComponent fails because it's designer-written code that will regularly be overwritten.

Theoretically, I only want to :

  • a) override the creation of the ComponentResourceManager to point it to my global resx and
  • b) change the call to ApplyResources to the overload that takes a CultureInfo as third parameter.

It seems as if I have to add a function call to my constructor that gets called after InitializeComponent() and overrides its behaviour. That seems terribly inefficient, but Visual Studio is right when it warns about touching InitializeComponent().

At the moment, I am indeed rolling my own WinForms localization Framework...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

后来的我们 2024-08-06 08:14:29

这是一个巨大的主题,有很多方法可以实现您想要的目标。 该框架确实提供了基础,但完整的解决方案需要您自己实现某些元素。

例如,默认框架实现是为每个资源创建一个 .resx 文件。 在 ASP.Net 中,这意味着每个用户/服务器控件或页面。 这不利于维护,如果您想将资源移动到数据库,您需要实现自己的提供程序。

我对 Winforms 的熟悉程度有限,但如果您使用 Silverlight 或 WPF,请阅读 Guy Smith-Ferrier 关于该主题的著作,网址为:http://www.guysmithferrier.com/category/Internationalization.aspx。 他还提供了一些可以让您的生活更轻松的工具集:http://www.dotneti18n.com/Downloads .aspx

我以前曾与他共事过,但从未遇到过对这个主题有更深入理解的人。

This is a huge subject and there are many ways to accomplish what you want. The framework does provide the basis but a complete solution requires that you implement certain elements yourself.

For example the default framework implementation is to create a .resx file for every resource. In ASP.Net this means each user/server control or page. This doesn't lend itself to easy maintenance and if you want to move resources to a database you need to implement your own provider.

My familiarity with Winforms is limited but if you are using Silverlight or WPF then have a read of Guy Smith-Ferrier's work on the subject at: http://www.guysmithferrier.com/category/Internationalization.aspx. He also has some toolsets that can make your life easier at: http://www.dotneti18n.com/Downloads.aspx.

I've worked with him before and have never come across anyone else with a better depth of understanding of the subject.

秋意浓 2024-08-06 08:14:29

您的要求是:

  1. 没有卫星资源文件,
  2. 每个表单只有一种大小和控制位置。
  3. 可执行文件中嵌入了许多语言。

在普通 Visual Studio 的 IDE 中无法实现。

它需要一些自定义工作,基本上完成所有这些步骤:

  • 获取处理 TMX 资源文件的自定义资源管理器。
  • 将所有可本地化的字符串放入 TMX 文件中。
    • 将此 TMX 文件作为嵌入项目中的资源。
  • 在 Form 构造函数中,创建 TMX ResourceManager,从嵌入式资源加载 TMX 文件。
  • 在您的代码中,使用 tmx ResourceManager 而不是默认的 ResourceManager 来获取本地化字符串。
    • 让表单使用默认的 ResourceManager 来获取除字符串之外的所有设计器内容。
  • 使用新的语言翻译充实您的 TMX 文件。
    • 可以在项目的下一个版本中添加更多内容,只需在编译之前将它们添加到此 TMX 文件即可。

资源:(无论如何都不是详尽的列表)

What you are asking for:

  1. no satellite resource files
  2. only one size and control placement per form.
  3. lots of languages embedded in the executable.

Is not do-able in vanilla Visual Studio's IDE.

What it would require is some custom work, basically fulfilling all these steps:

  • Acquire a custom resource manager that handles TMX resource files.
  • Put all your localizable strings in a TMX file.
    • Make this TMX file an embedded resource in your project.
  • In your Form constructor, create your TMX ResourceManager, loading the TMX file from your embedded resources.
  • In your code, use your tmx ResourceManager instead of the default ResourceManager for getting localized strings.
    • Let the Form use the default ResourceManager for getting all the designer things except the strings.
  • Get your TMX file fleshed out with the new language translations.
    • More can be added in the next release of your project, just by adding them to this TMX file before you compile.

RESOURCES: (not an exhaustive list, by any means)

伤痕我心 2024-08-06 08:14:29

正确的方法是,假设您要添加 Arabic 支持,即 RightToLeft 语言:

  1. 双击表单
  2. Set localized prop。 为 true
  3. Change Language 属性。 阿拉伯语 //这将自动打开新版本的表单,以便您可以自定义。
  4. 设置 RightToLeft 属性。 设置为 Yes
  5. 设置 RightToLeftLayout 属性。 为 True
  6. 开始重命名控件,并保存表单。
  7. 处理代码中的消息/错误 // 抱歉,我现在没有快速的解决方案,请尝试复制它们并 If/Else 当前本地。

The right way to do this is, suppose you want to add Arabic support witch is RightToLeft language:

  1. Double click the form
  2. Set localizable prop. to true
  3. Change Language prop. to Arabic //This will automatically open a new version of the form so you can customize.
  4. Set RightToLeft prop. to Yes
  5. Set RightToLeftLayout prop. to True
  6. Start renaming controls, and save the form.
  7. Handle Messages/Errors in code // Sorry I don't have a quick solution for now, try duplicate them and If/Else the current local.
⒈起吃苦の倖褔 2024-08-06 08:14:29

虽然这是一篇相当老的文章,但它仍然很有趣。 我为我的项目提出了一个解决方案,最终意味着很少的努力,并且使控件的代码免于本地化内容...

为需要本地化的所有内容创建一个界面

public interface ILocalizable
{
    void Localize();
}

现在创建您想要的控件的子类使用(表单、按钮、标签、菜单...)并让他们实现界面。

public class LocalizableForm : Form, ILocalizable
{
    public LocalizableForm() => Load += LocalizableForm_Load;

    private void LocalizableForm_Load(object? sender, EventArgs e) => Localize();

    [Browsable(true)]
    [Category("Localization")]
    public string? TextResourceKey { get; set; }

    public void Localize()
    {
        if (!string.IsNullOrWhiteSpace(TextResourceKey))
            Text = TextResources.ResourceManager.GetString(TextResourceKey);

        Controls.LocalizeCollection();

        if(IsMdiContainer)  
            MdiChildren.LocalizeCollection();
    }
}

这可以将您的实际表单从本地化代码中解放出来,因为您所要做的就是在设计器中设置 ResourceKey:

VS 设计器中属性部分的屏幕截图

在运行时,实际字符串将从中央资源文件 (TextResources.resx和 TextResources.DE.resx 在我的例子中)

为了方便起见,我添加了一个扩展方法来调用子控件或菜单​​项等集合中的元素上的 Localize()

public static void LocalizeCollection(this IEnumerable collection)
{
    foreach (var item in collection)
    {
        if (item is ILocalizable localizable)
        {
            localizable.Localize();
        }
    }
}

Although this is a pretty old post, it's still very interesting. I came up with a solution for my project that in the end means very little effort and leaves the code of the controls free of localisation stuff...

Create an interface for everything that needs to be localized

public interface ILocalizable
{
    void Localize();
}

Now create sub classes of the controls you want to use (forms, buttons, labels, menues...) and let them implement the interface.

public class LocalizableForm : Form, ILocalizable
{
    public LocalizableForm() => Load += LocalizableForm_Load;

    private void LocalizableForm_Load(object? sender, EventArgs e) => Localize();

    [Browsable(true)]
    [Category("Localization")]
    public string? TextResourceKey { get; set; }

    public void Localize()
    {
        if (!string.IsNullOrWhiteSpace(TextResourceKey))
            Text = TextResources.ResourceManager.GetString(TextResourceKey);

        Controls.LocalizeCollection();

        if(IsMdiContainer)  
            MdiChildren.LocalizeCollection();
    }
}

This frees your actual forms from localization code since all you have to do is set the ResourceKey in the designer:

screeshot of Properties section in VS designer

At runtime the actual strings will be taken from the central resource files (TextResources.resx and TextResources.DE.resx in my case)

For convenience I added an extension method to call Localize() on elements in collections like sub controls or menu items

public static void LocalizeCollection(this IEnumerable collection)
{
    foreach (var item in collection)
    {
        if (item is ILocalizable localizable)
        {
            localizable.Localize();
        }
    }
}
佞臣 2024-08-06 08:14:28

我刚刚完成了一个 C# .Net 3.5 项目,也遇到了类似的问题。 我们正在为现有的 8 种语言(包括英语)的多语言应用程序编写 WinForms 插件。

我们是这样做的:

  1. 使用默认语言英语创建所有表单和 UI。

  2. 将所有内部字符串放入资源文件中(不直接与自定义错误消息和对话框标题等表单相关的内容)

一旦我们完成了大部分工作和测试,我们就对其进行了本地化。

  1. 每个表单已有一个 .resx 文件,但该文件是空的。 我们将属性“可本地化”设置为 true,.resx 文件中填充了诸如按钮大小和按钮大小之类的内容。 字符串。

  2. 对于其他每种语言,我们更改了表单上的“语言”属性。 我们选择了每种语言的基本版本,例如:“西班牙语”而不是“西班牙语(智利)”等。我认为,这样它就适用于每种“西班牙语”方言。

  3. 然后我们检查每个控件,翻译其文本并根据需要调整大小。 这为每种语言和表单组合创建了一个 .resx。

然后,对于 8 种语言,每种形式有 8 个 .resx,一般字符串有 8 个 .resx。 编译时,输出文件夹包含我们正在创建的 .dll,然后是每种语言的子文件夹,其中包含 .resources.dll。

我们只需更改语言属性即可测试设计器中的 UI 版本,以检查我们是否拥有正确的字符串和字符串。 布局。

总而言之,一旦我们明白了这一点,一切就变得非常简单且无痛。

我们不需要为表单加载编写任何自定义调整

I've just completed a C# .Net 3.5 project with a similar problem. We were writing WinForms plugin for an existing multi-lingual application with 8 languages (including English).

This is how we did it:

  1. Create all our forms and UI in the default language, English.

  2. Put all our internal strings in a resource file (stuff not tied directly to a form like custom error messages and dialog box titles etc)

Once we had completed most of the work and testing we localised it.

  1. Each form already had a .resx file but this was empty. We set the property 'Localizable' to true, the .resx file was filled with things like button sizes & strings.

  2. For each of the other languages, we changed the 'Language' property on the form. We chose the basic version of each language eg: 'Spanish' instead of 'Spanish (Chile)' etc. so that it would work for every 'Spanish' dialect, I think.

  3. Then we went through each control, translated its text and resized, if needed. This created a .resx per language and form combination.

We were then left with, for 8 languages, 8 .resx for each form and 8 .resx for the general strings. When compiled the output folder had the .dll we were creating and then a sub folder for each language with a .resources.dll in it.

We were able to test the versions of the UI in the designer by just changing the language property to check that we had the correct strings & layout.

All in all once we got our heads around it, it was quite easy and painless.

We didn't need to write any custom tweaks to the form loading

北方的韩爷 2024-08-06 08:14:28

我问了一个关于 ASP.NET 的类似问题,并得到了第一个答案 - 这个工具及其工作流程可能也适合您 - 看看: Lingobit Localizer

它似乎能够加载您的 Winforms 应用程序,并允许您开始翻译标签等,并在执行时查看表单。 还有许多其他功能,例如增量翻译和翻译记忆库(如果您一遍又一遍地使用相同的术语)。

看起来很有前途(对于 Winforms)——不过我自己还没有使用过它。

这是潜在 .NET 本地化工具的广泛列表 - 不确定它们的工作效果如何以及有何作用它们涵盖了 - 看看吧,也许您会找到您正在寻找的东西。

马克

I was asking a similar question about ASP.NET and got a first answer - this tool and its workflow might also be something for you - have a look: Lingobit Localizer

It seems to be able to load your Winforms app and allows you to start translating your labels etc. and see the forms while you do it. Lots of other features, too, like incremental translation and translation memory (if you use the same terms over and over again).

Looks quite promising (for Winforms) - haven't used it myself, though.

Here's an extensive list of potential .NET localization tools - not sure, how well they work and what they cover - have a look, maybe you'll find what you're looking for.

Marc

何以笙箫默 2024-08-06 08:14:28

我没有满足您的第一个和第二个要求的解决方案,但请记住,本地化表单并不像翻译每个单词那么简单。 您需要检查每个翻译的文本是否适合其各自的控件。 另外,也许您有一个图标或图像需要在另一种文化中进行更改。

对于第三点,您可以使用以下行手动更改语言:

CultureInfo ci = new CultureInfo("fr");
Thread.CurrentThread.CurrentUICulture = ci; 

I dont have a solution for your first and second requirement but keep in mind that localizing a form is not as simple as translating each word. You need to check that each translated text fits in their respective control. Also, maybe you have an icon or an image which need to be change in another culture.

For your point three, you can change the language manually with the following lines:

CultureInfo ci = new CultureInfo("fr");
Thread.CurrentThread.CurrentUICulture = ci; 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文