如何在 C# 中使用本地化

发布于 2024-07-27 05:01:38 字数 108 浏览 5 评论 0原文

我似乎无法让本地化发挥作用。

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

我怎样才能做到这一点?

I just can't seem to get localization to work.

I have a class library. Now I want to create resx files in there, and return some values based on the thread culture.

How can I do that?

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

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

发布评论

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

评论(9

暖心男生 2024-08-03 05:01:38
  • 通过执行以下操作,将资源文件添加到您的项目(您可以将其称为“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”资源,因此它将回退到默认值,这是我们从一开始就添加的资源,

如果您可以创建包含更具体资源的文件 。需要(例如 strings.fr-FR.resx 和 strings.fr-CA.resx 分别用于法国和加拿大的法语)。因此,如果法国和加拿大的文本相同,则可以将其放入 strings.fr.resx,而加拿大法语中不同的字符串可以放入 strings.fr-CA.resx。

  • Add a Resource file to your project (you can call it "strings.resx") by doing the following:
    Right-click Properties in the project, select Add -> New Item... in the context menu, then in the list of Visual C# Items pick "Resources file" and name it strings.resx.
  • Add a string resouce in the resx file and give it a good name (example: name it "Hello" with and give it the value "Hello")
  • Save the resource file (note: this will be the default resource file, since it does not have a two-letter language code)
  • Add references to your program: System.Threading and System.Globalization

Run this code:

Console.WriteLine(Properties.strings.Hello);

It should print "Hello".

Now, add a new resource file, named "strings.fr.resx" (note the "fr" part; this one will contain resources in French). Add a string resource with the same name as in strings.resx, but with the value in French (Name="Hello", Value="Salut"). Now, if you run the following code, it should print Salut:

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

What happens is that the system will look for a resource for "fr-FR". It will not find one (since we specified "fr" in your file"). It will then fall back to checking for "fr", which it finds (and uses).

The following code, will print "Hello":

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

That is because it does not find any "en-US" resource, and also no "en" resource, so it will fall back to the default, which is the one that we added from the start.

You can create files with more specific resources if needed (for instance strings.fr-FR.resx and strings.fr-CA.resx for French in France and Canada respectively). In each such file you will need to add the resources for those strings that differ from the resource that it would fall back to. So if a text is the same in France and Canada, you can put it in strings.fr.resx, while strings that are different in Canadian french could go into strings.fr-CA.resx.

伪装你 2024-08-03 05:01:38

实际上,这很简单。 创建一个新的资源文件,例如 Strings.resx。 将访问修饰符设置为公共。 使用适当的文件模板,Visual Studio 将自动生成一个访问器类(在本例中,名称为 Strings)。 这是您的默认语言。

现在,当您想要添加德语本地化时,请添加本地化的 resx 文件。 在这种情况下,这通常是Strings.de.resx。 如果您想添加额外的本地化(例如奥地利),您还需要创建一个 Strings.de-AT.resx

现在创建一个字符串 - 假设一个名为 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 和 de-CH)时,以及“Hello, World!”当您的语言环境是其他语言时。在本地化版本中缺少,资源管理器将自动沿着链向上移动,从最专业的资源到不变的资源,

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

It's quite simple, actually. Create a new resource file, for example Strings.resx. Set Access Modifier to Public. Use the apprioriate file template, so Visual Studio will automatically generate an accessor class (the name will be Strings, in this case). This is your default language.

Now, when you want to add, say, German localization, add a localized resx file. This will be typically Strings.de.resx in this case. If you want to add additional localization for, say, Austria, you'll additionally create a Strings.de-AT.resx.

Now go create a string - let's say a string with the name HelloWorld. In your Strings.resx, add this string with the value "Hello, world!". In Strings.de.resx, add "Hallo, Welt!". And in Strings.de-AT.resx, add "Servus, Welt!". That's it so far.

Now you have this generated Strings class, and it has a property with a getter HelloWorld. Getting this property will load "Servus, Welt!" when your locale is de-AT, "Hallo, Welt! when your locale is any other de locale (including de-DE and de-CH), and "Hello, World!" when your locale is anything else. If a string is missing in the localized version, the resource manager will automatically walk up the chain, from the most specialized to the invariant resource.

You can use the ResourceManager class for more control about how exactly you are loading things. The generated Strings class uses it as well.

白鸥掠海 2024-08-03 05:01:38

此外,@Fredrik Mörk 对字符串的精彩回答,要添加本地化到表单,请执行以下操作:

  • 设置表单的属性“可本地化”更改为 true
  • 将表单的 Language 属性更改为您想要的语言(从包含所有内容的漂亮下拉列表中)
  • 翻译该表单中的控件,并在需要时移动它们be(压缩那些非常长的完整法语句子!)

编辑:这个 有关本地化 Windows 窗体 的 MSDN 文章不是我链接的原始文章...但如果需要的话可能会提供更多信息。 (旧的已经被拿走了)

In addition @Fredrik Mörk's great answer on strings, to add localization to a form do the following:

  • Set the form's property "Localizable" to true
  • Change the form's Language property to the language you want (from a nice drop-down with them all in)
  • Translate the controls in that form and move them about if need be (squash those really long full French sentences in!)

Edit: This MSDN article on Localizing Windows Forms is not the original one I linked ... but might shed more light if needed. (the old one has been taken away)

樱娆 2024-08-03 05:01:38

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”)

Great answer by F.Mörk. But if you want to update translation, or add new languages once the application is released, you're stuck, because you always have to recompile it to generate the resources.dll.

Here is a solution to manually compile a resource dll. It uses the resgen.exe and al.exe tools (installed with the sdk).

Say you have a Strings.fr.resx resource file, you can compile a resources dll with the following batch:

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

Be sure to keep the original namespace in the file names (here "WpfRibbonApplication1")

凉薄对峙 2024-08-03 05:01:38

修复并阐述了 @Fredrik Mörk 答案。

  • strings.resx 资源文件添加到您的项目(或不同的文件名)
  • Access Modifier 设置为 Public(在打开的 strings 中) .resx 文件选项卡)
  • 在 resx 文件中添加字符串资源:(示例:名称 Hello,值 Hello
  • 资源文件

保存Visual Studio 自动生成的 相应的 strings 类,它实际上放置在 strings.Designer.cs 中。 该类与您期望放置新创建的 .cs 文件位于同一命名空间中。

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

Console.WriteLine(strings.Hello);

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

  • 添加 strings.fr.resx (法语)
  • 添加一个与之前名称相同但值不同的字符串:(name < code>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 有何不同。

A fix and elaboration of @Fredrik Mörk answer.

  • Add a strings.resx Resource file to your project (or a different filename)
  • Set Access Modifier to Public (in the opened strings.resx file tab)
  • Add a string resouce in the resx file: (example: name Hello, value Hello)
  • Save the resource file

Visual Studio auto-generates a respective strings class, which is actually placed in strings.Designer.cs. The class is in the same namespace that you would expect a newly created .cs file to be placed in.

This code always prints Hello, because this is the default resource and no language-specific resources are available:

Console.WriteLine(strings.Hello);

Now add a new language-specific resource:

  • Add strings.fr.resx (for French)
  • Add a string with the same name as previously, but different value: (name Hello, value Salut)

The following code prints Salut:

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

What resource is used depends on Thread.CurrentThread.CurrentUICulture. It is set depending on Windows UI language setting, or can be set manually like in this example. Learn more about this here.

You can add country-specific resources like strings.fr-FR.resx or strings.fr-CA.resx.

The string to be used is determined in this priority order:

  • From country-specific resource like strings.fr-CA.resx
  • From language-specific resource like strings.fr.resx
  • From default strings.resx

Note that language-specific resources generate satellite assemblies.

Also learn how CurrentCulture differs from CurrentUICulture here.

擦肩而过的背影 2024-08-03 05:01:38

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

每种特定的文化都有不同的名称,例如 resources.nl.resx、resources.fr.resx、resources.de.resx……

现在解决方案最重要的部分是维护您的翻译。
在 Visual Studio 中安装 Microsoft MAT 工具:多语言应用程序工具包 (MAT)。
适用于 winforms、wpf、asp.net(核心)、uwp...

一般情况下,例如对于 WPF 解决方案,在 WPF 项目中

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

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

您现在唯一要做的就是:

  1. 将翻译添加到默认的 resources.resx 文件(在我的例子中是英语)中,
  2. 通过单击 .xlf 文件(不是 .resx 文件)进行翻译,因为 .xlf 文件将生成/更新.resx 文件。

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

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

更多信息:

In general you put your translations in resource files, e.g. resources.resx.

Each specific culture has a different name, e.g. resources.nl.resx, resources.fr.resx, resources.de.resx, …

Now the most important part of a solution is to maintain your translations.
In Visual Studio install the Microsoft MAT tool: Multilingual App Toolkit (MAT).
Works with winforms, wpf, asp.net (core), uwp, …

In general, e.g. for a WPF solution, in the WPF project

  • Install the Microsoft MAT extension for Visual Studio.
  • In the Solution Explorer, navigate to your Project > Properties > AssemblyInfo.cs
  • Add in AssemblyInfo.cs your default, neutral language (in my case English): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • Select your project in Solution Explorer and in Visual Studio, from the top menu, click "Tools" > "Multilingual App Toolkit" > "Enable Selection", to enable MAT for the project.
    • Now Right mouse click on the project in Solution Explorer, select "Multilingual App Toolkit" > "Add translation languages…" and select the language that you want to add translations for. e.g. Dutch.

What you will see is that a new folder will be created, called "MultilingualResources" containing a ....nl.xlf file.

The only thing you now have to do is:

  1. add your translation to your default resources.resx file (in my case English)
  2. Translate by clicking the .xlf file (NOT the .resx file) as the .xlf files will generate/update the .resx files.

(the .xlf files should open with the "Multilingual Editor", if this is not the case, right mouse click on the .xlf file, select "Open With…" and select "Multilingual Editor".

Have fun! now you can also see what has not been translated, export translations in xlf to external translation companies, import them again, recycle translations from other projects etc...

More info:

久光 2024-08-03 05:01:38

就我而言

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

,AssemblyInfo.cs 阻止了一切正常工作。

In my case

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

in the AssemblyInfo.cs prevented things to work as usual.

黎夕旧梦 2024-08-03 05:01:38

除了@Eric Bole-Feysot 的回答之外:

由于卫星程序集,可以基于 .dll/.exe 文件创建本地化。 这样:

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

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

In addition to @Eric Bole-Feysot answer:

Thanks to satellite assemblies, localization can be created based on .dll/.exe files. This way:

  • source code (VS project) could be separated from language project,
  • adding a new language does not require recompiling the project,
  • translation could be made even by the end-user.

There is a little known tool called LSACreator (free for non-commercial use or buy option) which allows you to create localization based on .dll/.exe files. In fact, internally (in language project's directory) it creates/manages localized versions of resx files and compiles an assembly in similar way as @Eric Bole-Feysot described.

冷月断魂刀 2024-08-03 05:01:38

您可以使用 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) );
    }
}

You could use Lexical.Localization¹ which allows embedding default value and culture specific values into the code, and be expanded in external localization files for futher cultures (like .json or .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) );
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文