windows LoadString 仅在我没有英文字符串表时才有效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1213510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LoadString works only if I don't have an English string table
提问by Csupor Jen?
I want to be able to modify the application's language programatically, or at least use the language specified in Control Panel -> Regional and Language Options -> Formats.
我希望能够以编程方式修改应用程序的语言,或者至少使用在控制面板 -> 区域和语言选项 -> 格式中指定的语言。
If I add an english string table, make a french and a german copy of it, and delete the english one, I can programatically switch between loading the french and the german strings. If I keep the english copy, the english strings get loaded, no matter what, when I try to load the german or the french ones.
如果我添加一个英文字符串表,制作它的法文和德文副本,然后删除英文表,我可以以编程方式在加载法文和德文字符串之间切换。如果我保留英文副本,无论如何,当我尝试加载德语或法语字符串时,都会加载英语字符串。
I think that this is a resource loader bug, and that the resource loader ignores SetThreadLocale, if it finds a string table in the same language as the windows ui language (the language of the windows explorer menus for example).
我认为这是一个资源加载器错误,如果资源加载器找到与 windows ui 语言(例如 windows 资源管理器菜单的语言)相同语言的字符串表,则它会忽略 SetThreadLocale。
I tried to change Control Panel -> Regional and Language Options -> Formats to French, but that has no effect. The resource editor shows the french string table without the language appended, but my program still always loads the english strings. Copying this change to the system account has no effect either.
我尝试将控制面板 -> 区域和语言选项 -> 格式更改为法语,但这没有效果。资源编辑器显示没有附加语言的法语字符串表,但我的程序仍然总是加载英语字符串。将此更改复制到系统帐户也无效。
Here is the code I tried this with:
这是我尝试过的代码:
#include "stdafx.h"
#include <iostream>
#include "windows.h" // this should go to stdafx.h
#include "resource.h" // this should not go to stdafx.h
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// 1036 = french, 1031 = german
SetThreadLocale(MAKELCID(1036, SORT_DEFAULT));
const int maxSize = 100;
wchar_t c[maxSize];
LoadString(GetModuleHandle(NULL), IDS_STRING101, c, maxSize);
std::cout << c;
return 0;
}
Hereis a half wrong, incomplete explanation (in the second half of Method 2). The second workaround proposed there, using only coutry-neutral string tables is useless, because I have separate portuguese-Portugal and portuguese-Brazil string tables.
这里有一半错误,不完整的解释(在方法 2 的后半部分)。那里提出的第二种解决方法,仅使用国家中性字符串表是无用的,因为我有单独的葡萄牙语-葡萄牙和葡萄牙语-巴西字符串表。
The first workaround proposed there does not work. With the code below, I get error 1814.
那里提出的第一个解决方法不起作用。使用下面的代码,我收到错误 1814。
HRSRC r = FindResource(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDS_STRING101),
RT_STRING);
DWORD e = GetLastError();
So, what should I do ? What's the explanation of this strange "bug" ?
所以我该怎么做 ?这个奇怪的“错误”的解释是什么?
LATER EDIT:
稍后编辑:
After some more tests I found out that:
经过一些更多的测试,我发现:
- GetThreadLocale() returns what is set in Control Panel -> Regional and Language Options -> Formats.
- The resource loader bug is essentially that if my program has US English resources too, those resources will be loaded, no matter what is set at Formats. If it does not have US English resources, the language set at Formats will be used.
- If I have a French (Neutral) and a German (Neutral) string table, and I set Formats to French (France), the german strings are loaded. If I add an English (Neutral) string table, the english strings are loaded. So, the neutral culture fallback does not work for what is set at Formats.
- If I add a Neutral string table, that one will be used, even if I have another English (Neutral) or an English (United States) string table.
- GetThreadLocale() 返回在控制面板 -> 区域和语言选项 -> 格式中设置的内容。
- 资源加载器错误本质上是,如果我的程序也有美国英语资源,那么无论格式设置什么,这些资源都会被加载。如果它没有美国英语资源,将使用格式中设置的语言。
- 如果我有一个法语(中性)和一个德语(中性)字符串表,并且我将格式设置为法语(法国),则加载德语字符串。如果我添加英语(中性)字符串表,则会加载英语字符串。因此,中性文化回退对 Formats 中设置的内容不起作用。
- 如果我添加一个中性字符串表,即使我有另一个英语(中性)或英语(美国)字符串表,也会使用该表。
回答by Sogger
Detailed description of how localized resources are selected (including the search order of FindResource) straight from MSDN: Multiple-Language Resources
直接从MSDN:Multiple-Language Resources详细说明如何选择本地化资源(包括FindResource的搜索顺序)
Edit: However, from my experience (at least on Windows XP) the search order detailed for FindResource on that page does not describe the actual behaviour. The actual behaviour seems to be:
编辑:但是,根据我的经验(至少在 Windows XP 上),该页面上 FindResource 的详细搜索顺序并未描述实际行为。实际行为似乎是:
- LANG_NEUTRAL resource
- resource where Lang and SubLang match UI language Lang and SubLang
- resource where Lang matches UI language Lang and resource Sublang is neutral
- resource where Lang and SubLang match locale language Lang and SubLang
- resource where Lang matches locale language Lang and resource Sublang is neutral
- resource with lowest numerical LANGID
- LANG_NEUTRAL 资源
- Lang 和 SubLang 匹配 UI 语言 Lang 和 SubLang 的资源
- Lang 匹配 UI 语言 Lang 且资源 Sublang 中立的资源
- Lang 和 SubLang 匹配区域设置语言 Lang 和 SubLang 的资源
- Lang 匹配区域设置语言 Lang 并且资源 Sublang 是中性的资源
- 具有最低数字 LANGID 的资源
Note: I don't have any sources to validate that list, so if anybody can update or correct anything, please do so.
注意:我没有任何来源来验证该列表,因此如果有人可以更新或更正任何内容,请这样做。
Edit: To understand this behaviour, it is important to recognize the difference between the 'locale' and 'UIlanguage' as explained here: NLS Terminology. The FindResource function language selection is based primarily off of the UI language which is NOT the 'Regional Options' setting in the 'Regional and Language Options' (that is the 'locale' setting, which is the same as calling SetThreadLocale()).
编辑:要了解这种行为,重要的是要认识到“语言环境”和“UIlanguage”之间的区别,如下所述:NLS 术语。FindResource 函数语言选择主要基于 UI 语言,它不是“区域和语言选项”中的“区域选项”设置(即“区域设置”设置,与调用 SetThreadLocale() 相同)。
As far as I can tell, the reason the locale setting or 'SetThreadLocale()' affects FindResource() is because of the exception case described by @Kirill V. Lyadvinsky in one of the answers here, explained in more detail on Michael Kaplan's blog.
据我所知,语言环境设置或“SetThreadLocale()”影响 FindResource() 的原因是@Kirill V. Lyadvinsky 在此处的其中一个答案中描述的异常情况,在Michael Kaplan 的博客上有更详细的解释.
Setting the language for FindResource in code cleanly and deterministically was only made possible with the new function 'SetThreadUILanguage' in Vista onwards. Every place you see that instead uses SetThreadLocale will have hacks to make it work and/or have issues when the UI language changes (ie: Foreign language windows install).
只有在 Vista 之后的新函数“SetThreadUILanguage”中,才能在代码中干净且确定地设置 FindResource 的语言。您看到的每个使用 SetThreadLocale 的地方都会有一些技巧来使其工作和/或在 UI 语言更改时出现问题(即:安装外语窗口)。
回答by Rob
Are you running Vista or Windows 7? If so then SetThreadLocale
doesn't work (even though it returns TRUE, sigh) and you have to use SetThreadUILanguage
.
您运行的是 Vista 还是 Windows 7?如果是这样,则SetThreadLocale
不起作用(即使它返回 TRUE,叹气)并且您必须使用SetThreadUILanguage
.
I have just completed a WTL app that has been translated into 7 different languages and the user can switch languages without the problems you are describing. I am using SetThreadLocale
on XP and SetThreadUILanguage
on Vista/7.
我刚刚完成了一个已被翻译成 7 种不同语言的 WTL 应用程序,用户可以在没有您描述的问题的情况下切换语言。我SetThreadLocale
在 XP 和SetThreadUILanguage
Vista/7 上使用。
More info:
更多信息:
回答by Kirill V. Lyadvinsky
The catch here is that if the thread locale is the same as the currently selected user locale, system's resource loader will by default use the language ID 0 (neutral). If the desired resource is defined as a neutral language, then this value will be returned. Otherwise, all of the language resources will be enumerated (in language ID order) and the first matching resource ID – regardless of its language – will be returned.
这里的问题是,如果线程区域设置与当前选择的用户区域设置相同,系统的资源加载器将默认使用语言 ID 0(中性)。如果所需资源定义为中性语言,则将返回此值。否则,将枚举所有语言资源(按语言 ID 顺序),并返回第一个匹配的资源 ID(无论其语言如何)。
The only way to control resources is to use separate resource DLLs for each language.
控制资源的唯一方法是为每种语言使用单独的资源 DLL。