如何在C#中使用本地化


268

我似乎无法本地化工作。

我有一个班级图书馆。现在,我想在其中创建resx文件,并根据线程区域性返回一些值。

我怎样才能做到这一点?


PS:确保已为Visual Studio安装了免费的Microsoft MAT(多语言应用程序工具包)扩展程序;-)
juFo

Answers:


571
  • 通过执行以下操作,将资源文件添加到您的项目中(可以将其称为“ strings.resx”):
    右键单击项目中的“ 属性 ”,在上下文菜单中选择“ 添加”->“新建项... ”,然后在列表中Visual C#项目选择“资源文件”并将其命名strings.resx
  • 在resx文件中添加一个字符串资源,并给它起一个好名字(例如:将其命名为“ Hello”,并为其赋予值“ Hello”)
  • 保存资源文件(注意:这是默认设置资源文件,因为它没有两个字母的语言代码)
  • 添加引用您的程序:System.ThreadingSystem.Globalization

运行此代码:

Console.WriteLine(Properties.strings.Hello);

它应该打印“ Hello”。

现在,添加一个名为“ strings.fr.resx”的新资源文件(请注意“ fr”部分;该文件将包含法语资源)。添加一个与strings.resx中名称相同的字符串资源,但其值以法语显示(Name =“ Hello”,Value =“ Salut”)。现在,如果您运行以下代码,它将显示Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);

发生的情况是系统将寻找“ fr-FR”的资源。它不会找到一个(因为我们在文件中指定了“ fr”),然后便退回到检查(找到并使用)的“ fr”。

下面的代码,将打印“ Hello”:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

那是因为它找不到任何“ en-US”资源,也找不到“ en”资源,因此它将回退到默认值,这是我们从一开始就添加的资源。

如果需要,您可以使用更具体的资源创建文件(例如,分别在法国和加拿大使用French的strings.fr-FR.resx和strings.fr-CA.resx)。在每个这样的文件中,您将需要为那些与后备资源不同的字符串添加资源。因此,如果文本在法国和加拿大是相同的,则可以将其放在strings.fr.resx中,而在加拿大法语中不同的字符串可以输入strings.fr-CA.resx。


24
答案可以参考Visual Studio在此处执行的“幕后”管道:resx.designer.cs文件,使智能工作;使用类库编译的附属程序集,需要与已编译的程序集以及使用该程序集的任何更高版本的项目一起部署,等等。答案很好,很简单,但是它无助于说明哪里可能出问题了,例如您不使用Visual Studio。

13
+1讯息!与其手动制作文件,不如尝试Zeta资源编辑器(zeta-resource-editor.com/index.html)。它是免费的,可以帮助您比在VS中更快地完成这类翻译。
Killnine 2012年

4
Access Modifier应该设置Public要生成的资源类。该类不一定位于Properties命名空间中,而是在其中放置.resx文件的位置。
安德烈·莫伊谢夫

3
请注意,在VS 2017中,由于错误(至少在15.4版之前),在winform中进行本地化的resx无法正常工作。可以购买票:developercommunity.visualstudio.com/content/problem/63772/…–
muccix

4
从.NET 4.5开始,也可以使用System.Globalization.CultureInfo.DefaultThreadCurrentCulture代替Thread.CurrentThread.CurrentUICulture,以便更改整个应用程序的语言环境,而不是逐个线程地
更改

41

实际上,这很简单。创建一个新的资源文件,例如Strings.resx。设置Access ModifierPublic。使用适当的文件模板,因此Visual Studio将自动生成访问器类(Strings在这种情况下,名称为)。这是您的默认语言。

现在,当您想添加德语本地化时,请添加本地化的resx文件。Strings.de.resx在这种情况下通常是这样。如果您想为例如奥地利添加其他本地化,则将另外创建一个Strings.de-AT.resx

现在创建一个字符串-假设一个名为name的字符串HelloWorld。在您的中Strings.resx,将此字符串添加为值“ Hello,world!”。在中Strings.de.resx,添加“ Hallo,Welt!”。然后在Strings.de-AT.resx中添加“ Servus,Welt!”。到此为止。

现在,您有了这个生成的Strings类,并且它具有带有getter的属性HelloWorld。获取此属性将加载“ Servus,Welt!”。当您的语言环境为de-AT时,“ Hallo,Welt!”(当您的语言环境为其他任何语言环境(包括de-DE和de-CH)时),“ Hello,World!”(当您的语言环境为其他任何语言时)。如果本地化版本中缺少该资源,资源管理器将自动从最专业的资源到不变的资源,沿着链条向上移动。

您可以使用ResourceManager该类来更好地控制加载内容的精确度。生成的Strings类也使用它。


如何设置语言环境?
Matheus Simon

1
@MatheusSimon:不需要。默认情况下,使用用户的当前语言环境。如果要强制使用某个区域设置(例如,允许用户手动更改语言),则必须在每个线程中设置System.Threading.Thread.CurrentCulture和CurrentUICulture ,这可能在首次加载任何资源之前进行。为此,重新启动应用程序比在运行时更新更容易。
OregonGhost

15

除了@FredrikMörk关于字符串的好答案之外,要在表单中添加本地化,请执行以下操作:

  • 表单的属性设置"Localizable"true
  • 将表单的Language属性更改为所需的语言(从一个不错的下拉菜单中将它们全部放入)
  • 翻译该形式的控件,并在需要时将其移动(将那些很长的完整法语句子挤进去!)

编辑:这篇关于本地化Windows窗体的MSDN文章不是我链接的原始文章 ……但是,如果需要的话,可能会引起更多注意。(旧的已被拿走)


msdn文章不再可用,是否有替代品?
fuomag9

不确定-我已经链接了我所能看到的最好的文章,但我不记得7年前的文章是什么;)
noelicus

14

F.Mörk的很好答案。但是,如果要在应用程序发布后更新翻译或添加新语言,则会遇到麻烦,因为您始终必须重新编译它才能生成resources.dll。

这是手动编译资源dll的解决方案。它使用resgen.exe和al.exe工具(与sdk一起安装)。

假设您有一个Strings.fr.resx资源文件,则可以使用以下批处理来编译资源dll:

resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
del WpfRibbonApplication1.Strings.fr.resources
pause

确保将原始名称空间保留在文件名中(此处为“ WpfRibbonApplication1”)


2
感谢您对保留名称空间(y)的评论,该名称空间(如果丢失)不会产生任何错误,而只是还原为后备资源。
Mosca Pt

11

@FredrikMörk答案的修正和详细说明。

  • strings.resx资源文件添加到您的项目(或其他文件名)
  • 设置Access ModifierPublic(在打开的strings.resx文件选项卡中)
  • 在resx文件中添加字符串资源:(例如:name Hello,value Hello
  • 保存资源文件

Visual Studio自动生成一个相应的strings类,该类实际上位于中strings.Designer.cs。该类与您希望将新创建的.cs文件放在相同的名称空间中。

始终打印此代码Hello,因为这是默认资源,并且没有特定于语言的资源可用:

Console.WriteLine(strings.Hello);

现在添加一个新的特定于语言的资源:

  • 添加strings.fr.resx(法语)
  • 添加一个与以前具有相同名称但值不同的字符串:(name Hello,value Salut

以下代码显示Salut

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(strings.Hello);

使用哪种资源取决于Thread.CurrentThread.CurrentUICulture。可以根据Windows UI语言设置进行设置,也可以像本示例一样手动设置。在这里了解更多信息。

您可以添加特定于国家的资源,例如strings.fr-FR.resxstrings.fr-CA.resx

要使用的字符串按以下优先级顺序确定:

  • 来自特定国家/地区的资源,例如 strings.fr-CA.resx
  • 来自特定语言的资源,例如 strings.fr.resx
  • 从默认 strings.resx

请注意,特定于语言的资源会生成附属程序集

还要了解CurrentCultureCurrentUICulture 这里有何不同。


1

就我而言

[assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]

AssemblyInfo.cs中的内容阻止了一切正常运行。


0

除了@Eric Bole-Feysot答案:

多亏了附属程序集,可以基于.dll / .exe文件创建本地化。这条路:

  • 源代码(VS项目)可以与语言项目分开,
  • 添加新语言不需要重新编译项目,
  • 甚至可以由最终用户进行翻译。

有一个鲜为人知的工具,称为LSACreator(非商业用途或购买选项免费),它使您可以基于.dll / .exe文件创建本地化。实际上,它在内部(在语言项目的目录中)创建/管理resx文件的本地化版本,并以与@Eric Bole-Feysot所述类似的方式编译程序集。


0

ResourceManager和.resx有点混乱。

您可以使用Lexical.Localization¹,它允许将默认值和区域性特定值嵌入代码中,并可以在外部本地化文件中扩展以进行进一步的区域性(例如.json或.resx)。

public class MyClass
{
    /// <summary>
    /// Localization root for this class.
    /// </summary>
    static ILine localization = LineRoot.Global.Type<MyClass>();

    /// <summary>
    /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
    /// </summary>
    static ILine ok = localization.Key("Success")
            .Text("Success")
            .fi("Onnistui")
            .sv("Det funkar");

    /// <summary>
    /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
    /// </summary>
    static ILine error = localization.Key("Error")
            .Format("Error (Code=0x{0:X8})")
            .fi("Virhe (Koodi=0x{0:X8})")
            .sv("Sönder (Kod=0x{0:X8})");

    public void DoOk()
    {
        Console.WriteLine( ok );
    }

    public void DoError()
    {
        Console.WriteLine( error.Value(0x100) );
    }
}

¹(我是该库的维护者)


0

通常,您将翻译内容放在资源文件中,例如resources.resx。

每个特定区域性都有不同的名称,例如resources.nl.resx,resources.fr.resx,resources.de.resx,…

现在,解决方案中最重要的部分是维护翻译。在Visual Studio中,安装Microsoft MAT工具:Multilingual App Toolkit(MAT)。适用于winforms,wpf,asp.net(核心),uwp等。

通常,例如,对于WPF解决方案,在WPF项目中

  • 安装Visual Studio的Microsoft MAT扩展。
  • 在解决方案资源管理器中,导航到项目>属性> AssemblyInfo.cs
  • 在AssemblyInfo.cs中添加默认的中性语言(在我的情况下为英语): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • 在解决方案资源管理器中选择您的项目,然后在Visual Studio中,从顶部菜单中单击“工具”>“多语言应用程序工具包”>“启用选择”,以为项目启用MAT。
    • 现在,右键单击解决方案资源管理器中的项目,选择“多语言应用工具包”>“添加翻译语言...”,然后选择要为其添加翻译的语言。例如荷兰语。

您将看到将创建一个包含....nl.xlf文件的名为“ MultilingualResources”的新文件夹。

您现在唯一要做的是:

  1. 将您的翻译添加到默认的resource.resx文件(在我的情况下为英语)
  2. 单击.xlf文件(而不是.resx文件)进行翻译,因为.xlf文件将生成/更新.resx文件。

(.xlf文件应使用“多语言编辑器”打开,如果不是这种情况,请右键单击.xlf文件,选择“打开方式...”,然后选择“多语言编辑器”。

玩得开心!现在您还可以看到尚未翻译的内容,将xlf中的翻译导出到外部翻译公司,再次导入,从其他项目中回收翻译等...

更多信息:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.