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 Preferences.app, 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));
}
closedir(dir);

CFPreferencesAppSynchronize(kCFPreferencesAnyApplication);
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;

if(CFArrayGetCount(intersected_locales))
user_language = (CFStringRef)CFArrayGetValueAtIndex(intersected_locales, 0);
if(user_language)
{
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;
}
else
{
s_bJapanese = false;
}

No comments: