CFLocaleCopy当前过时的值

时间:2019-11-05 14:30:00

标签: c++ macos foundation core-foundation

在我的工作场所,我们的应用通过使用类似于下面的代码来确定用户会话的语言环境(尽管在启动时到达它之前,它经过了许多层代码,所以问题是/通过运行下面的代码可能并不明显)

#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之前),以获取最新的语言环境。但没有运气。

我是否需要做其他任何事情以确保我从系统偏好设置中获得了语言环境对象的最新/更新值?

1 个答案:

答案 0 :(得分:1)

使用[NSLocale autoupdatingCurrentLocale],它会随着用户更改语言环境设置而改变,但是NSLocale是一个Objective-C类,因此您需要将粘合代码实现为Objective-C ++。

下面是一些未经测试的示例代码,为您提供了一个主意:

创建一个名为AppleLocale.mm的文件(当然,除非您的项目仅用于Apple平台,所以不需要Apple名称前缀)。

#include <Foundation/Foundation.h>

std::string get_user_locale()
{
    NSLocale* locale = [NSLocale autoupdatingCurrentLocale];
    return std::string([[locale localeIdentifier] UTF8String]);
}

注意:当然,您还需要一些标头中的函数原型。