Can I get a code page from a language preference?
Windows似乎至少跟踪"当前语言环境"的四个方面:
http://www.siao2.com/2005/02/01/364707.aspx
-
默认用户位置
-
默认系统位置
-
预设使用者介面语言
-
默认输入位置
我的大脑只是试图跟踪四个单独的区域设置对您有用的东西而感到痛苦。
但是,我不理解代码页与语言环境(或LCID或语言ID)之间的关系,它们似乎都不同(例如,日语(日本)为LANGID = 0x411位置代码1,但代码页日本是932)。
在Unicode和窄字符串之间转换时,如何配置我们的应用程序以使用用户期望的语言作为默认MBCS目标?
也就是说,我们曾经是MBCS应用程序。然后我们切换到Unicode。事情在英语下运行良好,但在亚洲语言下却失败,这显然是因为Windows转换功能WideCharToMultiByte和MultiByteToWideChar带有显式的代码页(不是区域设置ID或语言ID),可以将其设置为CP_ACP(默认为ANSI代码页),但似乎没有"默认为用户默认界面语言的代码页"的值。
我的意思是,这是一些令人费解的问题。"当前语言"的四个独立维度,三种不同的标识符类型以及C库和C ++标准库的(不同)字符串标识符。
在我们以前的MBCS构建中,磁盘I / O和用户I / O可以正常工作:所有内容保留在DEFAULT SYSTEM LOCALE(Windows XP术语:"非Unicode程序的语言")中。但是现在,在我们的UNICODE构建中,所有内容都尝试使用" C"作为语言环境,并且文件I / O无法将UNICODE正确地转码为用户的语言环境,反之亦然。
我们希望使用当前用户的语言代码页将文本文件写出来(窄时)。并且当读入时,当前用户的语言代码页应转换回UNICODE。
救命!!!
澄清:理想情况下,我想使用MUI语言代码页而不是OS默认代码页。 GetACP()返回系统默认代码页,但是我不知道该函数返回用户选择的MUI语言(如果未指定/未安装MUI,则该语言会自动恢复为系统默认语言)。
-
就我所能阅读的GetACP()文档而言,有关返回默认值的内容一无所获。 以我的经验,它返回与用户在OS中选择的语言环境相关的ID。
-
实际上,已记录@JonTrauntvein GetACP()表示它不遵循用户指定的MUI语言,如果希望了解MUI,则应避免使用。 请参阅msdn.microsoft.com/zh-cn/library/windows/desktop/,特别是:"为了与[MUI]版本兼容,您的应用程序应避免依赖GetACP的调用..."
-
还有谁觉得有必要在不说为什么的情况下投票否决这个问题? 如果您不能支持它,并且说出问题不准确或格式不正确,或者您的推理背后的原因是什么,那么这是没有用的批评。
我同意Jon Trauntvein的评论,GetACP函数的确反映了控制面板中用户的语言设置。另外,基于您提供的"全力以赴"博客的链接,默认用户界面语言是Windows用户界面将使用的语言,与程序所使用的语言不同。
但是,如果您确实要使用DEFAULT USER INTERFACE LANGUAGE,则可以通过调用GetUserDefaultUILanguage来获得它,然后可以使用下表将语言ID映射到代码页。
语言标识符和语言环境
您还可以使用GetLocaleInfo函数进行映射,但是首先您必须将从GetUserDefaultUILanguage获得的语言ID转换为语言环境ID,我认为您将获得代码页的名称,而不是一个数值,但您可以尝试看看。
-
谢谢,那是更多信息,但是它似乎与创建我自己的LCID或LANGID表到代码页的必要性有关,这是一个主要的难题,并且存在维护问题。在我看来,如果操作系统提供Wi??ndows的MUI版本,并且用户界面允许用户独立于操作系统本身选择语言,则我们的软件应该能够获取该语言的代码页...
如果您只想配置一个语言环境对象以使用当前选择的语言环境设置,那么您应该能够执行以下操作:
1
| std::locale loc = std::locale(""); |
您还可以使用Win32 :: GetACP()函数在Windows中访问当前代码页。这是我在字符串类中实现的将多字节字符附加到unicode字符串的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void StrUni::append_mb(char const *buff, size_t buff_len)
{
UINT current_code_page = ::GetACP();
int space_needed;
if(buff_len == 0)
return;
space_needed = ::MultiByteToWideChar(
current_code_page,
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
buff,
buff_len,
0,
0);
if(space_needed > 0)
{
reserve(this->buff_len + space_needed + 1);
MultiByteToWideChar(
current_code_page,
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
buff,
buff_len,
storage + this->buff_len,
space_needed);
this->buff_len += space_needed;
terminate();
}
} |
-
谢谢乔恩。不幸的是,GetACP()返回"非Unicode代码页",而不是"用户区域设置"。天哪,我什至不确定我要" DEFAULT USER LOCALE"而不是" DEFAULT SYSTEM LOCALE"?但是对我来说很直观,如果用户将所需的界面语言设置为"中文(台湾)",那么我们读写的狭窄代码文件应该是与中文(台湾)相对应的任何代码页,而不是中文(即使该操作系统是从中文(PRC)SKU安装的。
-
但是,当前代码页不是将多字节字符串转换为unicode所需的吗?如果需要语言环境,则可以像在std :: locale(")中那样向其传递一个空字符串来构造语言环境。语言环境所涵盖的内容远远超出了预期的字符串编码方式,还涵盖了各种格式的规则。此外,您可能需要在编写文件时考虑使用UTF-8进行字符编码。
-
你也许是对的。我只是不知道。在我看来,Windows从"默认系统区域设置"中提供了独立的"默认用户界面语言"。"默认用户界面语言"与MUI系统相关联,并且使用户可以指定运行软件时要使用的语言,而与OS安装媒体基础语言无关。但是GetACP()仅返回操作系统安装媒体的基本语言,而不返回用户所需的界面语言。如果我不使用他们想要的语言,似乎我不尊重用户的需求。
-
(关于使用utf-8或utf-16文件,将来会很好,但是此软件已经具有用MBCS编写的旧文件,因此必须能够读取所述文件)。
-
当系统使用英语时,我已经成功使用GetACP()来获取代码页,并且为巴西配置了区域设置(葡萄牙语是我唯一的第二语言)。但是,同事也使用英语安装和日语区域语言设置来完成此操作。因此,我推断此函数将返回当前配置的语言,而不是安装语言。
FWIW,这就是我最终要做的事情:
#define _CONVERSION_DONT_USE_THREAD_LOCALE // force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
在应用程序启动中,构造所需的语言环境:m_locale(FStringA(".%u", GetACP()).GetString(), LC_CTYPE)
强制其与GetACP()达成一致:// force C++ and C libraries based on setlocale() to use system locale for narrow strings
m_locale = ::std::locale::global(m_locale); // we store the previous global so we can restore before termination to avoid memory loss
这使我相对理想地使用了CString中MFC内置的窄范围宽转换,以便在从当前语言环境转换为MBCS字符串或从其转换时自动使用用户的默认语言。
注意:m_locale是类型::std::locale
只需使用CW2A()或CA2W(),它们就会使用当前的系统区域设置(或用于非Unicode应用程序的语言)为您完成转换。