问题:
我在Windows 7上开发了一个C#.NET 2.0应用程序,它已经为多种语言翻译了资源(例如 zh-CHS 用于中文, es 用于西班牙语等)。
我的客户想用英语运行他们的Windows 7操作系统,但是用西班牙语运行我的.NET应用程序( es )。
我的应用程序是多线程的,所以只是改变主GUI线程的文化不足以满足我的需求(相信我,我试过)。这是因为通过GUI向用户显示的其他字符串是在其他线程上生成的。为了获得100%的完整覆盖率,我需要手动设置每个单独线程的文化,以确保资源文件中的所有文本都使用正确的语言。因为我的产品基本上是其他开发组编写的其他插件的框架,所以我无法控制在其他插件中创建的线程中执行的操作。因此,手动更改每个线程的区域性不是一个有效选项。
我正在寻找的是一种为应用程序设置整体语言的方法,而无需更改任何操作系统用户设置。
在进行一些研究时,我遇到了以下方法来设置流程的首选UI语言:SetProcessPreferredUILanguages
在阅读完之后,看来这个电话就是我要找的。但是,当我在C#应用程序的Main方法中实现此调用时,它似乎没有做任何事情。
以下代码的返回值为true,但我从未看到我的GUI应用程序以西班牙语显示文本。
[DllImport("Kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern Boolean SetProcessPreferredUILanguages(UInt32 dwFlags, String pwszLanguagesBuffer, ref UInt32 pulNumLanguages);
public void SetLanguages()
{
uint numLangs = 0;
string[] langs = new string[3];
uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention
langs[0] = "es\u0000";
langs[1] = "zh-CHS\u0000";
langs[2] = "en-US\u0000";
numLangs = (uint)langs.Length;
if (SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, String.Concat(langs), ref numLangs))
{
Console.WriteLine("Successfully changed UI language");
}
}
为了在加载西班牙语资源的情况下成功运行我的GUI应用程序,我还缺少其他东西吗?
我正在尝试在Building MUI Applications的MSDN页面底部实现表的第二个选项,其中我有特定于应用程序的UI语言设置,并希望实现所需的资源加载结果:
应用程序调用MUI API来设置特定于应用程序的UI语言或流程首选的UI语言,然后调用标准资源 加载功能。资源以。所设置的语言返回 应用程序或系统语言。
我已成功调用成功设置进程首选UI语言,但我的资源没有按照我期望的语言加载。一位评论者提到这个调用仅适用于未管理的资源,我无法100%验证,但行为似乎表明情况就是这样。
我不可能是唯一一个试图以这种方式实现.NET应用程序的人。令人沮丧的是,没有更多关于如何做到这一点的信息。
提前致谢,
凯尔
答案 0 :(得分:0)
根据此处的反馈和其他研究,我得出的结论是,使用早于4.5的.NET版本无法为独立于操作系统语言的多线程.NET应用程序设置文化。
这真是太遗憾了。
我们最近将软件升级为使用.NET 4.0。
答案 1 :(得分:0)
从.NET 4.5开始,CultureInfo.DefaultThreadCurrentCulture属性允许您为当前应用程序域中的线程设置默认区域性。除此之外,我还没有找到一种方法来优雅地做到这一点。
以下代码将向您展示如何重现此行为:
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
namespace SimpleMultithreadedTestForCulture {
class Program {
static void Main() {
const double value = 12345.78;
Console.WriteLine("Value from local thread - default culture: {0}", value.ToString("C"));
CultureInfo myCulture = new CultureInfo(Thread.CurrentThread.CurrentUICulture.Name);
myCulture.NumberFormat.CurrencySymbol = "₤";
Thread.CurrentThread.CurrentUICulture = myCulture;
Thread.CurrentThread.CurrentCulture = myCulture;
Console.WriteLine("Value from local thread - 'my' culture: {0}", value.ToString("C"));
Task.Factory.StartNew(() => Console.WriteLine("Value from a different thread: {0}", value.ToString("C")));
Console.ReadKey();
}
}
}
输出:
Value from local thread - default culture: $12,345.78
Value from local thread - 'my' culture: £12,345.78
Value from a different thread: $12,345.78
这是一个related question,它有一个可能的.NET 4.0或之前的解决方案,使用帮助程序类来创建你的线程。即使他们在那里谈论WPF,它也适用于其他.NET多线程应用程序。
我知道你不想改变每个新线程的文化,但我想不出任何其他有效的替代方案。
答案 2 :(得分:0)
您的代码存在一些问题。不幸的是,问题的解决不会带来请求的行为。
代码应为:
[DllImport("Kernel32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern Boolean SetProcessPreferredUILanguages(UInt32 dwFlags,
String pwszLanguagesBuffer, ref UInt32 pulNumLanguages);
public void SetLanguages()
{
uint numLangs = 0;
string[] langs = new string[4];
uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention
langs[0] = "es\0";
langs[1] = "zh-CHS\0";
langs[2] = "en-US\0";
langs[3] = "\0"; //double null ending
numLangs = (uint)langs.Length;
if (SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, String.Concat(langs), ref numLangs))
{
if (numLangs == langs.Length - 1)
Console.WriteLine("Successfully changed UI language");
else if (numLangs < 1)
Console.WriteLine("No language could be set");
else
Console.WriteLine("Not all languages were set");
}
else
Console.WriteLine("No language could be set");
}
pwszLanguagesBuffer被定义为PCZZWSTR,这意味着宽字符串列表(因此Charset.Unicode),字符串以零字符结尾(不需要使用unicode转义序列),列表以双零字符结尾(因此新的“空语言”;另一种方式是将双\ 0放到最后一种语言)。我还添加了新的调试描述,以测试当前设置的语言,但不幸的是我无法在这里测试它(在工作中),因为该函数需要Win7。
但是如何做到这一点完全不同。见AppLocale
我无法保证,它会适用于您的情况。该应用程序需要Windows XP和更新的(在Windows 7上安装时存在一个小问题;请记住以管理员模式启动安装,否则它将无效)。该应用程序还有另一个更大的问题。从中欧转向西方是不可能的。但它适用于从中欧到希腊以及其他具有不同特征的国家。
我使用此应用程序为某些国家/地区开发旧的(非unicode)应用程序。不幸的是,它在开始时给出了麻烦的警告......