CFLocaleCopyCurrent устаревшее значение - PullRequest
0 голосов
/ 05 ноября 2019

На моем рабочем месте наше приложение определяет языковой стандарт пользовательского сеанса, используя код, подобный приведенному ниже (хотя существуют различные уровни кода, через которые он проходит, прежде чем попасть сюда во время запуска, поэтому проблема заключается в том, что/ может быть неочевидно при запуске приведенного ниже кода)

#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 , в которой говорится, что

Настройки, которые вы получаете из этой локали, не меняются, так как настройки пользователя изменяются, чтобы ваши операции были согласованными. Обычно вы выполняете некоторые операции с возвращенным объектом, а затем освобождаете его. Так как возвращаемый объект может быть кэширован, вам не нужно держаться за него бесконечно.

Я также проверил другую документацию по времени жизни CFLocale , в которой говорится, что

Объект, который вы возвращаете из CFLocaleCopyCurrent, не изменяется, когда пользователь изменяет свои настройки предпочтений. Более того, сам объект может кэшироваться системой времени выполнения, поэтому последовательные вызовы CFLocaleCopyCurrent могут возвращать один и тот же объект, даже если пользователь изменил настройки предпочтений. Если вы хотите убедиться, что ваши настройки локали соответствуют пользовательским настройкам, вы должны синхронизировать настройки и получить новый объект локали с CFLocaleCopyCurrent.

Учитывая эту информацию, я попытался включить CFPreferencesSynchronize и /или CFPreferencesSynchronize в коде приложения (непосредственно перед тем, как я вызову CFLocaleCopyCurrent), чтобы получить наиболее обновленную локаль. Но не повезло.

Нужно ли мне что-то делать, чтобы убедиться, что я получил самое последнее / обновленное значение объекта локали из системных настроек?

1 Ответ

1 голос
/ 06 ноября 2019

Используйте [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]);
}

Примечание: вам понадобится прототип функции в некоторых заголовках, конечно.

...