Wednesday, July 16, 2008

How to detect the selected language on Mac OS 10 Tiger/Leopard

I noticed many post on Apple Dev web site of people trying to know what is the current language selected on Mac OS 10 when doing a drag and drop of japanese language before english.

The following code tested on Tiger will work like a charm.

static Boolean s_curLangInited = FALSE;
static Boolean s_bJapanese = FALSE;

if (!s_curLangInited)
CFComparisonResult result;
CFStringEncoding encoding = kCFStringEncodingMacRoman; // = 0;
CFAllocatorRef alloc_default = kCFAllocatorDefault; // = NULL;

// a couple of c string literals.
const char cstr_ja[] = "ja_JP";

// convert from c string to CFString
CFStringRef cf_jaString = CFStringCreateWithCString(alloc_default,cstr_ja,encoding);
//CString curLangStr = AfxGetApp()->GetProfileString(_T("Settings"), _T("Language"), _T("nil"));
CFLocaleRef loc = ::CFLocaleCopyCurrent();
CFStringRef cf_lang = (CFStringRef)::CFLocaleGetValue (loc, kCFLocaleLanguageCode);

CFMutableArrayRef available_locales;
CFArrayRef intersected_locales;
char user_locale[50];
struct direct *file;
DIR *dir;
CFArrayRef prefered_languages;

CFLocaleRef user_locale_ref = CFLocaleCopyCurrent();
CFStringRef user_locale_string_ref = CFLocaleGetIdentifier( user_locale_ref );

/* the prefered language in System, because it can differ from CFLocaleCopyCurrent().
However this prefered language is stored using the general language denotation
that may not include the country code (en,fr,en-GB,...) which is not accepted
by setlocale (setlocale would expect en_US,fr_FR,en_GB,...).

So we retrieve possible locales from /usr/share/locale and intersect them
with the prefered languages using CFBundleCopyLocalizationsForPreferences.
dir = opendir("/usr/share/locale");
available_locales = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
while ((file = readdir(dir)))
/* This filters the 'right' locales (xx_xx.UTF-8) */
if (strstr(file->d_name, ".UTF-8"))
CFArrayAppendValue(available_locales, (void*)CFStringCreateWithCString(kCFAllocatorDefault,
file->d_name, kCFStringEncodingUTF8));

prefered_languages = (CFArrayRef)CFPreferencesCopyValue( CFSTR("AppleLanguages"), kCFPreferencesAnyApplication,
kCFPreferencesCurrentUser, kCFPreferencesAnyHost);

if (prefered_languages)
CFArrayRef intersected_locales = (CFArrayRef)CFBundleCopyLocalizationsForPreferences(available_locales, prefered_languages);
CFStringRef user_language = NULL;

user_language = (CFStringRef)CFArrayGetValueAtIndex(intersected_locales, 0);
CFStringGetCString( user_language, user_locale, sizeof(user_locale), kCFStringEncodingUTF8 );

result = CFStringCompareWithOptions(user_language, cf_jaString, CFRangeMake( 0 ,CFStringGetLength(cf_jaString)), kCFCompareCaseInsensitive);
if (result == kCFCompareEqualTo) {

s_bJapanese = true;
s_bJapanese = false;

No comments: