C++ 将三字母语言代码转换为语言标识符(LANGID)

C++ 将三字母语言代码转换为语言标识符(LANGID),c++,winapi,internationalization,C++,Winapi,Internationalization,Win32 API中是否有某种方法可以将指定了LOCALE\u sabbrelangame的GetLocaleInfo()返回的三字母语言代码转换为相应的LANGID或LCID?也就是说,与GetLocaleInfo()通常的做法相反 我试图做的是解析一个资源DLL使用的是什么样的语言,到目前为止,在不涉及任何DLL的情况下,使用格式为nameLNG.DLL的DLL名称,其中LNG是一个三个字母的语言代码,假设存在这样一个函数,似乎是最简单的方法 如果这不容易做到,我想B计划是给我们的语言DLL

Win32 API中是否有某种方法可以将指定了
LOCALE\u sabbrelangame
GetLocaleInfo()
返回的三字母语言代码转换为相应的
LANGID
LCID
?也就是说,与
GetLocaleInfo()
通常的做法相反

我试图做的是解析一个资源DLL使用的是什么样的语言,到目前为止,在不涉及任何DLL的情况下,使用格式为
nameLNG.DLL
的DLL名称,其中
LNG
是一个三个字母的语言代码,假设存在这样一个函数,似乎是最简单的方法


如果这不容易做到,我想B计划是给我们的语言DLL提供一个版本信息资源,在那里指定它们各自的区域性,然后在应用程序中读取它们使用的区域性。

您可以使用枚举已安装的区域性并自己构建映射。我在不久前编写的一个服务中的应用程序初始化期间这样做,到目前为止效果良好

在这种情况下,我建议使用方案B。我通常避免将内容编码到文件名中。如果没有其他原因,使用3个字符的变体并不完美,除非您严格指定要使用的变体-,或

如果您需要提供特定于语言环境的变体,那么您应该仔细查看。基本上,您需要指定语言和国家代码,在某些情况下还需要指定地区代码。无论如何,LCID封装了所有这些优点


我不能完全确定的一点是,资源信息中的langID是否是完整的LCID。参考中列出的代码是LCID,因此我将尝试在VERSIONINFO标头中使用LCID。如果没有,您可以始终将信息作为字符串包含在字符串块中。

不幸的是,没有直接的Win32 API为您提供三个字母缩写的LANGID

它看起来像是您的朋友:-)它已经实现了您的计划B,根据版本信息资源的内容查找LANGID

您要查找的代码片段是int函数

LANGID CLanguageSupport::GetLangIdFromFile(LPCTSTR pszFilename)

当然,缺点是版本信息和DLL名称之间可能不匹配。但你会很快在测试中发现它。如果您让诸如创建DLL之类的工具为您创建DLL,那么您肯定是安全的。

您可以通过调用
GetLocaleInfo()
来获取LangID,方法是为LCType参数调用
LOCAL\u RETURN\u NUMBER\LOCALE\u ILANGUAGE
,就像您传递
LOCALE\u sabbrelangame
以获取三个字母的ISO代码一样。通过将相同的lcid传递给此函数,可以使用ISO代码存储相应的LangID

请注意,MSDN表示,在Vista及以上版本中,不应使用
LOCALE\u ILANGUAGE
来支持
LOCALE\u俚语
,但我相信该评论不适用于使用
LOCALE\u ILANGUAGE
LOCALE\u RETURN\u NUMBER


随着项目的发展,您可能会为每种语言生成几个本地化文件。因此,我建议您将本地化文件存储在以该语言命名的子目录中。微软使用了以LangID命名的目录,例如“1033”作为英语资源目录。我认为使用三个字母的代码会更友好,比如“ENU\name.dll”。在任何情况下,子目录都是一个简单的解决方案,希望不会像更改目标文件名那样使构建过程复杂化。

不幸的是,我没有访问LCID的权限,但希望从语言代码三个字母的首字母缩略词(人造ISO代码)中获得LANGID。FWIW,MS希望我们远离LOCALE_i语言,因为他们希望转换为只使用字符串的“lang id”,一种la.NET文化ID。他们试图说服我们LANGID有一天可能会死,至少Win8+EnumSystemLocales中新支持的语言只给了我一个包含三个字母首字母缩写的列表,对吗?我不确定如何仅使用这些信息构建地图,并且缺少LCID或LANGID来进行翻译?如果EnumSystemLocales的回调函数返回一对LCID和“ISO”字符串,则此解决方案将是完美的。EnumLocalesProc的
EnumLocalesProc
的参数实际上是格式为十六进制数的LCID,并将其转换为字符串。文档对此不太清楚——“指向包含以null结尾的区域设置标识符字符串的缓冲区的指针”。他们没有提到的是,您必须在其上调用类似于
\u tcstoul(lpLocaleString,NULL,16)
的东西,才能将区域设置标识符转换为可用的形式。一旦你有了LCID,你就可以使用
LOCALE\u SISO639LANGNAME
LOCALE\u SISO3166CTRYNAME
GetLocaleInfo()
获得你所需要的。是的,我想我最终会使用这个类,因为你显然已经回避了我们现在面临的不仅仅是一个问题,而是两个问题。我们甚至可以重新实现我几天前拿走的语言子菜单,认为我们切换到MFC机制将是最终结果。哦,好吧。。。