2 *******************************************************************************
3 * Copyright (C) 2010-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
12 #include "unicode/locdspnm.h"
13 #include "unicode/msgfmt.h"
14 #include "unicode/ures.h"
15 #include "unicode/udisplaycontext.h"
16 #include "unicode/brkiter.h"
29 * Concatenate a number of null-terminated strings to buffer, leaving a
30 * null-terminated string. The last argument should be the null pointer.
31 * Return the length of the string in the buffer, not counting the trailing
32 * null. Return -1 if there is an error (buffer is null, or buflen < 1).
34 static int32_t ncat(char *buffer
, uint32_t buflen
, ...) {
38 const char* e
= buffer
+ buflen
- 1;
40 if (buffer
== NULL
|| buflen
< 1) {
44 va_start(args
, buflen
);
45 while ((str
= va_arg(args
, char *))) {
47 while (p
!= e
&& (c
= *str
++)) {
59 ////////////////////////////////////////////////////////////////////////////////////////////////////
61 // Access resource data for locale components.
62 // Wrap code in uloc.c for now.
68 ICUDataTable(const char* path
, const Locale
& locale
);
71 const Locale
& getLocale();
73 UnicodeString
& get(const char* tableKey
, const char* itemKey
,
74 UnicodeString
& result
) const;
75 UnicodeString
& get(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
76 UnicodeString
& result
) const;
78 UnicodeString
& getNoFallback(const char* tableKey
, const char* itemKey
,
79 UnicodeString
&result
) const;
80 UnicodeString
& getNoFallback(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
81 UnicodeString
&result
) const;
84 inline UnicodeString
&
85 ICUDataTable::get(const char* tableKey
, const char* itemKey
, UnicodeString
& result
) const {
86 return get(tableKey
, NULL
, itemKey
, result
);
89 inline UnicodeString
&
90 ICUDataTable::getNoFallback(const char* tableKey
, const char* itemKey
, UnicodeString
& result
) const {
91 return getNoFallback(tableKey
, NULL
, itemKey
, result
);
94 ICUDataTable::ICUDataTable(const char* path
, const Locale
& locale
)
95 : path(NULL
), locale(Locale::getRoot())
98 int32_t len
= uprv_strlen(path
);
99 this->path
= (const char*) uprv_malloc(len
+ 1);
101 uprv_strcpy((char *)this->path
, path
);
102 this->locale
= locale
;
107 ICUDataTable::~ICUDataTable() {
109 uprv_free((void*) path
);
115 ICUDataTable::getLocale() {
120 ICUDataTable::get(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
121 UnicodeString
&result
) const {
122 UErrorCode status
= U_ZERO_ERROR
;
125 const UChar
*s
= uloc_getTableStringWithFallback(path
, locale
.getName(),
126 tableKey
, subTableKey
, itemKey
,
128 if (U_SUCCESS(status
) && len
> 0) {
129 return result
.setTo(s
, len
);
131 return result
.setTo(UnicodeString(itemKey
, -1, US_INV
));
135 ICUDataTable::getNoFallback(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
136 UnicodeString
& result
) const {
137 UErrorCode status
= U_ZERO_ERROR
;
140 const UChar
*s
= uloc_getTableStringWithFallback(path
, locale
.getName(),
141 tableKey
, subTableKey
, itemKey
,
143 if (U_SUCCESS(status
)) {
144 return result
.setTo(s
, len
);
151 ////////////////////////////////////////////////////////////////////////////////////////////////////
153 LocaleDisplayNames::~LocaleDisplayNames() {}
155 ////////////////////////////////////////////////////////////////////////////////////////////////////
157 #if 0 // currently unused
159 class DefaultLocaleDisplayNames
: public LocaleDisplayNames
{
160 UDialectHandling dialectHandling
;
164 DefaultLocaleDisplayNames(UDialectHandling dialectHandling
);
166 virtual ~DefaultLocaleDisplayNames();
168 virtual const Locale
& getLocale() const;
169 virtual UDialectHandling
getDialectHandling() const;
171 virtual UnicodeString
& localeDisplayName(const Locale
& locale
,
172 UnicodeString
& result
) const;
173 virtual UnicodeString
& localeDisplayName(const char* localeId
,
174 UnicodeString
& result
) const;
175 virtual UnicodeString
& languageDisplayName(const char* lang
,
176 UnicodeString
& result
) const;
177 virtual UnicodeString
& scriptDisplayName(const char* script
,
178 UnicodeString
& result
) const;
179 virtual UnicodeString
& scriptDisplayName(UScriptCode scriptCode
,
180 UnicodeString
& result
) const;
181 virtual UnicodeString
& regionDisplayName(const char* region
,
182 UnicodeString
& result
) const;
183 virtual UnicodeString
& variantDisplayName(const char* variant
,
184 UnicodeString
& result
) const;
185 virtual UnicodeString
& keyDisplayName(const char* key
,
186 UnicodeString
& result
) const;
187 virtual UnicodeString
& keyValueDisplayName(const char* key
,
189 UnicodeString
& result
) const;
192 DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling
)
193 : dialectHandling(dialectHandling
) {
196 DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() {
200 DefaultLocaleDisplayNames::getLocale() const {
201 return Locale::getRoot();
205 DefaultLocaleDisplayNames::getDialectHandling() const {
206 return dialectHandling
;
210 DefaultLocaleDisplayNames::localeDisplayName(const Locale
& locale
,
211 UnicodeString
& result
) const {
212 return result
= UnicodeString(locale
.getName(), -1, US_INV
);
216 DefaultLocaleDisplayNames::localeDisplayName(const char* localeId
,
217 UnicodeString
& result
) const {
218 return result
= UnicodeString(localeId
, -1, US_INV
);
222 DefaultLocaleDisplayNames::languageDisplayName(const char* lang
,
223 UnicodeString
& result
) const {
224 return result
= UnicodeString(lang
, -1, US_INV
);
228 DefaultLocaleDisplayNames::scriptDisplayName(const char* script
,
229 UnicodeString
& result
) const {
230 return result
= UnicodeString(script
, -1, US_INV
);
234 DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode
,
235 UnicodeString
& result
) const {
236 const char* name
= uscript_getName(scriptCode
);
238 return result
= UnicodeString(name
, -1, US_INV
);
240 return result
.remove();
244 DefaultLocaleDisplayNames::regionDisplayName(const char* region
,
245 UnicodeString
& result
) const {
246 return result
= UnicodeString(region
, -1, US_INV
);
250 DefaultLocaleDisplayNames::variantDisplayName(const char* variant
,
251 UnicodeString
& result
) const {
252 return result
= UnicodeString(variant
, -1, US_INV
);
256 DefaultLocaleDisplayNames::keyDisplayName(const char* key
,
257 UnicodeString
& result
) const {
258 return result
= UnicodeString(key
, -1, US_INV
);
262 DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */,
264 UnicodeString
& result
) const {
265 return result
= UnicodeString(value
, -1, US_INV
);
268 #endif // currently unused class DefaultLocaleDisplayNames
270 ////////////////////////////////////////////////////////////////////////////////////////////////////
272 class LocaleDisplayNamesImpl
: public LocaleDisplayNames
{
274 UDialectHandling dialectHandling
;
275 ICUDataTable langData
;
276 ICUDataTable regionData
;
277 MessageFormat
*separatorFormat
;
278 MessageFormat
*format
;
279 MessageFormat
*keyTypeFormat
;
280 UDisplayContext capitalizationContext
;
281 BreakIterator
* capitalizationBrkIter
;
282 static UMutex capitalizationBrkIterLock
;
283 UnicodeString formatOpenParen
;
284 UnicodeString formatReplaceOpenParen
;
285 UnicodeString formatCloseParen
;
286 UnicodeString formatReplaceCloseParen
;
287 UDisplayContext nameLength
;
289 // Constants for capitalization context usage types.
290 enum CapContextUsage
{
291 kCapContextUsageLanguage
,
292 kCapContextUsageScript
,
293 kCapContextUsageTerritory
,
294 kCapContextUsageVariant
,
296 kCapContextUsageKeyValue
,
297 kCapContextUsageCount
299 // Capitalization transforms. For each usage type, indicates whether to titlecase for
300 // the context specified in capitalizationContext (which we know at construction time)
301 UBool fCapitalization
[kCapContextUsageCount
];
305 LocaleDisplayNamesImpl(const Locale
& locale
, UDialectHandling dialectHandling
);
306 LocaleDisplayNamesImpl(const Locale
& locale
, UDisplayContext
*contexts
, int32_t length
);
307 virtual ~LocaleDisplayNamesImpl();
309 virtual const Locale
& getLocale() const;
310 virtual UDialectHandling
getDialectHandling() const;
311 virtual UDisplayContext
getContext(UDisplayContextType type
) const;
313 virtual UnicodeString
& localeDisplayName(const Locale
& locale
,
314 UnicodeString
& result
) const;
315 virtual UnicodeString
& localeDisplayName(const char* localeId
,
316 UnicodeString
& result
) const;
317 virtual UnicodeString
& languageDisplayName(const char* lang
,
318 UnicodeString
& result
) const;
319 virtual UnicodeString
& scriptDisplayName(const char* script
,
320 UnicodeString
& result
) const;
321 virtual UnicodeString
& scriptDisplayName(UScriptCode scriptCode
,
322 UnicodeString
& result
) const;
323 virtual UnicodeString
& regionDisplayName(const char* region
,
324 UnicodeString
& result
) const;
325 virtual UnicodeString
& variantDisplayName(const char* variant
,
326 UnicodeString
& result
) const;
327 virtual UnicodeString
& keyDisplayName(const char* key
,
328 UnicodeString
& result
) const;
329 virtual UnicodeString
& keyValueDisplayName(const char* key
,
331 UnicodeString
& result
) const;
333 UnicodeString
& localeIdName(const char* localeId
,
334 UnicodeString
& result
) const;
335 UnicodeString
& regionShortDisplayName(const char* region
, // Apple-specific
336 UnicodeString
& result
) const;
337 UnicodeString
& appendWithSep(UnicodeString
& buffer
, const UnicodeString
& src
) const;
338 UnicodeString
& adjustForUsageAndContext(CapContextUsage usage
, UnicodeString
& result
) const;
339 void initialize(void);
342 UMutex
LocaleDisplayNamesImpl::capitalizationBrkIterLock
= U_MUTEX_INITIALIZER
;
344 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale
& locale
,
345 UDialectHandling dialectHandling
)
346 : dialectHandling(dialectHandling
)
347 , langData(U_ICUDATA_LANG
, locale
)
348 , regionData(U_ICUDATA_REGION
, locale
)
349 , separatorFormat(NULL
)
351 , keyTypeFormat(NULL
)
352 , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE
)
353 , capitalizationBrkIter(NULL
)
354 , nameLength(UDISPCTX_LENGTH_FULL
)
359 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale
& locale
,
360 UDisplayContext
*contexts
, int32_t length
)
361 : dialectHandling(ULDN_STANDARD_NAMES
)
362 , langData(U_ICUDATA_LANG
, locale
)
363 , regionData(U_ICUDATA_REGION
, locale
)
364 , separatorFormat(NULL
)
366 , keyTypeFormat(NULL
)
367 , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE
)
368 , capitalizationBrkIter(NULL
)
369 , nameLength(UDISPCTX_LENGTH_FULL
)
371 while (length
-- > 0) {
372 UDisplayContext value
= *contexts
++;
373 UDisplayContextType selector
= (UDisplayContextType
)((uint32_t)value
>> 8);
375 case UDISPCTX_TYPE_DIALECT_HANDLING
:
376 dialectHandling
= (UDialectHandling
)value
;
378 case UDISPCTX_TYPE_CAPITALIZATION
:
379 capitalizationContext
= value
;
381 case UDISPCTX_TYPE_DISPLAY_LENGTH
:
384 case UADISPCTX_TYPE_LENGTH
: // Apple-specific
385 nameLength
= (value
== UADISPCTX_LENGTH_SHORT
)? UDISPCTX_LENGTH_SHORT
: UDISPCTX_LENGTH_FULL
;
395 LocaleDisplayNamesImpl::initialize(void) {
396 LocaleDisplayNamesImpl
*nonConstThis
= (LocaleDisplayNamesImpl
*)this;
397 nonConstThis
->locale
= langData
.getLocale() == Locale::getRoot()
398 ? regionData
.getLocale()
399 : langData
.getLocale();
402 langData
.getNoFallback("localeDisplayPattern", "separator", sep
);
404 sep
= UnicodeString("{0}, {1}", -1, US_INV
);
406 UErrorCode status
= U_ZERO_ERROR
;
407 separatorFormat
= new MessageFormat(sep
, status
);
409 UnicodeString pattern
;
410 langData
.getNoFallback("localeDisplayPattern", "pattern", pattern
);
411 if (pattern
.isBogus()) {
412 pattern
= UnicodeString("{0} ({1})", -1, US_INV
);
414 format
= new MessageFormat(pattern
, status
);
415 if (pattern
.indexOf((UChar
)0xFF08) >= 0) {
416 formatOpenParen
.setTo((UChar
)0xFF08); // fullwidth (
417 formatReplaceOpenParen
.setTo((UChar
)0xFF3B); // fullwidth [
418 formatCloseParen
.setTo((UChar
)0xFF09); // fullwidth )
419 formatReplaceCloseParen
.setTo((UChar
)0xFF3D); // fullwidth ]
421 formatOpenParen
.setTo((UChar
)0x0028); // (
422 formatReplaceOpenParen
.setTo((UChar
)0x005B); // [
423 formatCloseParen
.setTo((UChar
)0x0029); // )
424 formatReplaceCloseParen
.setTo((UChar
)0x005D); // ]
427 UnicodeString ktPattern
;
428 langData
.get("localeDisplayPattern", "keyTypePattern", ktPattern
);
429 if (ktPattern
.isBogus()) {
430 ktPattern
= UnicodeString("{0}={1}", -1, US_INV
);
432 keyTypeFormat
= new MessageFormat(ktPattern
, status
);
434 uprv_memset(fCapitalization
, 0, sizeof(fCapitalization
));
435 #if !UCONFIG_NO_BREAK_ITERATION
436 // The following is basically copied from DateFormatSymbols::initializeData
438 const char * usageName
;
439 LocaleDisplayNamesImpl::CapContextUsage usageEnum
;
440 } ContextUsageNameToEnum
;
441 const ContextUsageNameToEnum contextUsageTypeMap
[] = {
442 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
443 { "key", kCapContextUsageKey
},
444 { "keyValue", kCapContextUsageKeyValue
},
445 { "languages", kCapContextUsageLanguage
},
446 { "script", kCapContextUsageScript
},
447 { "territory", kCapContextUsageTerritory
},
448 { "variant", kCapContextUsageVariant
},
449 { NULL
, (CapContextUsage
)0 },
451 // Only get the context data if we need it! This is a const object so we know now...
452 // Also check whether we will need a break iterator (depends on the data)
453 UBool needBrkIter
= FALSE
;
454 if (capitalizationContext
== UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
|| capitalizationContext
== UDISPCTX_CAPITALIZATION_FOR_STANDALONE
) {
456 UResourceBundle
*localeBundle
= ures_open(NULL
, locale
.getName(), &status
);
457 if (U_SUCCESS(status
)) {
458 UResourceBundle
*contextTransforms
= ures_getByKeyWithFallback(localeBundle
, "contextTransforms", NULL
, &status
);
459 if (U_SUCCESS(status
)) {
460 UResourceBundle
*contextTransformUsage
;
461 while ( (contextTransformUsage
= ures_getNextResource(contextTransforms
, NULL
, &status
)) != NULL
) {
462 const int32_t * intVector
= ures_getIntVector(contextTransformUsage
, &len
, &status
);
463 if (U_SUCCESS(status
) && intVector
!= NULL
&& len
>= 2) {
464 const char* usageKey
= ures_getKey(contextTransformUsage
);
465 if (usageKey
!= NULL
) {
466 const ContextUsageNameToEnum
* typeMapPtr
= contextUsageTypeMap
;
467 int32_t compResult
= 0;
468 // linear search; list is short and we cannot be sure that bsearch is available
469 while ( typeMapPtr
->usageName
!= NULL
&& (compResult
= uprv_strcmp(usageKey
, typeMapPtr
->usageName
)) > 0 ) {
472 if (typeMapPtr
->usageName
!= NULL
&& compResult
== 0) {
473 int32_t titlecaseInt
= (capitalizationContext
== UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
)? intVector
[0]: intVector
[1];
474 if (titlecaseInt
!= 0) {
475 fCapitalization
[typeMapPtr
->usageEnum
] = TRUE
;;
481 status
= U_ZERO_ERROR
;
482 ures_close(contextTransformUsage
);
484 ures_close(contextTransforms
);
486 ures_close(localeBundle
);
489 // Get a sentence break iterator if we will need it
490 if (needBrkIter
|| capitalizationContext
== UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
) {
491 status
= U_ZERO_ERROR
;
492 capitalizationBrkIter
= BreakIterator::createSentenceInstance(locale
, status
);
493 if (U_FAILURE(status
)) {
494 delete capitalizationBrkIter
;
495 capitalizationBrkIter
= NULL
;
501 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
502 delete separatorFormat
;
504 delete keyTypeFormat
;
505 delete capitalizationBrkIter
;
509 LocaleDisplayNamesImpl::getLocale() const {
514 LocaleDisplayNamesImpl::getDialectHandling() const {
515 return dialectHandling
;
519 LocaleDisplayNamesImpl::getContext(UDisplayContextType type
) const {
521 case UDISPCTX_TYPE_DIALECT_HANDLING
:
522 return (UDisplayContext
)dialectHandling
;
523 case UDISPCTX_TYPE_CAPITALIZATION
:
524 return capitalizationContext
;
525 case UDISPCTX_TYPE_DISPLAY_LENGTH
:
527 case UADISPCTX_TYPE_LENGTH
: // Apple-specific
528 return (nameLength
== UDISPCTX_LENGTH_SHORT
)? UADISPCTX_LENGTH_SHORT
: UADISPCTX_LENGTH_STANDARD
;
532 return (UDisplayContext
)0;
536 LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage
,
537 UnicodeString
& result
) const {
538 #if !UCONFIG_NO_BREAK_ITERATION
539 // check to see whether we need to titlecase result
540 if ( result
.length() > 0 && u_islower(result
.char32At(0)) && capitalizationBrkIter
!= NULL
&&
541 ( capitalizationContext
==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
|| fCapitalization
[usage
] ) ) {
542 // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE
543 Mutex
lock(&capitalizationBrkIterLock
);
544 result
.toTitle(capitalizationBrkIter
, locale
, U_TITLECASE_NO_LOWERCASE
| U_TITLECASE_NO_BREAK_ADJUSTMENT
);
551 LocaleDisplayNamesImpl::localeDisplayName(const Locale
& locale
,
552 UnicodeString
& result
) const {
553 UnicodeString resultName
;
555 const char* lang
= locale
.getLanguage();
556 if (uprv_strlen(lang
) == 0) {
559 const char* script
= locale
.getScript();
560 const char* country
= locale
.getCountry();
561 const char* variant
= locale
.getVariant();
563 UBool hasScript
= uprv_strlen(script
) > 0;
564 UBool hasCountry
= uprv_strlen(country
) > 0;
565 UBool hasVariant
= uprv_strlen(variant
) > 0;
567 if (dialectHandling
== ULDN_DIALECT_NAMES
) {
568 char buffer
[ULOC_FULLNAME_CAPACITY
];
569 do { // loop construct is so we can break early out of search
570 if (hasScript
&& hasCountry
) {
571 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", script
, "_", country
, (char *)0);
572 localeIdName(buffer
, resultName
);
573 if (!resultName
.isBogus()) {
580 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", script
, (char *)0);
581 localeIdName(buffer
, resultName
);
582 if (!resultName
.isBogus()) {
588 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", country
, (char*)0);
589 localeIdName(buffer
, resultName
);
590 if (!resultName
.isBogus()) {
597 if (resultName
.isBogus() || resultName
.isEmpty()) {
598 localeIdName(lang
, resultName
);
601 UnicodeString resultRemainder
;
603 StringEnumeration
*e
= NULL
;
604 UErrorCode status
= U_ZERO_ERROR
;
607 resultRemainder
.append(scriptDisplayName(script
, temp
));
610 appendWithSep(resultRemainder
, regionShortDisplayName(country
, temp
)); // Apple modification
613 appendWithSep(resultRemainder
, variantDisplayName(variant
, temp
));
615 resultRemainder
.findAndReplace(formatOpenParen
, formatReplaceOpenParen
);
616 resultRemainder
.findAndReplace(formatCloseParen
, formatReplaceCloseParen
);
618 e
= locale
.createKeywords(status
);
619 if (e
&& U_SUCCESS(status
)) {
621 char value
[ULOC_KEYWORD_AND_VALUES_CAPACITY
]; // sigh, no ULOC_VALUE_CAPACITY
623 while ((key
= e
->next((int32_t *)0, status
)) != NULL
) {
624 locale
.getKeywordValue(key
, value
, ULOC_KEYWORD_AND_VALUES_CAPACITY
, status
);
625 keyDisplayName(key
, temp
);
626 temp
.findAndReplace(formatOpenParen
, formatReplaceOpenParen
);
627 temp
.findAndReplace(formatCloseParen
, formatReplaceCloseParen
);
628 keyValueDisplayName(key
, value
, temp2
);
629 temp2
.findAndReplace(formatOpenParen
, formatReplaceOpenParen
);
630 temp2
.findAndReplace(formatCloseParen
, formatReplaceCloseParen
);
631 if (temp2
!= UnicodeString(value
, -1, US_INV
)) {
632 appendWithSep(resultRemainder
, temp2
);
633 } else if (temp
!= UnicodeString(key
, -1, US_INV
)) {
635 Formattable data
[] = {
640 status
= U_ZERO_ERROR
;
641 keyTypeFormat
->format(data
, 2, temp3
, fpos
, status
);
642 appendWithSep(resultRemainder
, temp3
);
644 appendWithSep(resultRemainder
, temp
)
645 .append((UChar
)0x3d /* = */)
652 if (!resultRemainder
.isEmpty()) {
653 Formattable data
[] = {
658 status
= U_ZERO_ERROR
;
659 format
->format(data
, 2, result
, fpos
, status
);
660 return adjustForUsageAndContext(kCapContextUsageLanguage
, result
);
664 return adjustForUsageAndContext(kCapContextUsageLanguage
, result
);
668 LocaleDisplayNamesImpl::appendWithSep(UnicodeString
& buffer
, const UnicodeString
& src
) const {
669 if (buffer
.isEmpty()) {
672 UnicodeString combined
;
673 Formattable data
[] = {
678 UErrorCode status
= U_ZERO_ERROR
;
679 separatorFormat
->format(data
, 2, combined
, fpos
, status
);
680 if (U_SUCCESS(status
)) {
681 buffer
.setTo(combined
);
688 LocaleDisplayNamesImpl::localeDisplayName(const char* localeId
,
689 UnicodeString
& result
) const {
690 return localeDisplayName(Locale(localeId
), result
);
695 LocaleDisplayNamesImpl::localeIdName(const char* localeId
,
696 UnicodeString
& result
) const {
697 if (nameLength
== UDISPCTX_LENGTH_SHORT
) {
698 langData
.getNoFallback("Languages%short", localeId
, result
);
699 if (!result
.isBogus()) {
703 return langData
.getNoFallback("Languages", localeId
, result
);
707 LocaleDisplayNamesImpl::languageDisplayName(const char* lang
,
708 UnicodeString
& result
) const {
709 if (uprv_strcmp("root", lang
) == 0 || uprv_strchr(lang
, '_') != NULL
) {
710 return result
= UnicodeString(lang
, -1, US_INV
);
712 if (nameLength
== UDISPCTX_LENGTH_SHORT
) {
713 langData
.get("Languages%short", lang
, result
);
714 if (!result
.isBogus()) {
715 return adjustForUsageAndContext(kCapContextUsageLanguage
, result
);
718 langData
.get("Languages", lang
, result
);
719 return adjustForUsageAndContext(kCapContextUsageLanguage
, result
);
723 LocaleDisplayNamesImpl::scriptDisplayName(const char* script
,
724 UnicodeString
& result
) const {
725 if (nameLength
== UDISPCTX_LENGTH_SHORT
) {
726 langData
.get("Scripts%short", script
, result
);
727 if (!result
.isBogus()) {
728 return adjustForUsageAndContext(kCapContextUsageScript
, result
);
731 langData
.get("Scripts", script
, result
);
732 return adjustForUsageAndContext(kCapContextUsageScript
, result
);
736 LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode
,
737 UnicodeString
& result
) const {
738 return scriptDisplayName(uscript_getName(scriptCode
), result
);
742 LocaleDisplayNamesImpl::regionDisplayName(const char* region
,
743 UnicodeString
& result
) const {
744 if (nameLength
== UDISPCTX_LENGTH_SHORT
) {
745 regionData
.get("Countries%short", region
, result
);
746 if (!result
.isBogus()) {
747 return adjustForUsageAndContext(kCapContextUsageTerritory
, result
);
750 regionData
.get("Countries", region
, result
);
751 return adjustForUsageAndContext(kCapContextUsageTerritory
, result
);
756 LocaleDisplayNamesImpl::regionShortDisplayName(const char* region
,
757 UnicodeString
& result
) const {
758 if (uprv_strcmp(region
, "PS") != 0) {
759 regionData
.getNoFallback("Countries%short", region
, result
);
760 if (!result
.isBogus()) {
761 return adjustForUsageAndContext(kCapContextUsageTerritory
, result
);
764 regionData
.get("Countries", region
, result
);
765 return adjustForUsageAndContext(kCapContextUsageTerritory
, result
);
769 LocaleDisplayNamesImpl::variantDisplayName(const char* variant
,
770 UnicodeString
& result
) const {
771 // don't have a resource for short variant names
772 langData
.get("Variants", variant
, result
);
773 return adjustForUsageAndContext(kCapContextUsageVariant
, result
);
777 LocaleDisplayNamesImpl::keyDisplayName(const char* key
,
778 UnicodeString
& result
) const {
779 // don't have a resource for short key names
780 langData
.get("Keys", key
, result
);
781 return adjustForUsageAndContext(kCapContextUsageKey
, result
);
785 LocaleDisplayNamesImpl::keyValueDisplayName(const char* key
,
787 UnicodeString
& result
) const {
788 if (uprv_strcmp(key
, "currency") == 0) {
789 // ICU4C does not have ICU4J CurrencyDisplayInfo equivalent for now.
790 UErrorCode sts
= U_ZERO_ERROR
;
791 UnicodeString
ustrValue(value
, -1, US_INV
);
793 UBool isChoice
= FALSE
;
794 const UChar
*currencyName
= ucurr_getName(ustrValue
.getTerminatedBuffer(),
795 locale
.getBaseName(), UCURR_LONG_NAME
, &isChoice
, &len
, &sts
);
796 if (U_FAILURE(sts
)) {
797 // Return the value as is on failure
801 result
.setTo(currencyName
, len
);
802 return adjustForUsageAndContext(kCapContextUsageKeyValue
, result
);
805 if (nameLength
== UDISPCTX_LENGTH_SHORT
) {
806 langData
.get("Types%short", key
, value
, result
);
807 if (!result
.isBogus()) {
808 return adjustForUsageAndContext(kCapContextUsageKeyValue
, result
);
811 langData
.get("Types", key
, value
, result
);
812 return adjustForUsageAndContext(kCapContextUsageKeyValue
, result
);
815 ////////////////////////////////////////////////////////////////////////////////////////////////////
818 LocaleDisplayNames::createInstance(const Locale
& locale
,
819 UDialectHandling dialectHandling
) {
820 return new LocaleDisplayNamesImpl(locale
, dialectHandling
);
824 LocaleDisplayNames::createInstance(const Locale
& locale
,
825 UDisplayContext
*contexts
, int32_t length
) {
826 if (contexts
== NULL
) {
829 return new LocaleDisplayNamesImpl(locale
, contexts
, length
);
834 ////////////////////////////////////////////////////////////////////////////////////////////////////
838 U_CAPI ULocaleDisplayNames
* U_EXPORT2
839 uldn_open(const char * locale
,
840 UDialectHandling dialectHandling
,
841 UErrorCode
*pErrorCode
) {
842 if (U_FAILURE(*pErrorCode
)) {
845 if (locale
== NULL
) {
846 locale
= uloc_getDefault();
848 return (ULocaleDisplayNames
*)LocaleDisplayNames::createInstance(Locale(locale
), dialectHandling
);
851 U_CAPI ULocaleDisplayNames
* U_EXPORT2
852 uldn_openForContext(const char * locale
,
853 UDisplayContext
*contexts
, int32_t length
,
854 UErrorCode
*pErrorCode
) {
855 if (U_FAILURE(*pErrorCode
)) {
858 if (locale
== NULL
) {
859 locale
= uloc_getDefault();
861 return (ULocaleDisplayNames
*)LocaleDisplayNames::createInstance(Locale(locale
), contexts
, length
);
865 U_CAPI
void U_EXPORT2
866 uldn_close(ULocaleDisplayNames
*ldn
) {
867 delete (LocaleDisplayNames
*)ldn
;
870 U_CAPI
const char * U_EXPORT2
871 uldn_getLocale(const ULocaleDisplayNames
*ldn
) {
873 return ((const LocaleDisplayNames
*)ldn
)->getLocale().getName();
878 U_CAPI UDialectHandling U_EXPORT2
879 uldn_getDialectHandling(const ULocaleDisplayNames
*ldn
) {
881 return ((const LocaleDisplayNames
*)ldn
)->getDialectHandling();
883 return ULDN_STANDARD_NAMES
;
886 U_CAPI UDisplayContext U_EXPORT2
887 uldn_getContext(const ULocaleDisplayNames
*ldn
,
888 UDisplayContextType type
,
889 UErrorCode
*pErrorCode
) {
890 if (U_FAILURE(*pErrorCode
)) {
891 return (UDisplayContext
)0;
893 return ((const LocaleDisplayNames
*)ldn
)->getContext(type
);
896 U_CAPI
int32_t U_EXPORT2
897 uldn_localeDisplayName(const ULocaleDisplayNames
*ldn
,
900 int32_t maxResultSize
,
901 UErrorCode
*pErrorCode
) {
902 if (U_FAILURE(*pErrorCode
)) {
905 if (ldn
== NULL
|| locale
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
906 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
909 UnicodeString
temp(result
, 0, maxResultSize
);
910 ((const LocaleDisplayNames
*)ldn
)->localeDisplayName(locale
, temp
);
911 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
914 U_CAPI
int32_t U_EXPORT2
915 uldn_languageDisplayName(const ULocaleDisplayNames
*ldn
,
918 int32_t maxResultSize
,
919 UErrorCode
*pErrorCode
) {
920 if (U_FAILURE(*pErrorCode
)) {
923 if (ldn
== NULL
|| lang
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
924 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
927 UnicodeString
temp(result
, 0, maxResultSize
);
928 ((const LocaleDisplayNames
*)ldn
)->languageDisplayName(lang
, temp
);
929 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
932 U_CAPI
int32_t U_EXPORT2
933 uldn_scriptDisplayName(const ULocaleDisplayNames
*ldn
,
936 int32_t maxResultSize
,
937 UErrorCode
*pErrorCode
) {
938 if (U_FAILURE(*pErrorCode
)) {
941 if (ldn
== NULL
|| script
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
942 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
945 UnicodeString
temp(result
, 0, maxResultSize
);
946 ((const LocaleDisplayNames
*)ldn
)->scriptDisplayName(script
, temp
);
947 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
950 U_CAPI
int32_t U_EXPORT2
951 uldn_scriptCodeDisplayName(const ULocaleDisplayNames
*ldn
,
952 UScriptCode scriptCode
,
954 int32_t maxResultSize
,
955 UErrorCode
*pErrorCode
) {
956 return uldn_scriptDisplayName(ldn
, uscript_getName(scriptCode
), result
, maxResultSize
, pErrorCode
);
959 U_CAPI
int32_t U_EXPORT2
960 uldn_regionDisplayName(const ULocaleDisplayNames
*ldn
,
963 int32_t maxResultSize
,
964 UErrorCode
*pErrorCode
) {
965 if (U_FAILURE(*pErrorCode
)) {
968 if (ldn
== NULL
|| region
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
969 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
972 UnicodeString
temp(result
, 0, maxResultSize
);
973 ((const LocaleDisplayNames
*)ldn
)->regionDisplayName(region
, temp
);
974 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
977 U_CAPI
int32_t U_EXPORT2
978 uldn_variantDisplayName(const ULocaleDisplayNames
*ldn
,
981 int32_t maxResultSize
,
982 UErrorCode
*pErrorCode
) {
983 if (U_FAILURE(*pErrorCode
)) {
986 if (ldn
== NULL
|| variant
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
987 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
990 UnicodeString
temp(result
, 0, maxResultSize
);
991 ((const LocaleDisplayNames
*)ldn
)->variantDisplayName(variant
, temp
);
992 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
995 U_CAPI
int32_t U_EXPORT2
996 uldn_keyDisplayName(const ULocaleDisplayNames
*ldn
,
999 int32_t maxResultSize
,
1000 UErrorCode
*pErrorCode
) {
1001 if (U_FAILURE(*pErrorCode
)) {
1004 if (ldn
== NULL
|| key
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
1005 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
1008 UnicodeString
temp(result
, 0, maxResultSize
);
1009 ((const LocaleDisplayNames
*)ldn
)->keyDisplayName(key
, temp
);
1010 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
1013 U_CAPI
int32_t U_EXPORT2
1014 uldn_keyValueDisplayName(const ULocaleDisplayNames
*ldn
,
1018 int32_t maxResultSize
,
1019 UErrorCode
*pErrorCode
) {
1020 if (U_FAILURE(*pErrorCode
)) {
1023 if (ldn
== NULL
|| key
== NULL
|| value
== NULL
|| (result
== NULL
&& maxResultSize
> 0)
1024 || maxResultSize
< 0) {
1025 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
1028 UnicodeString
temp(result
, 0, maxResultSize
);
1029 ((const LocaleDisplayNames
*)ldn
)->keyValueDisplayName(key
, value
, temp
);
1030 return temp
.extract(result
, maxResultSize
, *pErrorCode
);