2

Windows 似乎至少跟踪“当前语言环境”的四个维度: http ://www.siao2.com/2005/02/01/364707.aspx

  • 默认用户区域
  • 默认系统语言环境
  • 默认用户界面语言
  • 默认输入语言环境

我只是想跟踪四个不同的语言环境到底有什么用处,我的大脑很痛……

但是,我不了解代码页和语言环境(或LCID,或语言 ID)之间的关系,所有这些似乎都不同(例如,日语(日本)是 LANGID = 0x411 位置代码 1,但日本的代码页是932)。

在 Unicode 和窄字符串之间转换时,如何配置我们的应用程序以使用用户所需的语言作为默认 MBCS 目标?

也就是说,我们曾经是一个MBCS应用。然后我们切换到Unicode。事情在英语中运行良好,但在亚洲语言中失败,显然是因为 Windows 转换功能WideCharToMultiByteMultiByteToWideChar采用显式代码页(不是区域设置 ID 或语言 ID),可以设置为CP_ACP(默认为 ANSI 代码页),但不要似乎具有“默认为用户的默认界面语言的代码页”的值。

我的意思是,这是一些非常复杂的废话。“当前语言”的四个独立维度,三种不同的标识符类型,以及 C 库和 C++ 标准库的(不同的)字符串标识符。

在我们之前的 MBCS 版本中,磁盘 I/O 和用户 I/O 工作正常:一切都保留在默认系统区域(Windows XP 术语:“非 Unicode 程序的语言”)中。但是现在,在我们的 UNICODE 构建中,一切都试图使用“C”作为语言环境,并且文件 I/O 无法正确地将 UNICODE 转码为用户的语言环境,反之亦然。

我们希望使用当前用户语言的代码页写出文本文件(当缩小时)。并且在读入时,当前用户的语言代码页应转换回 UNICODE。

帮助!!!

澄清:理想情况下,我希望使用 MUI 语言代码页而不是操作系统默认代码页。GetACP() 返回系统默认代码页,但我不知道返回用户选择的 MUI 语言的函数(如果未指定/安装 MUI,它将自动恢复为系统默认值)。

4

4 回答 4

2

我同意 Jon Trauntvein 的评论,该GetACP功能确实反映了控制面板中用户的语言设置。此外,根据您提供的“全部整理”博客的链接,默认用户界面语言是 Windows 用户界面将使用的语言,与程序使用的语言不同。

但是,如果您真的想使用默认用户界面语言,那么您可以通过调用获得它GetUserDefaultUILanguage,然后您可以使用下表将语言 ID 映射到代码页。 语言标识符和语言环境

您也可以使用该GetLocaleInfo函数进行映射,但首先您必须将获得的语言 ID 转换GetUserDefaultUILanguage为区域设置 ID,我认为您将获得代码页的名称而不是数值,但是您可以试试看。

于 2013-08-20T03:46:06.113 回答
1

如果您只想配置一个语言环境对象以使用当前选择的语言环境设置,您应该能够执行以下操作:

std::locale loc = std::locale("");

您还可以使用 Win32 ::GetACP() 函数访问 Windows 中的当前代码页。这是我在字符串类中实现的一个示例,用于将多字节字符附加到 unicode 字符串:

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();
    }
}
于 2013-08-19T18:18:26.323 回答
0

只需使用 CW2A() 或 CA2W() 即可使用当前系统区域设置(或用于非 Unicode 应用程序的语言)为您处理转换。

于 2015-08-27T23:19:10.403 回答
0

FWIW,这就是我最终做的事情:

  1. #define _CONVERSION_DONT_USE_THREAD_LOCALE // force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
  2. 在应用程序启动中,构建所需的语言环境:m_locale(FStringA(".%u", GetACP()).GetString(), LC_CTYPE)
  3. 强制它同意 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

这让我可以相对理想地使用 MFC 在 CString 中内置的窄<-> 宽转换,以便在与当前语言环境的 MBCS 字符串相互转换时自动使用用户的默认语言。

注:m_locale是类型::std::locale

于 2016-11-15T21:16:07.327 回答