2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright 2002-2003, Apple Computer, Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 // Note the header file is in the OpenSource set (stripped to almost nothing), but not the .c file
30 #include <CoreFoundation/CFLocale.h>
31 #include <CoreFoundation/CFString.h>
32 #include <CoreFoundation/CFArray.h>
33 #include <CoreFoundation/CFDictionary.h>
34 #include <CoreFoundation/CFPreferences.h>
35 #include <CoreFoundation/CFCalendar.h>
36 #include <CoreFoundation/CFNumber.h>
37 #include "CFInternal.h"
38 #include <unicode/uloc.h> // ICU locales
39 #include <unicode/ulocdata.h> // ICU locale data
40 #include <unicode/ucurr.h> // ICU currency functions
41 #include <unicode/uset.h> // ICU Unicode sets
42 #include <unicode/putil.h> // ICU low-level utilities
43 #include <unicode/umsg.h> // ICU message formatting
44 #if DEPLOYMENT_TARGET_MACOSX
45 #include <CoreFoundation/CFNumberFormatter.h>
48 #include <unicode/ucol.h>
51 CONST_STRING_DECL(kCFLocaleCurrentLocaleDidChangeNotification
, "kCFLocaleCurrentLocaleDidChangeNotification")
53 static const char *kCalendarKeyword
= "calendar";
54 static const char *kCollationKeyword
= "collation";
55 #define kMaxICUNameSize 1024
57 typedef struct __CFLocale
*CFMutableLocaleRef
;
59 __private_extern__
CONST_STRING_DECL(__kCFLocaleCollatorID
, "locale:collator id")
62 __kCFLocaleKeyTableCount
= 16
67 bool (*get
)(CFLocaleRef
, bool user
, CFTypeRef
*, CFStringRef context
); // returns an immutable copy & reference
68 bool (*set
)(CFMutableLocaleRef
, CFTypeRef
, CFStringRef context
);
69 bool (*name
)(const char *, const char *, CFStringRef
*);
74 // Must forward decl. these functions:
75 static bool __CFLocaleCopyLocaleID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
76 static bool __CFLocaleSetNOP(CFMutableLocaleRef locale
, CFTypeRef cf
, CFStringRef context
);
77 static bool __CFLocaleFullName(const char *locale
, const char *value
, CFStringRef
*out
);
78 static bool __CFLocaleCopyCodes(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
79 static bool __CFLocaleCountryName(const char *locale
, const char *value
, CFStringRef
*out
);
80 static bool __CFLocaleScriptName(const char *locale
, const char *value
, CFStringRef
*out
);
81 static bool __CFLocaleLanguageName(const char *locale
, const char *value
, CFStringRef
*out
);
82 static bool __CFLocaleCurrencyShortName(const char *locale
, const char *value
, CFStringRef
*out
);
83 static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
84 static bool __CFLocaleVariantName(const char *locale
, const char *value
, CFStringRef
*out
);
85 static bool __CFLocaleNoName(const char *locale
, const char *value
, CFStringRef
*out
);
86 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
87 static bool __CFLocaleCalendarName(const char *locale
, const char *value
, CFStringRef
*out
);
88 static bool __CFLocaleCollationName(const char *locale
, const char *value
, CFStringRef
*out
);
89 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
90 static bool __CFLocaleCopyCalendar(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
91 static bool __CFLocaleCopyCollationID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
92 static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
93 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
94 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
95 static bool __CFLocaleCurrencyFullName(const char *locale
, const char *value
, CFStringRef
*out
);
96 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
98 // Note string members start with an extra &, and are fixed up at init time
99 static struct key_table __CFLocaleKeyTable
[__kCFLocaleKeyTableCount
] = {
100 {(CFStringRef
)&kCFLocaleIdentifier
, __CFLocaleCopyLocaleID
, __CFLocaleSetNOP
, __CFLocaleFullName
, NULL
},
101 {(CFStringRef
)&kCFLocaleLanguageCode
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleLanguageName
, (CFStringRef
)&kCFLocaleLanguageCode
},
102 {(CFStringRef
)&kCFLocaleCountryCode
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleCountryName
, (CFStringRef
)&kCFLocaleCountryCode
},
103 {(CFStringRef
)&kCFLocaleScriptCode
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleScriptName
, (CFStringRef
)&kCFLocaleScriptCode
},
104 {(CFStringRef
)&kCFLocaleVariantCode
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleVariantName
, (CFStringRef
)&kCFLocaleVariantCode
},
105 {(CFStringRef
)&kCFLocaleExemplarCharacterSet
, __CFLocaleCopyExemplarCharSet
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
106 {(CFStringRef
)&kCFLocaleCalendarIdentifier
, __CFLocaleCopyCalendarID
, __CFLocaleSetNOP
, __CFLocaleCalendarName
, NULL
},
107 {(CFStringRef
)&kCFLocaleCalendar
, __CFLocaleCopyCalendar
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
108 {(CFStringRef
)&kCFLocaleCollationIdentifier
, __CFLocaleCopyCollationID
, __CFLocaleSetNOP
, __CFLocaleCollationName
, NULL
},
109 {(CFStringRef
)&kCFLocaleUsesMetricSystem
, __CFLocaleCopyUsesMetric
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
110 {(CFStringRef
)&kCFLocaleMeasurementSystem
, __CFLocaleCopyMeasurementSystem
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
111 {(CFStringRef
)&kCFLocaleDecimalSeparator
, __CFLocaleCopyNumberFormat
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFNumberFormatterDecimalSeparator
},
112 {(CFStringRef
)&kCFLocaleGroupingSeparator
, __CFLocaleCopyNumberFormat
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFNumberFormatterGroupingSeparator
},
113 {(CFStringRef
)&kCFLocaleCurrencySymbol
, __CFLocaleCopyNumberFormat2
, __CFLocaleSetNOP
, __CFLocaleCurrencyShortName
, (CFStringRef
)&kCFNumberFormatterCurrencySymbol
},
114 {(CFStringRef
)&kCFLocaleCurrencyCode
, __CFLocaleCopyNumberFormat2
, __CFLocaleSetNOP
, __CFLocaleCurrencyFullName
, (CFStringRef
)&kCFNumberFormatterCurrencyCode
},
115 {(CFStringRef
)&__kCFLocaleCollatorID
, __CFLocaleCopyCollatorID
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
119 static CFLocaleRef __CFLocaleSystem
= NULL
;
120 static CFMutableDictionaryRef __CFLocaleCache
= NULL
;
121 static CFSpinLock_t __CFLocaleGlobalLock
= CFSpinLockInit
;
125 CFStringRef _identifier
; // canonical identifier, never NULL
126 CFMutableDictionaryRef _cache
;
127 CFMutableDictionaryRef _overrides
;
128 CFDictionaryRef _prefs
;
133 enum { /* Bits 0-1 */
134 __kCFLocaleOrdinary
= 0,
135 __kCFLocaleSystem
= 1,
137 __kCFLocaleCustom
= 3
140 CF_INLINE CFIndex
__CFLocaleGetType(CFLocaleRef locale
) {
141 return __CFBitfieldGetValue(((const CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0);
144 CF_INLINE
void __CFLocaleSetType(CFLocaleRef locale
, CFIndex type
) {
145 __CFBitfieldSetValue(((CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0, (uint8_t)type
);
148 CF_INLINE
void __CFLocaleLockGlobal(void) {
149 __CFSpinLock(&__CFLocaleGlobalLock
);
152 CF_INLINE
void __CFLocaleUnlockGlobal(void) {
153 __CFSpinUnlock(&__CFLocaleGlobalLock
);
156 CF_INLINE
void __CFLocaleLock(CFLocaleRef locale
) {
157 __CFSpinLock(&locale
->_lock
);
160 CF_INLINE
void __CFLocaleUnlock(CFLocaleRef locale
) {
161 __CFSpinUnlock(&locale
->_lock
);
165 static Boolean
__CFLocaleEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
166 CFLocaleRef locale1
= (CFLocaleRef
)cf1
;
167 CFLocaleRef locale2
= (CFLocaleRef
)cf2
;
168 // a user locale and a locale created with an ident are not the same even if their contents are
169 if (__CFLocaleGetType(locale1
) != __CFLocaleGetType(locale2
)) return false;
170 if (!CFEqual(locale1
->_identifier
, locale2
->_identifier
)) return false;
171 if (NULL
== locale1
->_overrides
&& NULL
!= locale2
->_overrides
) return false;
172 if (NULL
!= locale1
->_overrides
&& NULL
== locale2
->_overrides
) return false;
173 if (NULL
!= locale1
->_overrides
&& !CFEqual(locale1
->_overrides
, locale2
->_overrides
)) return false;
174 if (__kCFLocaleUser
== __CFLocaleGetType(locale1
)) {
175 return CFEqual(locale1
->_prefs
, locale2
->_prefs
);
180 static CFHashCode
__CFLocaleHash(CFTypeRef cf
) {
181 CFLocaleRef locale
= (CFLocaleRef
)cf
;
182 return CFHash(locale
->_identifier
);
185 static CFStringRef
__CFLocaleCopyDescription(CFTypeRef cf
) {
186 CFLocaleRef locale
= (CFLocaleRef
)cf
;
187 const char *type
= NULL
;
188 switch (__CFLocaleGetType(locale
)) {
189 case __kCFLocaleOrdinary
: type
= "ordinary"; break;
190 case __kCFLocaleSystem
: type
= "system"; break;
191 case __kCFLocaleUser
: type
= "user"; break;
192 case __kCFLocaleCustom
: type
= "custom"; break;
194 return CFStringCreateWithFormat(CFGetAllocator(locale
), NULL
, CFSTR("<CFLocale %p [%p]>{type = %s, identifier = '%@'}"), cf
, CFGetAllocator(locale
), type
, locale
->_identifier
);
197 static void __CFLocaleDeallocate(CFTypeRef cf
) {
198 CFLocaleRef locale
= (CFLocaleRef
)cf
;
199 CFRelease(locale
->_identifier
);
200 if (NULL
!= locale
->_cache
) CFRelease(locale
->_cache
);
201 if (NULL
!= locale
->_overrides
) CFRelease(locale
->_overrides
);
202 if (NULL
!= locale
->_prefs
) CFRelease(locale
->_prefs
);
205 static CFTypeID __kCFLocaleTypeID
= _kCFRuntimeNotATypeID
;
207 static const CFRuntimeClass __CFLocaleClass
= {
212 __CFLocaleDeallocate
,
216 __CFLocaleCopyDescription
219 static void __CFLocaleInitialize(void) {
221 __kCFLocaleTypeID
= _CFRuntimeRegisterClass(&__CFLocaleClass
);
222 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
223 // table fixup to workaround compiler/language limitations
224 __CFLocaleKeyTable
[idx
].key
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].key
);
225 if (NULL
!= __CFLocaleKeyTable
[idx
].context
) {
226 __CFLocaleKeyTable
[idx
].context
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].context
);
231 CFTypeID
CFLocaleGetTypeID(void) {
232 if (_kCFRuntimeNotATypeID
== __kCFLocaleTypeID
) __CFLocaleInitialize();
233 return __kCFLocaleTypeID
;
236 CFLocaleRef
CFLocaleGetSystem(void) {
238 __CFLocaleLockGlobal();
239 if (NULL
== __CFLocaleSystem
) {
240 __CFLocaleUnlockGlobal();
241 locale
= CFLocaleCreate(kCFAllocatorSystemDefault
, CFSTR(""));
242 if (!locale
) return NULL
;
243 __CFLocaleSetType(locale
, __kCFLocaleSystem
);
244 __CFLocaleLockGlobal();
245 if (NULL
== __CFLocaleSystem
) {
246 __CFLocaleSystem
= locale
;
248 if (locale
) CFRelease(locale
);
251 locale
= __CFLocaleSystem
? (CFLocaleRef
)CFRetain(__CFLocaleSystem
) : NULL
;
252 __CFLocaleUnlockGlobal();
256 static CFLocaleRef __CFLocaleCurrent
= NULL
;
258 #if DEPLOYMENT_TARGET_MACOSX
259 #define FALLBACK_LOCALE_NAME CFSTR("")
262 CFLocaleRef
CFLocaleCopyCurrent(void) {
264 __CFLocaleLockGlobal();
265 if (__CFLocaleCurrent
) {
266 CFRetain(__CFLocaleCurrent
);
267 __CFLocaleUnlockGlobal();
268 return __CFLocaleCurrent
;
270 __CFLocaleUnlockGlobal();
272 CFDictionaryRef prefs
= NULL
;
273 CFStringRef identifier
= NULL
;
275 struct __CFLocale
*locale
;
276 uint32_t size
= sizeof(struct __CFLocale
) - sizeof(CFRuntimeBase
);
277 locale
= (struct __CFLocale
*)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault
, CFLocaleGetTypeID(), size
, NULL
);
278 if (NULL
== locale
) {
281 __CFLocaleSetType(locale
, __kCFLocaleUser
);
282 if (NULL
== identifier
) identifier
= CFRetain(FALLBACK_LOCALE_NAME
);
283 locale
->_identifier
= identifier
;
284 locale
->_cache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
285 locale
->_overrides
= NULL
;
286 locale
->_prefs
= prefs
;
287 locale
->_lock
= CFSpinLockInit
;
289 __CFLocaleLockGlobal();
290 if (NULL
== __CFLocaleCurrent
) {
291 __CFLocaleCurrent
= locale
;
295 locale
= (struct __CFLocale
*)CFRetain(__CFLocaleCurrent
);
296 __CFLocaleUnlockGlobal();
300 __private_extern__ CFDictionaryRef
__CFLocaleGetPrefs(CFLocaleRef locale
) {
301 return locale
->_prefs
;
304 CFLocaleRef
CFLocaleCreate(CFAllocatorRef allocator
, CFStringRef identifier
) {
305 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
306 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
307 __CFGenericValidateType(identifier
, CFStringGetTypeID());
308 CFStringRef localeIdentifier
= NULL
;
310 localeIdentifier
= CFLocaleCreateCanonicalLocaleIdentifierFromString(allocator
, identifier
);
312 if (NULL
== localeIdentifier
) return NULL
;
313 CFStringRef old
= localeIdentifier
;
314 localeIdentifier
= (CFStringRef
)CFStringCreateCopy(allocator
, localeIdentifier
);
316 __CFLocaleLockGlobal();
317 // Look for cases where we can return a cached instance.
318 // We only use cached objects if the allocator is the system
319 // default allocator.
320 if (!allocator
) allocator
= __CFGetDefaultAllocator();
321 Boolean canCache
= (kCFAllocatorSystemDefault
== allocator
);
322 if (canCache
&& __CFLocaleCache
) {
323 CFLocaleRef locale
= (CFLocaleRef
)CFDictionaryGetValue(__CFLocaleCache
, localeIdentifier
);
326 __CFLocaleUnlockGlobal();
327 CFRelease(localeIdentifier
);
331 struct __CFLocale
*locale
= NULL
;
332 uint32_t size
= sizeof(struct __CFLocale
) - sizeof(CFRuntimeBase
);
333 locale
= (struct __CFLocale
*)_CFRuntimeCreateInstance(allocator
, CFLocaleGetTypeID(), size
, NULL
);
334 if (NULL
== locale
) {
337 __CFLocaleSetType(locale
, __kCFLocaleOrdinary
);
338 locale
->_identifier
= localeIdentifier
;
339 locale
->_cache
= CFDictionaryCreateMutable(allocator
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
340 locale
->_overrides
= NULL
;
341 locale
->_prefs
= NULL
;
342 locale
->_lock
= CFSpinLockInit
;
344 if (NULL
== __CFLocaleCache
) {
345 __CFLocaleCache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
347 CFDictionarySetValue(__CFLocaleCache
, localeIdentifier
, locale
);
349 __CFLocaleUnlockGlobal();
350 return (CFLocaleRef
)locale
;
353 CFLocaleRef
CFLocaleCreateCopy(CFAllocatorRef allocator
, CFLocaleRef locale
) {
354 return (CFLocaleRef
)CFRetain(locale
);
357 CFStringRef
CFLocaleGetIdentifier(CFLocaleRef locale
) {
358 CF_OBJC_FUNCDISPATCH0(CFLocaleGetTypeID(), CFStringRef
, locale
, "localeIdentifier");
359 return locale
->_identifier
;
362 CFTypeRef
CFLocaleGetValue(CFLocaleRef locale
, CFStringRef key
) {
363 CF_OBJC_FUNCDISPATCH1(CFLocaleGetTypeID(), CFTypeRef
, locale
, "objectForKey:", key
);
364 CFIndex idx
, slot
= -1;
365 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
366 if (__CFLocaleKeyTable
[idx
].key
== key
) {
371 if (-1 == slot
&& NULL
!= key
) {
372 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
373 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
383 if (NULL
!= locale
->_overrides
&& CFDictionaryGetValueIfPresent(locale
->_overrides
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
386 __CFLocaleLock(locale
);
387 if (CFDictionaryGetValueIfPresent(locale
->_cache
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
388 __CFLocaleUnlock(locale
);
391 if (__kCFLocaleUser
== __CFLocaleGetType(locale
) && __CFLocaleKeyTable
[slot
].get(locale
, true, &value
, __CFLocaleKeyTable
[slot
].context
)) {
392 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
393 if (value
) CFRelease(value
);
394 __CFLocaleUnlock(locale
);
397 if (__CFLocaleKeyTable
[slot
].get(locale
, false, &value
, __CFLocaleKeyTable
[slot
].context
)) {
398 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
399 if (value
) CFRelease(value
);
400 __CFLocaleUnlock(locale
);
403 __CFLocaleUnlock(locale
);
407 CFStringRef
CFLocaleCopyDisplayNameForPropertyValue(CFLocaleRef displayLocale
, CFStringRef key
, CFStringRef value
) {
408 CF_OBJC_FUNCDISPATCH2(CFLocaleGetTypeID(), CFStringRef
, displayLocale
, "_copyDisplayNameForKey:value:", key
, value
);
409 CFIndex idx
, slot
= -1;
410 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
411 if (__CFLocaleKeyTable
[idx
].key
== key
) {
416 if (-1 == slot
&& NULL
!= key
) {
417 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
418 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
424 if (-1 == slot
|| !value
) {
427 // Get the locale ID as a C string
428 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
429 char cValue
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
430 if (CFStringGetCString(displayLocale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
) && CFStringGetCString(value
, cValue
, sizeof(cValue
)/sizeof(char), kCFStringEncodingASCII
)) {
432 if ((NULL
== displayLocale
->_prefs
) && __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
)) {
436 // We could not find a result using the requested language. Fall back through all preferred languages.
438 if (displayLocale
->_prefs
) {
439 langPref
= (CFArrayRef
)CFDictionaryGetValue(displayLocale
->_prefs
, CFSTR("AppleLanguages"));
440 if (langPref
) CFRetain(langPref
);
442 langPref
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
444 if (langPref
!= NULL
) {
445 CFIndex count
= CFArrayGetCount(langPref
);
447 bool success
= false;
448 for (i
= 0; i
< count
&& !success
; ++i
) {
449 CFStringRef language
= (CFStringRef
)CFArrayGetValueAtIndex(langPref
, i
);
450 CFStringRef cleanLanguage
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, language
);
451 if (CFStringGetCString(cleanLanguage
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
)) {
452 success
= __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
);
454 CFRelease(cleanLanguage
);
464 CFArrayRef
CFLocaleCopyAvailableLocaleIdentifiers(void) {
465 int32_t locale
, localeCount
= uloc_countAvailable();
466 CFMutableSetRef working
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeSetCallBacks
);
467 for (locale
= 0; locale
< localeCount
; ++locale
) {
468 const char *localeID
= uloc_getAvailable(locale
);
469 CFStringRef string1
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, localeID
, kCFStringEncodingASCII
);
470 CFStringRef string2
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, string1
);
471 CFSetAddValue(working
, string1
);
472 // do not include canonicalized version as IntlFormats cannot cope with that in its popup
476 CFIndex cnt
= CFSetGetCount(working
);
477 STACK_BUFFER_DECL(const void *, buffer
, cnt
);
478 CFSetGetValues(working
, buffer
);
479 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, buffer
, cnt
, &kCFTypeArrayCallBacks
);
484 static CFArrayRef
__CFLocaleCopyCStringsAsArray(const char* const* p
) {
485 CFMutableArrayRef working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
487 CFStringRef string
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, *p
, kCFStringEncodingASCII
);
488 CFArrayAppendValue(working
, string
);
491 CFArrayRef result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
496 static CFArrayRef
__CFLocaleCopyUEnumerationAsArray(UEnumeration
*enumer
, UErrorCode
*icuErr
) {
497 const UChar
*next
= NULL
;
499 CFMutableArrayRef working
= NULL
;
500 if (U_SUCCESS(*icuErr
)) {
501 working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
503 while ((next
= uenum_unext(enumer
, &len
, icuErr
)) && U_SUCCESS(*icuErr
)) {
504 CFStringRef string
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)next
, (CFIndex
) len
);
505 CFArrayAppendValue(working
, string
);
508 if (*icuErr
== U_INDEX_OUTOFBOUNDS_ERROR
) {
509 *icuErr
= U_ZERO_ERROR
; // Temp: Work around bug (ICU 5220) in ucurr enumerator
511 CFArrayRef result
= NULL
;
512 if (U_SUCCESS(*icuErr
)) {
513 result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
515 if (working
!= NULL
) {
521 CFArrayRef
CFLocaleCopyISOLanguageCodes(void) {
522 const char* const* p
= uloc_getISOLanguages();
523 return __CFLocaleCopyCStringsAsArray(p
);
526 CFArrayRef
CFLocaleCopyISOCountryCodes(void) {
527 const char* const* p
= uloc_getISOCountries();
528 return __CFLocaleCopyCStringsAsArray(p
);
531 CFArrayRef
CFLocaleCopyISOCurrencyCodes(void) {
532 UErrorCode icuStatus
= U_ZERO_ERROR
;
533 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_ALL
, &icuStatus
);
534 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
539 CFArrayRef
CFLocaleCopyCommonISOCurrencyCodes(void) {
540 UErrorCode icuStatus
= U_ZERO_ERROR
;
541 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_COMMON
|UCURR_NON_DEPRECATED
, &icuStatus
);
542 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
547 CFArrayRef
CFLocaleCopyPreferredLanguages(void) {
548 CFMutableArrayRef newArray
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
549 CFArrayRef languagesArray
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
550 if (languagesArray
&& (CFArrayGetTypeID() == CFGetTypeID(languagesArray
))) {
551 for (CFIndex idx
= 0, cnt
= CFArrayGetCount(languagesArray
); idx
< cnt
; idx
++) {
552 CFStringRef str
= (CFStringRef
)CFArrayGetValueAtIndex(languagesArray
, idx
);
553 if (str
&& (CFStringGetTypeID() == CFGetTypeID(str
))) {
554 CFStringRef ident
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, str
);
555 CFArrayAppendValue(newArray
, ident
);
560 if (languagesArray
) CFRelease(languagesArray
);
564 // -------- -------- -------- -------- -------- --------
566 // These functions return true or false depending on the success or failure of the function.
567 // In the Copy case, this is failure to fill the *cf out parameter, and that out parameter is
568 // returned by reference WITH a retain on it.
569 static bool __CFLocaleSetNOP(CFMutableLocaleRef locale
, CFTypeRef cf
, CFStringRef context
) {
573 static bool __CFLocaleCopyLocaleID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
574 *cf
= CFRetain(locale
->_identifier
);
579 static bool __CFLocaleCopyCodes(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
580 CFDictionaryRef codes
= NULL
;
581 // this access of _cache is protected by the lock in CFLocaleGetValue()
582 if (!CFDictionaryGetValueIfPresent(locale
->_cache
, CFSTR("__kCFLocaleCodes"), (const void **)&codes
)) {
583 codes
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, locale
->_identifier
);
584 if (codes
) CFDictionarySetValue(locale
->_cache
, CFSTR("__kCFLocaleCodes"), codes
);
585 if (codes
) CFRelease(codes
);
588 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(codes
, context
); // context is one of kCFLocale*Code constants
589 if (value
) CFRetain(value
);
596 CFCharacterSetRef
_CFCreateCharacterSetFromUSet(USet
*set
) {
597 UErrorCode icuErr
= U_ZERO_ERROR
;
598 CFMutableCharacterSetRef working
= CFCharacterSetCreateMutable(NULL
);
599 UChar buffer
[2048]; // Suitable for most small sets
605 int32_t itemCount
= uset_getItemCount(set
);
607 for (i
= 0; i
< itemCount
; ++i
)
613 stringLen
= uset_getItem(set
, i
, &start
, &end
, buffer
, sizeof(buffer
)/sizeof(UChar
), &icuErr
);
614 if (icuErr
== U_BUFFER_OVERFLOW_ERROR
)
616 string
= (UChar
*) malloc(sizeof(UChar
)*(stringLen
+1));
622 icuErr
= U_ZERO_ERROR
;
623 (void) uset_getItem(set
, i
, &start
, &end
, string
, stringLen
+1, &icuErr
);
625 if (U_FAILURE(icuErr
))
627 if (string
!= buffer
)
633 CFCharacterSetAddCharactersInRange(working
, CFRangeMake(start
, end
-start
+1));
636 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, (UniChar
*)string
, stringLen
, kCFAllocatorNull
);
637 CFCharacterSetAddCharactersInString(working
, cfString
);
640 if (string
!= buffer
)
644 CFCharacterSetRef result
= CFCharacterSetCreateCopy(kCFAllocatorSystemDefault
, working
);
650 static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
651 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
652 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
653 UErrorCode icuStatus
= U_ZERO_ERROR
;
654 ULocaleData
* uld
= ulocdata_open(localeID
, &icuStatus
);
655 USet
*set
= ulocdata_getExemplarSet(uld
, NULL
, USET_ADD_CASE_MAPPINGS
, ULOCDATA_ES_STANDARD
, &icuStatus
);
657 if (U_FAILURE(icuStatus
))
659 if (icuStatus
== U_USING_DEFAULT_WARNING
) // If default locale used, force to empty set
661 *cf
= (CFTypeRef
) _CFCreateCharacterSetFromUSet(set
);
663 return (*cf
!= NULL
);
668 static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
, const char *keyword
)
670 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
671 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
))
673 char value
[ULOC_KEYWORD_AND_VALUES_CAPACITY
];
674 UErrorCode icuStatus
= U_ZERO_ERROR
;
675 if (uloc_getKeywordValue(localeID
, keyword
, value
, sizeof(value
)/sizeof(char), &icuStatus
) > 0 && U_SUCCESS(icuStatus
))
677 *cf
= (CFTypeRef
) CFStringCreateWithCString(kCFAllocatorSystemDefault
, value
, kCFStringEncodingASCII
);
685 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
686 bool succeeded
= __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCalendarKeyword
);
688 if (CFEqual(*cf
, kCFGregorianCalendar
)) {
690 *cf
= CFRetain(kCFGregorianCalendar
);
691 } else if (CFEqual(*cf
, kCFBuddhistCalendar
)) {
693 *cf
= CFRetain(kCFBuddhistCalendar
);
694 } else if (CFEqual(*cf
, kCFJapaneseCalendar
)) {
696 *cf
= CFRetain(kCFJapaneseCalendar
);
697 } else if (CFEqual(*cf
, kCFIslamicCalendar
)) {
699 *cf
= CFRetain(kCFIslamicCalendar
);
700 } else if (CFEqual(*cf
, kCFIslamicCivilCalendar
)) {
702 *cf
= CFRetain(kCFIslamicCivilCalendar
);
703 } else if (CFEqual(*cf
, kCFHebrewCalendar
)) {
705 *cf
= CFRetain(kCFHebrewCalendar
);
706 } else if (CFEqual(*cf
, kCFChineseCalendar
)) {
708 *cf
= CFRetain(kCFChineseCalendar
);
711 *cf
= CFRetain(kCFGregorianCalendar
);
716 static bool __CFLocaleCopyCalendar(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
717 if (__CFLocaleCopyCalendarID(locale
, user
, cf
, context
)) {
718 CFCalendarRef calendar
= CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault
, (CFStringRef
)*cf
);
719 CFCalendarSetLocale(calendar
, locale
);
727 static bool __CFLocaleCopyCollationID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
728 return __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCollationKeyword
);
731 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
732 CFStringRef canonLocaleCFStr
= NULL
;
733 if (!canonLocaleCFStr
) {
734 canonLocaleCFStr
= CFLocaleGetIdentifier(locale
);
735 CFRetain(canonLocaleCFStr
);
737 *cf
= canonLocaleCFStr
;
738 return canonLocaleCFStr
? true : false;
741 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
742 bool us
= false; // Default is Metric
746 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
747 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
748 UErrorCode icuStatus
= U_ZERO_ERROR
;
749 UMeasurementSystem ms
= UMS_SI
;
750 ms
= ulocdata_getMeasurementSystem(localeID
, &icuStatus
);
751 if (U_SUCCESS(icuStatus
)) {
759 *cf
= us
? CFRetain(kCFBooleanFalse
) : CFRetain(kCFBooleanTrue
);
763 static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
764 if (__CFLocaleCopyUsesMetric(locale
, user
, cf
, context
)) {
765 bool us
= (*cf
== kCFBooleanFalse
);
767 *cf
= us
? CFRetain(CFSTR("U.S.")) : CFRetain(CFSTR("Metric"));
773 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
774 CFStringRef str
= NULL
;
775 #if DEPLOYMENT_TARGET_MACOSX
776 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterDecimalStyle
);
777 str
= nf
? CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
778 if (nf
) CFRelease(nf
);
787 // ICU does not reliably set up currency info for other than Currency-type formatters,
788 // so we have to have another routine here which creates a Currency number formatter.
789 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
790 CFStringRef str
= NULL
;
791 #if DEPLOYMENT_TARGET_MACOSX
792 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterCurrencyStyle
);
793 str
= nf
? CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
794 if (nf
) CFRelease(nf
);
803 typedef int32_t (*__CFICUFunction
)(const char *, const char *, UChar
*, int32_t, UErrorCode
*);
805 static bool __CFLocaleICUName(const char *locale
, const char *valLocale
, CFStringRef
*out
, __CFICUFunction icu
) {
806 UErrorCode icuStatus
= U_ZERO_ERROR
;
808 UChar name
[kMaxICUNameSize
];
810 size
= (*icu
)(valLocale
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
811 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
812 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
813 return (*out
!= NULL
);
818 static bool __CFLocaleICUKeywordValueName(const char *locale
, const char *value
, const char *keyword
, CFStringRef
*out
) {
819 UErrorCode icuStatus
= U_ZERO_ERROR
;
821 UChar name
[kMaxICUNameSize
];
822 // Need to make a fake locale ID
823 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
824 if (strlen(value
) < ULOC_KEYWORD_AND_VALUES_CAPACITY
) {
825 snprintf(lid
, sizeof(lid
), "en_US@%s=%s", keyword
, value
);
826 size
= uloc_getDisplayKeywordValue(lid
, keyword
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
827 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
828 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
829 return (*out
!= NULL
);
835 static bool __CFLocaleICUCurrencyName(const char *locale
, const char *value
, UCurrNameStyle style
, CFStringRef
*out
) {
836 int valLen
= strlen(value
);
837 if (valLen
!= 3) // not a valid ISO code
840 UBool isChoice
= FALSE
;
842 UErrorCode icuStatus
= U_ZERO_ERROR
;
843 u_charsToUChars(value
, curr
, valLen
);
846 name
= ucurr_getName(curr
, locale
, style
, &isChoice
, &size
, &icuStatus
);
847 if (U_FAILURE(icuStatus
) || icuStatus
== U_USING_DEFAULT_WARNING
)
849 UChar result
[kMaxICUNameSize
];
852 UChar pattern
[kMaxICUNameSize
];
853 CFStringRef patternRef
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("{0,choice,%S}"), name
);
854 CFIndex pattlen
= CFStringGetLength(patternRef
);
855 CFStringGetCharacters(patternRef
, CFRangeMake(0, pattlen
), (UniChar
*)pattern
);
856 CFRelease(patternRef
);
857 pattern
[pattlen
] = '\0'; // null terminate the pattern
858 // Format the message assuming a large amount of the currency
859 size
= u_formatMessage("en_US", pattern
, pattlen
, result
, kMaxICUNameSize
, &icuStatus
, 10.0);
860 if (U_FAILURE(icuStatus
))
865 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
866 return (*out
!= NULL
);
869 static bool __CFLocaleFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
870 UErrorCode icuStatus
= U_ZERO_ERROR
;
872 UChar name
[kMaxICUNameSize
];
874 // First, try to get the full locale.
875 size
= uloc_getDisplayName(value
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
876 if (U_FAILURE(icuStatus
) || size
<= 0)
879 // Did we wind up using a default somewhere?
880 if (icuStatus
== U_USING_DEFAULT_WARNING
) {
881 // For some locale IDs, there may be no language which has a translation for every
882 // piece. Rather than return nothing, see if we can at least handle
883 // the language part of the locale.
884 UErrorCode localStatus
= U_ZERO_ERROR
;
886 UChar localName
[kMaxICUNameSize
];
887 localSize
= uloc_getDisplayLanguage(value
, locale
, localName
, kMaxICUNameSize
, &localStatus
);
888 if (U_FAILURE(localStatus
) || size
<= 0 || localStatus
== U_USING_DEFAULT_WARNING
)
892 // This locale is OK, so use the result.
893 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
894 return (*out
!= NULL
);
897 static bool __CFLocaleLanguageName(const char *locale
, const char *value
, CFStringRef
*out
) {
898 int len
= strlen(value
);
899 if (len
>= 2 && len
<= 3)
900 return __CFLocaleICUName(locale
, value
, out
, uloc_getDisplayLanguage
);
904 static bool __CFLocaleCountryName(const char *locale
, const char *value
, CFStringRef
*out
) {
905 // Need to make a fake locale ID
906 char lid
[ULOC_FULLNAME_CAPACITY
];
907 if (strlen(value
) == 2) {
908 snprintf(lid
, sizeof(lid
), "en_%s", value
);
909 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayCountry
);
914 static bool __CFLocaleScriptName(const char *locale
, const char *value
, CFStringRef
*out
) {
915 // Need to make a fake locale ID
916 char lid
[ULOC_FULLNAME_CAPACITY
];
917 if (strlen(value
) == 4) {
918 snprintf(lid
, sizeof(lid
), "en_%s_US", value
);
919 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayScript
);
924 static bool __CFLocaleVariantName(const char *locale
, const char *value
, CFStringRef
*out
) {
925 // Need to make a fake locale ID
926 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
927 if (strlen(value
) < ULOC_FULLNAME_CAPACITY
) {
928 snprintf(lid
, sizeof(lid
), "en_US_%s", value
);
929 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayVariant
);
934 static bool __CFLocaleCalendarName(const char *locale
, const char *value
, CFStringRef
*out
) {
935 return __CFLocaleICUKeywordValueName(locale
, value
, kCalendarKeyword
, out
);
938 static bool __CFLocaleCollationName(const char *locale
, const char *value
, CFStringRef
*out
) {
939 return __CFLocaleICUKeywordValueName(locale
, value
, kCollationKeyword
, out
);
942 static bool __CFLocaleCurrencyShortName(const char *locale
, const char *value
, CFStringRef
*out
) {
943 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_SYMBOL_NAME
, out
);
946 static bool __CFLocaleCurrencyFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
947 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_LONG_NAME
, out
);
950 static bool __CFLocaleNoName(const char *locale
, const char *value
, CFStringRef
*out
) {
954 // Remember to keep the names such that they would make sense for the user locale,
955 // in addition to the others; for example, it is "Currency", not "DefaultCurrency".
956 // (And besides, "Default" is almost always implied.) Words like "Default" and
957 // "Preferred" and so on should be left out of the names.
958 CONST_STRING_DECL(kCFLocaleIdentifier
, "locale:id")
959 CONST_STRING_DECL(kCFLocaleLanguageCode
, "locale:language code")
960 CONST_STRING_DECL(kCFLocaleCountryCode
, "locale:country code")
961 CONST_STRING_DECL(kCFLocaleScriptCode
, "locale:script code")
962 CONST_STRING_DECL(kCFLocaleVariantCode
, "locale:variant code")
963 CONST_STRING_DECL(kCFLocaleExemplarCharacterSet
, "locale:exemplar characters")
964 CONST_STRING_DECL(kCFLocaleCalendarIdentifier
, "calendar")
965 CONST_STRING_DECL(kCFLocaleCalendar
, "locale:calendarref")
966 CONST_STRING_DECL(kCFLocaleCollationIdentifier
, "collation")
967 CONST_STRING_DECL(kCFLocaleUsesMetricSystem
, "locale:uses metric")
968 CONST_STRING_DECL(kCFLocaleMeasurementSystem
, "locale:measurement system")
969 CONST_STRING_DECL(kCFLocaleDecimalSeparator
, "locale:decimal separator")
970 CONST_STRING_DECL(kCFLocaleGroupingSeparator
, "locale:grouping separator")
971 CONST_STRING_DECL(kCFLocaleCurrencySymbol
, "locale:currency symbol")
972 CONST_STRING_DECL(kCFLocaleCurrencyCode
, "currency")
974 CONST_STRING_DECL(kCFGregorianCalendar
, "gregorian")
975 CONST_STRING_DECL(kCFBuddhistCalendar
, "buddhist")
976 CONST_STRING_DECL(kCFJapaneseCalendar
, "japanese")
977 CONST_STRING_DECL(kCFIslamicCalendar
, "islamic")
978 CONST_STRING_DECL(kCFIslamicCivilCalendar
, "islamic-civil")
979 CONST_STRING_DECL(kCFHebrewCalendar
, "hebrew")
980 CONST_STRING_DECL(kCFChineseCalendar
, "chinese")
982 #undef kMaxICUNameSize