How can I determine the order of the languages set by the user in the Language tab of the International preference pane?

Q: How can I determine the order of the languages set by the user in the Language tab of the International preference pane?

A: As documented at Internationalization Programming Topics: Getting the Current Language and Locale, most developers do not need to deal with the order of the languages as the appropriate localization will be chosen by the system automatically, and for a finer control, developers can use the CFBundle localization-related APIs.

But there may be situations where you want to get the list of languages directly from the user preferences.

Retrieving the languages in Cocoa

The documentation explains how to retrieve this list with a Cocoa example:

Listing 1: Retrieving the languages in Cocoa (short).

NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
NSArray * languages = [defaults objectForKey:@"AppleLanguages"];
NSLog(@"%@\n", languages);

which would return the following printout:

Listing 2: Languages printout.

(en, fr, de, es, it, nl, sv, nb, ja, "zh-Hans", da, fi, pt, "zh-Hant", ko, hu)

It may be worthwhile to note that the code could also have been written as:

Listing 3: Retrieving the languages in Cocoa (expanded).

NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
NSDictionary * globalDomain = [defaults persistentDomainForName:@"NSGlobalDomain"];
NSArray * languages = [globalDomain objectForKey:@"AppleLanguages"];
NSLog(@"%@\n", languages);

Since the AppleLanguages key is in the global domain of the user defaults.

Note: Running this code on different versions of Mac OS X will printout different results. Mac OS X v10.4 (Tiger) is using the standard canonical form as defined by BCP 47 / RFC 4646. Older versions of Mac OS X might use the English name instead (for instance, "Japanese" instead of "ja") or older forms (for instance, "zh_TW" instead of "zh-Hant" for Traditional Chinese).

Since you cannot count on the data to be in canonical form, it is imperative that you use the CFLocale APIs to convert the entries of the AppleLanguages dictionary in canonical forms.

If you are building your code for Mac OS X v10.4 and later, you can use the CFLocaleCreateCanonicalLanguageIdentifierFromString API.

If you are building your code for Mac OS X v10.3 (Panther) and later, you can use the CFLocaleCreateCanonicalLocaleIdentifierFromString API.

If you are building your code for Mac OS X v10.2 (Jaguar) or earlier, you will have to use your own table mapping non-canonical forms to canonical forms.

Back to Top 

Retrieving the languages in Terminal

In Terminal, you could obtain the exact same printout with:

Listing 4: Retrieving the languages in Terminal (expanded).

defaults read NSGlobalDomain AppleLanguages

or

Listing 5: Retrieving the languages in Terminal (short).

defaults read -g AppleLanguages

Back to Top 

Retrieving the languages in Carbon

To retrieve this order of languages in Carbon you use:

Listing 6: Retrieving the languages in Carbon.

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

which would printout:

Listing 7: Carbon Languages printout.

<CFArray 0x30a5d0 [0xa07ba150]>{type = immutable, count = 16, values = (
  0 : <CFString 0x309b10 [0xa07ba150]>{contents = "en"}
  1 : <CFString 0x30a4c0 [0xa07ba150]>{contents = "fr"}
  2 : <CFString 0x30a4d0 [0xa07ba150]>{contents = "de"}
  3 : <CFString 0x30a4e0 [0xa07ba150]>{contents = "es"}
  4 : <CFString 0x30a4f0 [0xa07ba150]>{contents = "it"}
  5 : <CFString 0x30a500 [0xa07ba150]>{contents = "nl"}
  6 : <CFString 0x30a510 [0xa07ba150]>{contents = "sv"}
  7 : <CFString 0x30a520 [0xa07ba150]>{contents = "nb"}
  8 : <CFString 0x30a530 [0xa07ba150]>{contents = "ja"}
  9 : <CFString 0x30a540 [0xa07ba150]>{contents = "zh-Hans"}
  10 : <CFString 0x30a560 [0xa07ba150]>{contents = "da"}
  11 : <CFString 0x30a570 [0xa07ba150]>{contents = "fi"}
  12 : <CFString 0x30a580 [0xa07ba150]>{contents = "pt"}
  13 : <CFString 0x30a590 [0xa07ba150]>{contents = "zh-Hant"}
  14 : <CFString 0x30a5b0 [0xa07ba150]>{contents = "ko"}
  15 : <CFString 0x30a5c0 [0xa07ba150]>{contents = "hu"}
)}

Note: The AppleLanguages array is set for the user's account if the account was created by Setup Assistant or the Accounts preference pane. This array may be NULL or corrupted if the account was created in a different manner and your code should deal gracefully with unexpected situations.

Back to Top 

Document Revision History

DateNotes
2006-12-19First Version

Posted: 2006-12-19


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.