关于 CFLocaleCopyCurrent API 不正确的 return 值
Regarding CFLocaleCopyCurrent API incorrect return value
在我的工作场所,我们处于遵循以下独立代码的情况,
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <boost/cast.hpp>
// Reference release
struct reference_close
{
void operator()(const void *ref) const
{
CFRelease(static_cast<CFTypeRef>(ref));
}
}; // end of reference_close structure
typedef std::unique_ptr<const void, reference_close> reference_uptr;
std::string get_user_locale()
{
reference_uptr ref_ptr(CFLocaleCopyCurrent());
CFLocaleRef locale_ref(static_cast<CFLocaleRef>(ref_ptr.get()));
if (locale_ref == nullptr)
{
return std::string();
}
const size_t default_size(128);
std::vector<char> buff(default_size);
CFStringRef str_ref(CFLocaleGetIdentifier(locale_ref));
// CFStringRef str_ref((CFStringRef)CFLocaleGetValue(locale_ref,kCFLocaleLanguageCode));
if (str_ref != nullptr)
{
CFIndex len(CFStringGetLength(str_ref) + 1);
if (len > boost::numeric_cast<CFIndex>(default_size))
{
buff.resize(len);
}
buff[0] = 0;
if (!CFStringGetCString(str_ref, &buff[0], len, kCFStringEncodingISOLatin1))
{
return std::string();
}
}
return std::string(&buff[0]);
} // end of get_user_locale()
int main()
{
std::cout << "get_user_locale() : "<<get_user_locale() << std::endl;
return 0;
}
在 OS X 10.12 和 10.13 beta 上给了我们不同的输出。
简而言之,这就是我们所做的。
在 10.12 机器上
1) 设置首选语言为ru,地区为RU
2) 重启机器
3) 获取 "defaults read -g AppleLocale" 的输出以确保输出是
{
ru_RU
}
4) 编译代码,运行 exe。我们得到的输出为 { ru_RU }.
然后我们在 OS X 10.13(测试版)机器上重复步骤 1) 到 3) 然后 运行 相同的 exe(在 10.12 上创建,你可能会问为什么,这是因为我们在 10.13 机器上的一些内部构建系统限制),我们得到的输出是 "en_RU",这是不正确的。
我们是不是漏掉了什么?或者这是 OS X 10.13 (beta) 中的已知问题?如果是这样,我们该如何解决?
更新
我们还编写了以下 Objective-C 代码来使用 NSLocale 接口,这也给了我们相同的结果,即 ru_RU 在 10.12 和 en_RU 在 10.13(测试版)
#import <Foundation/Foundation.h>
int main()
{
@autoreleasepool
{
NSLog(@"localeIdentifier: %@", [[NSLocale currentLocale] localeIdentifier]);
}
}
我们得到错误值的原因是我们的应用程序未本地化到我们预期的语言环境,例如 ru
。
我们通过在应用程序的 Contents/Resources
目录中添加一个空 ru.lproj
目录来更正此问题,并且 API 开始为我们提供正确答案。
在我的工作场所,我们处于遵循以下独立代码的情况,
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <boost/cast.hpp>
// Reference release
struct reference_close
{
void operator()(const void *ref) const
{
CFRelease(static_cast<CFTypeRef>(ref));
}
}; // end of reference_close structure
typedef std::unique_ptr<const void, reference_close> reference_uptr;
std::string get_user_locale()
{
reference_uptr ref_ptr(CFLocaleCopyCurrent());
CFLocaleRef locale_ref(static_cast<CFLocaleRef>(ref_ptr.get()));
if (locale_ref == nullptr)
{
return std::string();
}
const size_t default_size(128);
std::vector<char> buff(default_size);
CFStringRef str_ref(CFLocaleGetIdentifier(locale_ref));
// CFStringRef str_ref((CFStringRef)CFLocaleGetValue(locale_ref,kCFLocaleLanguageCode));
if (str_ref != nullptr)
{
CFIndex len(CFStringGetLength(str_ref) + 1);
if (len > boost::numeric_cast<CFIndex>(default_size))
{
buff.resize(len);
}
buff[0] = 0;
if (!CFStringGetCString(str_ref, &buff[0], len, kCFStringEncodingISOLatin1))
{
return std::string();
}
}
return std::string(&buff[0]);
} // end of get_user_locale()
int main()
{
std::cout << "get_user_locale() : "<<get_user_locale() << std::endl;
return 0;
}
在 OS X 10.12 和 10.13 beta 上给了我们不同的输出。
简而言之,这就是我们所做的。
在 10.12 机器上
1) 设置首选语言为ru,地区为RU
2) 重启机器
3) 获取 "defaults read -g AppleLocale" 的输出以确保输出是 { ru_RU }
4) 编译代码,运行 exe。我们得到的输出为 { ru_RU }.
然后我们在 OS X 10.13(测试版)机器上重复步骤 1) 到 3) 然后 运行 相同的 exe(在 10.12 上创建,你可能会问为什么,这是因为我们在 10.13 机器上的一些内部构建系统限制),我们得到的输出是 "en_RU",这是不正确的。
我们是不是漏掉了什么?或者这是 OS X 10.13 (beta) 中的已知问题?如果是这样,我们该如何解决?
更新
我们还编写了以下 Objective-C 代码来使用 NSLocale 接口,这也给了我们相同的结果,即 ru_RU 在 10.12 和 en_RU 在 10.13(测试版)
#import <Foundation/Foundation.h>
int main()
{
@autoreleasepool
{
NSLog(@"localeIdentifier: %@", [[NSLocale currentLocale] localeIdentifier]);
}
}
我们得到错误值的原因是我们的应用程序未本地化到我们预期的语言环境,例如 ru
。
我们通过在应用程序的 Contents/Resources
目录中添加一个空 ru.lproj
目录来更正此问题,并且 API 开始为我们提供正确答案。