1/* 2******************************************************************************* 3* Copyright (C) 2010, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6*/ 7 8#include "unicode/utypes.h" 9 10#if !UCONFIG_NO_FORMATTING 11 12#include "unicode/locdspnm.h" 13 14#include "unicode/msgfmt.h" 15 16#include "cmemory.h" 17#include "cstring.h" 18#include "ulocimp.h" 19#include "ureslocs.h" 20 21#include <stdarg.h> 22 23/** 24 * Concatenate a number of null-terminated strings to buffer, leaving a 25 * null-terminated string. The last argument should be the null pointer. 26 * Return the length of the string in the buffer, not counting the trailing 27 * null. Return -1 if there is an error (buffer is null, or buflen < 1). 28 */ 29static int32_t ncat(char *buffer, uint32_t buflen, ...) { 30 va_list args; 31 char *str; 32 char *p = buffer; 33 const char* e = buffer + buflen - 1; 34 35 if (buffer == NULL || buflen < 1) { 36 return -1; 37 } 38 39 va_start(args, buflen); 40 while ((str = va_arg(args, char *))) { 41 char c; 42 while (p != e && (c = *str++)) { 43 *p++ = c; 44 } 45 } 46 *p = 0; 47 va_end(args); 48 49 return p - buffer; 50} 51 52U_NAMESPACE_BEGIN 53 54//////////////////////////////////////////////////////////////////////////////////////////////////// 55 56// Access resource data for locale components. 57// Wrap code in uloc.c for now. 58class ICUDataTable { 59 const char* path; 60 Locale locale; 61 62public: 63 ICUDataTable(const char* path, const Locale& locale); 64 ~ICUDataTable(); 65 66 const Locale& getLocale(); 67 68 UnicodeString& get(const char* tableKey, const char* itemKey, 69 UnicodeString& result) const; 70 UnicodeString& get(const char* tableKey, const char* subTableKey, const char* itemKey, 71 UnicodeString& result) const; 72 73 UnicodeString& getNoFallback(const char* tableKey, const char* itemKey, 74 UnicodeString &result) const; 75 UnicodeString& getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 76 UnicodeString &result) const; 77}; 78 79inline UnicodeString & 80ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const { 81 return get(tableKey, NULL, itemKey, result); 82} 83 84inline UnicodeString & 85ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const { 86 return getNoFallback(tableKey, NULL, itemKey, result); 87} 88 89ICUDataTable::ICUDataTable(const char* path, const Locale& locale) 90 : path(NULL), locale(Locale::getRoot()) 91{ 92 if (path) { 93 int32_t len = uprv_strlen(path); 94 this->path = (const char*) uprv_malloc(len + 1); 95 if (this->path) { 96 uprv_strcpy((char *)this->path, path); 97 this->locale = locale; 98 } 99 } 100} 101 102ICUDataTable::~ICUDataTable() { 103 if (path) { 104 uprv_free((void*) path); 105 path = NULL; 106 } 107} 108 109const Locale& 110ICUDataTable::getLocale() { 111 return locale; 112} 113 114UnicodeString & 115ICUDataTable::get(const char* tableKey, const char* subTableKey, const char* itemKey, 116 UnicodeString &result) const { 117 UErrorCode status = U_ZERO_ERROR; 118 int32_t len = 0; 119 120 const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 121 tableKey, subTableKey, itemKey, 122 &len, &status); 123 if (U_SUCCESS(status)) { 124 return result.setTo(s, len); 125 } 126 return result.setTo(UnicodeString(itemKey, -1, US_INV)); 127} 128 129UnicodeString & 130ICUDataTable::getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 131 UnicodeString& result) const { 132 UErrorCode status = U_ZERO_ERROR; 133 int32_t len = 0; 134 135 const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 136 tableKey, subTableKey, itemKey, 137 &len, &status); 138 if (U_SUCCESS(status)) { 139 return result.setTo(s, len); 140 } 141 142 result.setToBogus(); 143 return result; 144} 145 146//////////////////////////////////////////////////////////////////////////////////////////////////// 147 148UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(LocaleDisplayNames) 149 150//////////////////////////////////////////////////////////////////////////////////////////////////// 151 152#if 0 // currently unused 153 154class DefaultLocaleDisplayNames : public LocaleDisplayNames { 155 UDialectHandling dialectHandling; 156 157public: 158 // constructor 159 DefaultLocaleDisplayNames(UDialectHandling dialectHandling); 160 161 virtual ~DefaultLocaleDisplayNames(); 162 163 virtual const Locale& getLocale() const; 164 virtual UDialectHandling getDialectHandling() const; 165 virtual UnicodeString& localeDisplayName(const Locale& locale, 166 UnicodeString& result) const; 167 virtual UnicodeString& localeDisplayName(const char* localeId, 168 UnicodeString& result) const; 169 virtual UnicodeString& languageDisplayName(const char* lang, 170 UnicodeString& result) const; 171 virtual UnicodeString& scriptDisplayName(const char* script, 172 UnicodeString& result) const; 173 virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 174 UnicodeString& result) const; 175 virtual UnicodeString& regionDisplayName(const char* region, 176 UnicodeString& result) const; 177 virtual UnicodeString& variantDisplayName(const char* variant, 178 UnicodeString& result) const; 179 virtual UnicodeString& keyDisplayName(const char* key, 180 UnicodeString& result) const; 181 virtual UnicodeString& keyValueDisplayName(const char* key, 182 const char* value, 183 UnicodeString& result) const; 184}; 185 186DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling) 187 : dialectHandling(dialectHandling) { 188} 189 190DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() { 191} 192 193const Locale& 194DefaultLocaleDisplayNames::getLocale() const { 195 return Locale::getRoot(); 196} 197 198UDialectHandling 199DefaultLocaleDisplayNames::getDialectHandling() const { 200 return dialectHandling; 201} 202 203UnicodeString& 204DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale, 205 UnicodeString& result) const { 206 return result = UnicodeString(locale.getName(), -1, US_INV); 207} 208 209UnicodeString& 210DefaultLocaleDisplayNames::localeDisplayName(const char* localeId, 211 UnicodeString& result) const { 212 return result = UnicodeString(localeId, -1, US_INV); 213} 214 215UnicodeString& 216DefaultLocaleDisplayNames::languageDisplayName(const char* lang, 217 UnicodeString& result) const { 218 return result = UnicodeString(lang, -1, US_INV); 219} 220 221UnicodeString& 222DefaultLocaleDisplayNames::scriptDisplayName(const char* script, 223 UnicodeString& result) const { 224 return result = UnicodeString(script, -1, US_INV); 225} 226 227UnicodeString& 228DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode, 229 UnicodeString& result) const { 230 const char* name = uscript_getName(scriptCode); 231 if (name) { 232 return result = UnicodeString(name, -1, US_INV); 233 } 234 return result.remove(); 235} 236 237UnicodeString& 238DefaultLocaleDisplayNames::regionDisplayName(const char* region, 239 UnicodeString& result) const { 240 return result = UnicodeString(region, -1, US_INV); 241} 242 243UnicodeString& 244DefaultLocaleDisplayNames::variantDisplayName(const char* variant, 245 UnicodeString& result) const { 246 return result = UnicodeString(variant, -1, US_INV); 247} 248 249UnicodeString& 250DefaultLocaleDisplayNames::keyDisplayName(const char* key, 251 UnicodeString& result) const { 252 return result = UnicodeString(key, -1, US_INV); 253} 254 255UnicodeString& 256DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */, 257 const char* value, 258 UnicodeString& result) const { 259 return result = UnicodeString(value, -1, US_INV); 260} 261 262#endif // currently unused class DefaultLocaleDisplayNames 263 264//////////////////////////////////////////////////////////////////////////////////////////////////// 265 266class LocaleDisplayNamesImpl : public LocaleDisplayNames { 267 Locale locale; 268 UDialectHandling dialectHandling; 269 ICUDataTable langData; 270 ICUDataTable regionData; 271 UnicodeString sep; 272 MessageFormat *format; 273 274public: 275 // constructor 276 LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling); 277 virtual ~LocaleDisplayNamesImpl(); 278 279 virtual const Locale& getLocale() const; 280 virtual UDialectHandling getDialectHandling() const; 281 282 virtual UnicodeString& localeDisplayName(const Locale& locale, 283 UnicodeString& result) const; 284 virtual UnicodeString& localeDisplayName(const char* localeId, 285 UnicodeString& result) const; 286 virtual UnicodeString& languageDisplayName(const char* lang, 287 UnicodeString& result) const; 288 virtual UnicodeString& scriptDisplayName(const char* script, 289 UnicodeString& result) const; 290 virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 291 UnicodeString& result) const; 292 virtual UnicodeString& regionDisplayName(const char* region, 293 UnicodeString& result) const; 294 virtual UnicodeString& variantDisplayName(const char* variant, 295 UnicodeString& result) const; 296 virtual UnicodeString& keyDisplayName(const char* key, 297 UnicodeString& result) const; 298 virtual UnicodeString& keyValueDisplayName(const char* key, 299 const char* value, 300 UnicodeString& result) const; 301 static UClassID U_EXPORT2 getStaticClassID(); 302 virtual UClassID getDynamicClassID() const; 303private: 304 UnicodeString& localeIdName(const char* localeId, 305 UnicodeString& result) const; 306 UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; 307}; 308 309UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleDisplayNamesImpl) 310 311LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, 312 UDialectHandling dialectHandling) 313 : dialectHandling(dialectHandling) 314 , langData(U_ICUDATA_LANG, locale) 315 , regionData(U_ICUDATA_REGION, locale) 316 , format(NULL) 317{ 318 LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this; 319 nonConstThis->locale = langData.getLocale() == Locale::getRoot() 320 ? regionData.getLocale() 321 : langData.getLocale(); 322 323 langData.getNoFallback("localeDisplayPattern", "separator", sep); 324 if (sep.isBogus()) { 325 sep = UnicodeString(", ", -1, US_INV); 326 } 327 328 UnicodeString pattern; 329 langData.getNoFallback("localeDisplayPattern", "pattern", pattern); 330 if (pattern.isBogus()) { 331 pattern = UnicodeString("{0} ({1})", -1, US_INV); 332 } 333 UErrorCode status = U_ZERO_ERROR; 334 format = new MessageFormat(pattern, status); 335} 336 337LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() { 338 delete format; 339} 340 341const Locale& 342LocaleDisplayNamesImpl::getLocale() const { 343 return locale; 344} 345 346UDialectHandling 347LocaleDisplayNamesImpl::getDialectHandling() const { 348 return dialectHandling; 349} 350 351UnicodeString& 352LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale, 353 UnicodeString& result) const { 354 UnicodeString resultName; 355 356 const char* lang = locale.getLanguage(); 357 if (uprv_strlen(lang) == 0) { 358 lang = "root"; 359 } 360 const char* script = locale.getScript(); 361 const char* country = locale.getCountry(); 362 const char* variant = locale.getVariant(); 363 364 UBool hasScript = uprv_strlen(script) > 0; 365 UBool hasCountry = uprv_strlen(country) > 0; 366 UBool hasVariant = uprv_strlen(variant) > 0; 367 368 if (dialectHandling == ULDN_DIALECT_NAMES) { 369 char buffer[ULOC_FULLNAME_CAPACITY]; 370 do { // loop construct is so we can break early out of search 371 if (hasScript && hasCountry) { 372 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); 373 localeIdName(buffer, resultName); 374 if (!resultName.isBogus()) { 375 hasScript = FALSE; 376 hasCountry = FALSE; 377 break; 378 } 379 } 380 if (hasScript) { 381 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); 382 localeIdName(buffer, resultName); 383 if (!resultName.isBogus()) { 384 hasScript = FALSE; 385 break; 386 } 387 } 388 if (hasCountry) { 389 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); 390 localeIdName(buffer, resultName); 391 if (!resultName.isBogus()) { 392 hasCountry = FALSE; 393 break; 394 } 395 } 396 } while (FALSE); 397 } 398 if (resultName.isBogus() || resultName.isEmpty()) { 399 localeIdName(lang, resultName); 400 } 401 402 UnicodeString resultRemainder; 403 UnicodeString temp; 404 StringEnumeration *e = NULL; 405 UErrorCode status = U_ZERO_ERROR; 406 407 if (hasScript) { 408 resultRemainder.append(scriptDisplayName(script, temp)); 409 } 410 if (hasCountry) { 411 appendWithSep(resultRemainder, regionDisplayName(country, temp)); 412 } 413 if (hasVariant) { 414 appendWithSep(resultRemainder, variantDisplayName(variant, temp)); 415 } 416 417 e = locale.createKeywords(status); 418 if (e && U_SUCCESS(status)) { 419 UnicodeString temp2; 420 char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY 421 const char* key; 422 while ((key = e->next((int32_t *)0, status)) != NULL) { 423 locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); 424 appendWithSep(resultRemainder, keyDisplayName(key, temp)) 425 .append("=") 426 .append(keyValueDisplayName(key, value, temp2)); 427 } 428 delete e; 429 } 430 431 if (!resultRemainder.isEmpty()) { 432 Formattable data[] = { 433 resultName, 434 resultRemainder 435 }; 436 FieldPosition fpos; 437 status = U_ZERO_ERROR; 438 format->format(data, 2, result, fpos, status); 439 return result; 440 } 441 442 return result = resultName; 443} 444 445UnicodeString& 446LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const { 447 if (!buffer.isEmpty()) { 448 buffer.append(sep); 449 } 450 buffer.append(src); 451 return buffer; 452} 453 454UnicodeString& 455LocaleDisplayNamesImpl::localeDisplayName(const char* localeId, 456 UnicodeString& result) const { 457 return localeDisplayName(Locale(localeId), result); 458} 459 460UnicodeString& 461LocaleDisplayNamesImpl::localeIdName(const char* localeId, 462 UnicodeString& result) const { 463 return langData.getNoFallback("Languages", localeId, result); 464} 465 466UnicodeString& 467LocaleDisplayNamesImpl::languageDisplayName(const char* lang, 468 UnicodeString& result) const { 469 if (uprv_strcmp("root", lang) == 0 || uprv_strchr(lang, '_') != NULL) { 470 return result = UnicodeString(lang, -1, US_INV); 471 } 472 return langData.get("Languages", lang, result); 473} 474 475UnicodeString& 476LocaleDisplayNamesImpl::scriptDisplayName(const char* script, 477 UnicodeString& result) const { 478 return langData.get("Scripts", script, result); 479} 480 481UnicodeString& 482LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode, 483 UnicodeString& result) const { 484 const char* name = uscript_getName(scriptCode); 485 return langData.get("Scripts", name, result); 486} 487 488UnicodeString& 489LocaleDisplayNamesImpl::regionDisplayName(const char* region, 490 UnicodeString& result) const { 491 return regionData.get("Countries", region, result); 492} 493 494UnicodeString& 495LocaleDisplayNamesImpl::variantDisplayName(const char* variant, 496 UnicodeString& result) const { 497 return langData.get("Variants", variant, result); 498} 499 500UnicodeString& 501LocaleDisplayNamesImpl::keyDisplayName(const char* key, 502 UnicodeString& result) const { 503 return langData.get("Keys", key, result); 504} 505 506UnicodeString& 507LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, 508 const char* value, 509 UnicodeString& result) const { 510 return langData.get("Types", key, value, result); 511} 512 513//////////////////////////////////////////////////////////////////////////////////////////////////// 514 515LocaleDisplayNames* 516LocaleDisplayNames::createInstance(const Locale& locale, 517 UDialectHandling dialectHandling) { 518 return new LocaleDisplayNamesImpl(locale, dialectHandling); 519} 520 521U_NAMESPACE_END 522 523//////////////////////////////////////////////////////////////////////////////////////////////////// 524 525U_NAMESPACE_USE 526 527U_DRAFT ULocaleDisplayNames * U_EXPORT2 528uldn_open(const char * locale, 529 UDialectHandling dialectHandling, 530 UErrorCode *pErrorCode) { 531 if (U_FAILURE(*pErrorCode)) { 532 return 0; 533 } 534 if (locale == NULL) { 535 locale = uloc_getDefault(); 536 } 537 return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), dialectHandling); 538} 539 540U_DRAFT void U_EXPORT2 541uldn_close(ULocaleDisplayNames *ldn) { 542 delete (LocaleDisplayNames *)ldn; 543} 544 545U_DRAFT const char * U_EXPORT2 546uldn_getLocale(const ULocaleDisplayNames *ldn) { 547 if (ldn) { 548 return ((const LocaleDisplayNames *)ldn)->getLocale().getName(); 549 } 550 return NULL; 551} 552 553U_DRAFT UDialectHandling U_EXPORT2 554uldn_getDialectHandling(const ULocaleDisplayNames *ldn) { 555 if (ldn) { 556 return ((const LocaleDisplayNames *)ldn)->getDialectHandling(); 557 } 558 return ULDN_STANDARD_NAMES; 559} 560 561U_DRAFT int32_t U_EXPORT2 562uldn_localeDisplayName(const ULocaleDisplayNames *ldn, 563 const char *locale, 564 UChar *result, 565 int32_t maxResultSize, 566 UErrorCode *pErrorCode) { 567 if (U_FAILURE(*pErrorCode)) { 568 return 0; 569 } 570 if (ldn == NULL || locale == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 571 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 572 return 0; 573 } 574 UnicodeString temp(result, 0, maxResultSize); 575 ((const LocaleDisplayNames *)ldn)->localeDisplayName(locale, temp); 576 return temp.extract(result, maxResultSize, *pErrorCode); 577} 578 579U_DRAFT int32_t U_EXPORT2 580uldn_languageDisplayName(const ULocaleDisplayNames *ldn, 581 const char *lang, 582 UChar *result, 583 int32_t maxResultSize, 584 UErrorCode *pErrorCode) { 585 if (U_FAILURE(*pErrorCode)) { 586 return 0; 587 } 588 if (ldn == NULL || lang == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 589 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 590 return 0; 591 } 592 UnicodeString temp(result, 0, maxResultSize); 593 ((const LocaleDisplayNames *)ldn)->languageDisplayName(lang, temp); 594 return temp.extract(result, maxResultSize, *pErrorCode); 595} 596 597U_DRAFT int32_t U_EXPORT2 598uldn_scriptDisplayName(const ULocaleDisplayNames *ldn, 599 const char *script, 600 UChar *result, 601 int32_t maxResultSize, 602 UErrorCode *pErrorCode) { 603 if (U_FAILURE(*pErrorCode)) { 604 return 0; 605 } 606 if (ldn == NULL || script == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 607 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 608 return 0; 609 } 610 UnicodeString temp(result, 0, maxResultSize); 611 ((const LocaleDisplayNames *)ldn)->scriptDisplayName(script, temp); 612 return temp.extract(result, maxResultSize, *pErrorCode); 613} 614 615U_DRAFT int32_t U_EXPORT2 616uldn_scriptCodeDisplayName(const ULocaleDisplayNames *ldn, 617 UScriptCode scriptCode, 618 UChar *result, 619 int32_t maxResultSize, 620 UErrorCode *pErrorCode) { 621 return uldn_scriptDisplayName(ldn, uscript_getName(scriptCode), result, maxResultSize, pErrorCode); 622} 623 624U_DRAFT int32_t U_EXPORT2 625uldn_regionDisplayName(const ULocaleDisplayNames *ldn, 626 const char *region, 627 UChar *result, 628 int32_t maxResultSize, 629 UErrorCode *pErrorCode) { 630 if (U_FAILURE(*pErrorCode)) { 631 return 0; 632 } 633 if (ldn == NULL || region == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 634 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 635 return 0; 636 } 637 UnicodeString temp(result, 0, maxResultSize); 638 ((const LocaleDisplayNames *)ldn)->regionDisplayName(region, temp); 639 return temp.extract(result, maxResultSize, *pErrorCode); 640} 641 642U_DRAFT int32_t U_EXPORT2 643uldn_variantDisplayName(const ULocaleDisplayNames *ldn, 644 const char *variant, 645 UChar *result, 646 int32_t maxResultSize, 647 UErrorCode *pErrorCode) { 648 if (U_FAILURE(*pErrorCode)) { 649 return 0; 650 } 651 if (ldn == NULL || variant == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 652 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 653 return 0; 654 } 655 UnicodeString temp(result, 0, maxResultSize); 656 ((const LocaleDisplayNames *)ldn)->variantDisplayName(variant, temp); 657 return temp.extract(result, maxResultSize, *pErrorCode); 658} 659 660U_DRAFT int32_t U_EXPORT2 661uldn_keyDisplayName(const ULocaleDisplayNames *ldn, 662 const char *key, 663 UChar *result, 664 int32_t maxResultSize, 665 UErrorCode *pErrorCode) { 666 if (U_FAILURE(*pErrorCode)) { 667 return 0; 668 } 669 if (ldn == NULL || key == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 670 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 671 return 0; 672 } 673 UnicodeString temp(result, 0, maxResultSize); 674 ((const LocaleDisplayNames *)ldn)->keyDisplayName(key, temp); 675 return temp.extract(result, maxResultSize, *pErrorCode); 676} 677 678U_DRAFT int32_t U_EXPORT2 679uldn_keyValueDisplayName(const ULocaleDisplayNames *ldn, 680 const char *key, 681 const char *value, 682 UChar *result, 683 int32_t maxResultSize, 684 UErrorCode *pErrorCode) { 685 if (U_FAILURE(*pErrorCode)) { 686 return 0; 687 } 688 if (ldn == NULL || key == NULL || value == NULL || (result == NULL && maxResultSize > 0) 689 || maxResultSize < 0) { 690 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 691 return 0; 692 } 693 UnicodeString temp(result, 0, maxResultSize); 694 ((const LocaleDisplayNames *)ldn)->keyValueDisplayName(key, value, temp); 695 return temp.extract(result, maxResultSize, *pErrorCode); 696} 697 698#endif 699