【发布时间】:2020-03-01 22:54:43
【问题描述】:
在我的工作场所,我们的应用程序通过使用类似于下面的代码来确定用户会话的区域设置(尽管在启动时它到达这里之前要经过各种代码层,所以问题是/运行下面的代码可能不明显)
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 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));
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;
}
该应用程序具有定义明确的捆绑结构,其中包含必要的资源和本地化资源目录,例如Contents/Resources/ja.lproj
最近,我们面临一个问题,我们执行以下操作
1) 更改首选项中的系统语言和国家/地区,例如从 en_US 更改为 ja_JP
2) 重启机器
3) 启动应用程序并查看错误输出,例如 en_JP
4) 重新启动应用程序以获取正确答案为 ja_JP
我已阅读 CFLocaleCopyCurrent 的文档,其中指出
您从此语言环境中获得的设置不会随着用户的设置而改变 首选项已更改,以便您的操作保持一致。 通常,您对返回的对象执行一些操作,然后 释放它。由于返回的对象可能会被缓存,所以不需要 无限期地坚持下去。
我还查看了lifetime of CFLocale 上的另一个文档,其中指出
你从 CFLocaleCopyCurrent 返回的对象不会改变 用户更改其首选项设置。此外,对象 本身可能会被运行时系统缓存,所以连续调用 CFLocaleCopyCurrent 可能返回相同的对象,即使用户有 更改首选项设置。如果您想确保您的语言环境 设置与用户偏好一致,必须同步 首选项并使用 CFLocaleCopyCurrent 获取新的语言环境对象。
鉴于此信息,我尝试将CFPreferencesSynchronize 和/或CFPreferencesSynchronize 合并到应用程序代码中(就在我调用CFLocaleCopyCurrent 之前)以获得最新的语言环境。但没有运气。
我是否需要做任何额外的事情来确保从系统首选项中获取语言环境对象的最新/更新值?
【问题讨论】:
-
为什么不使用
[NSLocale autoupdatingCurrentLocale]?无论如何,这段代码看起来写得很糟糕。 -
@trojanfoe 对于
CFLocale类有没有autoupdatingCurrentLocale的任何C++ 替代品?我发现很难在我的 C++ 代码中混合 Objective C 代码。 -
您只需要在
.mm文件中实现C++,它就会被编译为Objective-C++。我将用一些(未经测试的)示例代码添加答案。 -
CFLocaleCopyCurrent的文档说“当前语言环境的语言可能与用户默认设置的 AppleLanguages 数组中第一个索引处的语言不对应。”。en_JP是正确的。 -
@Willeke 嗯,令人沮丧的是,它第一次返回了错误的语言 (
en_JP),然后更正了一个 (ja_JP)。
标签: c++ macos foundation core-foundation