NSIS调用GetLocaleInfo获取区域信息出现乱码问题求助
解决NSIS中获取法语区域信息出现乱码的问题
嘿,这个乱码问题我之前做多语言安装包时也踩过坑!核心原因是你用了ANSI版本的Win32 API,和NSIS的字符串处理机制不兼容,导致法语的特殊字符(比如重音)变成乱码。下面给你拆解问题和解决方案:
问题根源
你调用的GetLocaleInfoA是ANSI编码版本的函数,它返回的字符串是系统当前ANSI代码页的编码结果。但NSIS内部是基于**Unicode(UTF-16)**处理字符串的,直接接收ANSI编码的法语字符就会出现编码转换错误,表现为乱码。
解决方案:改用宽字符版本API
Win32提供了对应的宽字符版本GetLocaleInfoW,我们需要用这个函数,同时把NSIS的字符串参数类型从t(ANSI)改成w(宽字符),这样就能正确接收Unicode格式的区域信息了。
方案1:直接获取fr-FR格式的语言标签
如果你目标就是拿到fr-FR这种标准语言标签,不用拆分获取语言和国家,直接用LOCALE_SNAME常量(值为0x5C),它会直接返回符合RFC 4646规范的完整标签:
!define LOCALE_SNAME '0x5C' ; 返回标准语言标签,如"fr-FR" !define LOCALE_SISO639LANGNAME 0x00000059 ; ISO语言缩写,如"fr" !define LOCALE_SISO3166CTRYNAME 0x0000005A ; ISO国家缩写,如"FR" Function getLocale ; 获取系统默认语言ID(可选) System::Call 'kernel32::GetSystemDefaultLangID() i .r0' ; 直接获取完整语言标签(推荐) System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SNAME}, w .r1, i ${NSIS_MAX_STRLEN}) i r0' ; 也可以组合ISO缩写得到fr-FR System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SISO639LANGNAME}, w .r2, i ${NSIS_MAX_STRLEN}) i r0' System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SISO3166CTRYNAME}, w .r3, i ${NSIS_MAX_STRLEN}) i r0' StrCpy $4 "$2-$3" ; 拼接成fr-FR MessageBox MB_OK|MB_ICONINFORMATION "系统语言ID: $0$\r$\n完整语言标签: $1$\r$\n组合ISO标签: $4" FunctionEnd
方案2:修复原有原生名称的乱码问题
如果你需要获取法语原生名称(比如français、France),只需要把原有代码里的GetLocaleInfoA换成GetLocaleInfoW,同时把参数里的t改成w即可:
!define LOCALE_ILANGUAGE '0x1' !define LOCALE_SLANGUAGE '0x2' !define LOCALE_SNATIVELANGNAME '0x4' !define LOCALE_SNATIVECTRYNAME '0x8' Function getLocale System::Call 'kernel32::GetSystemDefaultLangID() i .r0' ; 全部改用GetLocaleInfoW和w类型参数 System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SNATIVELANGNAME}, w .r1, i ${NSIS_MAX_STRLEN}) i r0' System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SNATIVECTRYNAME}, w .r2, i ${NSIS_MAX_STRLEN}) i r0' System::Call 'kernel32::GetLocaleInfoW(i 1024, i ${LOCALE_SLANGUAGE}, w .r3, i ${NSIS_MAX_STRLEN}) i r0' MessageBox MB_OK|MB_ICONINFORMATION "系统语言ID: $0$\r$\n原生语言名称: $1$\r$\n原生国家名称: $2$\r$\n区域信息: $3" FunctionEnd
额外注意点
- 代码里的
1024是LOCALE_SYSTEM_DEFAULT的常量值,如果你想获取用户当前设置的区域信息,可以换成0x800(LOCALE_USER_DEFAULT)。 - NSIS的
System::Call中,w代表宽字符字符串,对应Win32的LPWSTR类型,必须和GetLocaleInfoW配合使用,否则依然会出问题。
内容的提问来源于stack exchange,提问作者sinsedrix
相关产品推荐
相关产品推荐

