If your application is properly internationalized, you should rarely have to choose which localization to apply to use. The routines associated with the NSBundle
class and CFBundleRef
opaque type automatically apply the user’s preferences to determine which localized resource files to return in response to a programmatic request. However, there may be situations beyond simply loading resources from a bundle that would require your program to know which localization was in use. For those situations, both NSBundle
and CFBundleRef
provides ways for you to get that information.
Before discussing the techniques of how to get localizations, it is important to remember how a bundle communicates its supported localizations to the system. The directory containing the bundle’s resources can also contain one or more language-specific project (.lproj
) directories. Each of these .lproj
directories contains the resources associated with a specific language or regional dialect. The methods of the NSBundle
class and functions associated with the CFBundleRef
opaque type look for these directories and use them to build a list of supported localizations. However, this is not the only way to build this list.
An application can notify the system that it supports additional localizations through its information property list (Info.plist
) file. To specify localizations not included in your bundle’s .lproj
directories, add the CFBundleLocalizations
key to this file. The value for the key is an array of strings, each of which contains an ISO language designator as described in “Language and Locale Designations.”
If you are using the functions associated with the CFBundleRef
opaque type to manage your program bundle, you can use the CFBundleCopyPreferredLocalizationsFromArray
function to get the most relevant localizations. When calling this method, you must pass in a list of localizations your software supports.
You can also use the function CFBundleCopyBundleLocalizations
to generate this list for you using the bundle information. This function compares your application’s supported localizations against the user’s language and region preferences. The function then returns an array of strings with a handful of localizations. One of them is the language-only localization most appropriate for the user. If a region-specific localization is also available, the function returns it as well, giving it precedence over the language-only localization.
If you are writing your application in Objective-C, you can use the preferredLocalizationsFromArray:
and localizations
methods of the NSBundle
class to implement the same behavior as the CFBundleCopyPreferredLocalizationsFromArray
and CFBundleCopyBundleLocalizations
functions. You can also use the preferredLocalizations
method as a shortcut to perform both actions with a single method. As with the Core Foundation functions, the preferredLocalizations
and preferredLocalizationsFromArray:
methods return an array of strings containing the language designators in use by the bundle.
Prior to Mac OS X v10.4, language dialects were specified by combining a language designator with a region designator. With the introduction of support for custom dialect codes (see “Language and Locale IDs”), getting the appropriate language code is now somewhat more complicated. Fortunately, Mac OS X provides routines to help you determine the appropriate language and locale codes based on the information you have.
In Mac OS X v10.3, the CFLocaleRef
opaque type was introduced in Core Foundation. One of the functions introduced with this type is the CFLocaleCreateCanonicalLocaleIdentifierFromString
function, which takes the locale code you specify and returns an appropriate canonical version. This function is particularly useful for converting older locale strings, such as the older, English-based .lproj directory names, into the ISO-compliant names.
In Mac OS X v10.4, the CFLocaleCreateCanonicalLanguageIdentifierFromString
function was added to perform the same canonical conversion for language and dialect codes. For example, this function converts the old specifier for traditional Chinese (zh_TW
) to the more modern version (zh-Hant
). Also in Mac OS X v10.4, Cocoa added the NSLocale
class to provide Objective-C wrappers for the corresponding Core Foundation functions.
If you use a CFBundleRef
type or NSBundle
object to retrieve language-specific resources from your bundle, then you do not need to worry about language identifiers directly. The CFBundleRef
and NSBundle
routines automatically handle language and locale IDs in canonical and non-canonical forms.
If your code requires Mac OS X v10.4 or later, you should start using the new canonical forms for language and locale IDs. Some older language codes are replaced by newer codes in v10.4. In addition to several of the Chinese language codes, support for the newer Norwegian ISO code (nb
) is now available and should be preferred over the older version.
Note: If your program also supports versions of Mac OS X prior to 10.3, you may need to maintain your own table of canonical IDs.
There may be situations where you want to get the preferred locale ID or the list of languages directly from the user preferences. Mac OS X stores each user’s list of preferred languages in that user’s defaults database. The list of preferred languages is identified by the defaults key AppleLanguages
and is stored in the global variable NSGlobalDomain
. You can access that list using the NSUserDefaults
class in Cocoa or the Core Foundation preferences functions.
Important: If you get the user language preference from the defaults database, you must get the canonical form using the CFLocaleCreateCanonicalLanguageIdentifierFromString
function (in Mac OS X v10.4 and later) or CFLocaleCreateCanonicalLocaleIdentifierFromString
function (in Mac OS X v10.3 and later) before using the identifier.
The following example shows you to get the list of preferred languages from the defaults database using Cocoa. The returned array contains the languages associated with the AppleLanguages
key in the user's preferred order. Thus, in most cases, you would simply want to get the first object in the array.
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults]; |
NSArray* languages = [defs objectForKey:@"AppleLanguages"]; |
NSString* preferredLang = [languages objectAtIndex:0]; |
The locale for the current user is also stored in the defaults database under the AppleLocale
key.
Important: Although you can get the user's preferred settings from the defaults database, it is recommended you use the CFBundleRef
functions or NSBundle
class instead. The associated functions and methods of those objects return the preferred language or locale that is also supported by your application. (Bear in mind that the returned values may not correspond directly with the user's exact preferences.)
Last updated: 2009-08-07