diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
index b30c26961ee..0ed81c29048 100644
--- a/icu4c/source/common/locid.cpp
+++ b/icu4c/source/common/locid.cpp
@@ -63,6 +63,7 @@ typedef enum ELocalePos {
eUS,
eCANADA,
eCANADA_FRENCH,
+ eROOT,
//eDEFAULT,
@@ -498,7 +499,7 @@ Locale &Locale::operator=(const Locale &other)
uprv_strcpy(script, other.script);
uprv_strcpy(country, other.country);
- /* The variantBegin is an offset into fullName, just copy it */
+ /* The variantBegin is an offset, just copy it */
variantBegin = other.variantBegin;
fIsBogus = other.fIsBogus;
return *this;
@@ -654,6 +655,10 @@ Locale::setToBogus() {
uprv_free(fullName);
fullName = fullNameBuffer;
}
+ if(baseName && baseName != baseNameBuffer) {
+ uprv_free(baseName);
+ baseName = NULL;
+ }
*fullNameBuffer = 0;
*language = 0;
*script = 0;
@@ -1001,6 +1006,12 @@ void Locale::setFromPOSIXID(const char *posixID)
init(posixID, TRUE);
}
+const Locale & U_EXPORT2
+Locale::getRoot(void)
+{
+ return getLocale(eROOT);
+}
+
const Locale & U_EXPORT2
Locale::getEnglish(void)
{
@@ -1157,6 +1168,7 @@ Locale::getLocaleCache(void)
if (tLocaleCache == NULL) {
return NULL;
}
+ tLocaleCache[eROOT] = Locale("");
tLocaleCache[eENGLISH] = Locale("en");
tLocaleCache[eFRENCH] = Locale("fr");
tLocaleCache[eGERMAN] = Locale("de");
diff --git a/icu4c/source/common/uloc.c b/icu4c/source/common/uloc.c
index d525e0aad52..638b3074e82 100644
--- a/icu4c/source/common/uloc.c
+++ b/icu4c/source/common/uloc.c
@@ -1,6 +1,6 @@
/*
**********************************************************************
-* Copyright (C) 1997-2009, International Business Machines
+* Copyright (C) 1997-2010, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
@@ -2116,8 +2116,8 @@ uloc_setDefault(const char* newDefaultLocale,
* default locale because that would result in a mix of languages that is
* unpredictable to the programmer and most likely useless.
*/
-static const UChar *
-_res_getTableStringWithFallback(const char *path, const char *locale,
+U_CAPI const UChar * U_EXPORT2
+uloc_getTableStringWithFallback(const char *path, const char *locale,
const char *tableKey, const char *subTableKey,
const char *itemKey,
int32_t *pLength,
@@ -2256,7 +2256,7 @@ _getStringOrCopyKey(const char *path, const char *locale,
*pErrorCode = U_MISSING_RESOURCE_ERROR;
} else {
/* second-level item, use special fallback */
- s=_res_getTableStringWithFallback(path, locale,
+ s=uloc_getTableStringWithFallback(path, locale,
tableKey,
subTableKey,
itemKey,
@@ -2953,7 +2953,7 @@ _uloc_getOrientationHelper(const char* localeId,
if (!U_FAILURE(*status)) {
const UChar* const value =
- _res_getTableStringWithFallback(
+ uloc_getTableStringWithFallback(
NULL,
localeBuffer,
"layout",
diff --git a/icu4c/source/common/ulocimp.h b/icu4c/source/common/ulocimp.h
index a0ea6aa5fcc..c397121194e 100644
--- a/icu4c/source/common/ulocimp.h
+++ b/icu4c/source/common/ulocimp.h
@@ -1,6 +1,6 @@
/*
**********************************************************************
-* Copyright (C) 2004, International Business Machines
+* Copyright (C) 2004-2010, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
@@ -21,4 +21,18 @@
U_CAPI UEnumeration* U_EXPORT2
uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status);
+/**
+ * Look up a resource bundle table item with fallback on the table level.
+ * This is accessible so it can be called by C++ code.
+ */
+U_CAPI const UChar * U_EXPORT2
+uloc_getTableStringWithFallback(
+ const char *path,
+ const char *locale,
+ const char *tableKey,
+ const char *subTableKey,
+ const char *itemKey,
+ int32_t *pLength,
+ UErrorCode *pErrorCode);
+
#endif
diff --git a/icu4c/source/common/unicode/locid.h b/icu4c/source/common/unicode/locid.h
index 55656bfb2c5..c7ddc936f9e 100644
--- a/icu4c/source/common/unicode/locid.h
+++ b/icu4c/source/common/unicode/locid.h
@@ -180,6 +180,8 @@
U_NAMESPACE_BEGIN
class U_COMMON_API Locale : public UObject {
public:
+ /** Useful constant for the Root locale. @draft ICU 4.4 */
+ static const Locale &U_EXPORT2 getRoot(void);
/** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getEnglish(void);
/** Useful constant for this language. @stable ICU 2.0 */
@@ -425,8 +427,9 @@ public:
/**
* Gets the list of keywords for the specified locale.
*
- * @return pointer to StringEnumeration class. Client must dispose of it by calling delete.
- * @param status Returns any error information while performing this operation.
+ * @param status the status code
+ * @return pointer to StringEnumeration class, or NULL if there are no keywords.
+ * Client must dispose of it by calling delete.
* @stable ICU 2.8
*/
StringEnumeration * createKeywords(UErrorCode &status) const;
@@ -435,10 +438,10 @@ public:
* Get the value for a keyword.
*
* @param keywordName name of the keyword for which we want the value. Case insensitive.
- * @param status Returns any error information while performing this operation.
* @param buffer The buffer to receive the keyword value.
* @param bufferCapacity The capacity of receiving buffer
- * @return the length of keyword value
+ * @param status Returns any error information while performing this operation.
+ * @return the length of the keyword value
*
* @stable ICU 2.8
*/
@@ -758,7 +761,8 @@ Locale::getScript() const
inline const char *
Locale::getVariant() const
{
- return &fullName[variantBegin];
+ getBaseName(); // lazy init
+ return &baseName[variantBegin];
}
inline const char *
diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in
index 4d0bc711f5f..0e883416c52 100644
--- a/icu4c/source/i18n/Makefile.in
+++ b/icu4c/source/i18n/Makefile.in
@@ -1,6 +1,6 @@
#******************************************************************************
#
-# Copyright (C) 1998-2009, International Business Machines
+# Copyright (C) 1998-2010, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@@ -83,7 +83,7 @@ wintzimpl.o windtfmt.o winnmfmt.o basictz.o dtrule.o rbtz.o tzrule.o tztrans.o v
zonemeta.o zstrfmt.o plurrule.o plurfmt.o dtitvfmt.o dtitvinf.o \
tmunit.o tmutamt.o tmutfmt.o colldata.o bmsearch.o bms.o currpinf.o \
uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o \
-ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o
+ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o locdspnm.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h
diff --git a/icu4c/source/i18n/i18n.vcproj b/icu4c/source/i18n/i18n.vcproj
index c5d221c8463..7b579ef2fe4 100644
--- a/icu4c/source/i18n/i18n.vcproj
+++ b/icu4c/source/i18n/i18n.vcproj
@@ -1918,6 +1918,50 @@
RelativePath=".\japancal.h"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/icu4c/source/i18n/locdspnm.cpp b/icu4c/source/i18n/locdspnm.cpp
new file mode 100644
index 00000000000..c2e44debb94
--- /dev/null
+++ b/icu4c/source/i18n/locdspnm.cpp
@@ -0,0 +1,504 @@
+/*
+*******************************************************************************
+* Copyright (C) 2010, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/locdspnm.h"
+
+#include "unicode/msgfmt.h"
+
+#include "cmemory.h"
+#include "cstring.h"
+#include "ulocimp.h"
+#include "ureslocs.h"
+
+/**
+ * Concatenate a number of null-terminated strings to buffer, leaving a
+ * null-terminated string. The last argument should be the null pointer.
+ * Return the length of the string in the buffer, not counting the trailing
+ * null. Return -1 if there is an error (buffer is null, or buflen < 1).
+ */
+static int32_t ncat(char *buffer, uint32_t buflen, ...) {
+ va_list args;
+ char *str;
+ char *p = buffer;
+ const char* e = buffer + buflen - 1;
+
+ if (buffer == NULL || buflen < 1) {
+ return -1;
+ }
+
+ va_start(args, buflen);
+ while (str = va_arg(args, char *)) {
+ char c;
+ while (p != e && (c = *str++)) {
+ *p++ = c;
+ }
+ }
+ *p = 0;
+ va_end(args);
+
+ return p - buffer;
+}
+
+U_NAMESPACE_BEGIN
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Access resource data for locale components.
+// Wrap code in uloc.c for now.
+class ICUDataTable {
+ const char* path;
+ Locale locale;
+
+public:
+ ICUDataTable(const char* path, const Locale& locale);
+ ~ICUDataTable();
+
+ const Locale& getLocale();
+
+ UnicodeString& get(const char* tableKey, const char* itemKey,
+ UnicodeString& result) const;
+ UnicodeString& get(const char* tableKey, const char* subTableKey, const char* itemKey,
+ UnicodeString& result) const;
+
+ UnicodeString& getNoFallback(const char* tableKey, const char* itemKey,
+ UnicodeString &result) const;
+ UnicodeString& getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey,
+ UnicodeString &result) const;
+};
+
+inline UnicodeString &
+ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const {
+ return get(tableKey, NULL, itemKey, result);
+}
+
+inline UnicodeString &
+ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const {
+ return getNoFallback(tableKey, NULL, itemKey, result);
+}
+
+ICUDataTable::ICUDataTable(const char* path, const Locale& locale)
+ : path(NULL), locale(Locale::getRoot())
+{
+ if (path) {
+ int32_t len = uprv_strlen(path);
+ this->path = (const char*) uprv_malloc(len + 1);
+ if (this->path) {
+ uprv_strcpy((char *)this->path, path);
+ this->locale = locale;
+ }
+ }
+}
+
+ICUDataTable::~ICUDataTable() {
+ if (path) {
+ uprv_free((void*) path);
+ path = NULL;
+ }
+}
+
+const Locale&
+ICUDataTable::getLocale() {
+ return locale;
+}
+
+UnicodeString &
+ICUDataTable::get(const char* tableKey, const char* subTableKey, const char* itemKey,
+ UnicodeString &result) const {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+
+ const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(),
+ tableKey, subTableKey, itemKey,
+ &len, &status);
+ if (U_SUCCESS(status)) {
+ return result.setTo(s, len);
+ }
+ return result.setTo(UnicodeString(itemKey, -1, US_INV));
+}
+
+UnicodeString &
+ICUDataTable::getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey,
+ UnicodeString& result) const {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+
+ const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(),
+ tableKey, subTableKey, itemKey,
+ &len, &status);
+ if (U_SUCCESS(status)) {
+ return result.setTo(s, len);
+ }
+
+ result.setToBogus();
+ return result;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DefaultLocaleDisplayNames : public LocaleDisplayNames {
+ UDialectHandling dialectHandling;
+
+public:
+ // constructor
+ DefaultLocaleDisplayNames(UDialectHandling dialectHandling);
+
+ virtual ~DefaultLocaleDisplayNames();
+
+ virtual const Locale& getLocale() const;
+ virtual UDialectHandling getDialectHandling() const;
+ virtual UnicodeString& localeDisplayName(const Locale& locale,
+ UnicodeString& result) const;
+ virtual UnicodeString& localeDisplayName(const char* localeId,
+ UnicodeString& result) const;
+ virtual UnicodeString& languageDisplayName(const char* lang,
+ UnicodeString& result) const;
+ virtual UnicodeString& scriptDisplayName(const char* script,
+ UnicodeString& result) const;
+ virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode,
+ UnicodeString& result) const;
+ virtual UnicodeString& regionDisplayName(const char* region,
+ UnicodeString& result) const;
+ virtual UnicodeString& variantDisplayName(const char* variant,
+ UnicodeString& result) const;
+ virtual UnicodeString& keyDisplayName(const char* key,
+ UnicodeString& result) const;
+ virtual UnicodeString& keyValueDisplayName(const char* key,
+ const char* value,
+ UnicodeString& result) const;
+};
+
+DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling)
+ : dialectHandling(dialectHandling) {
+}
+
+DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() {
+}
+
+const Locale&
+DefaultLocaleDisplayNames::getLocale() const {
+ return Locale::getRoot();
+}
+
+UDialectHandling
+DefaultLocaleDisplayNames::getDialectHandling() const {
+ return dialectHandling;
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale,
+ UnicodeString& result) const {
+ return result.remove();
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::localeDisplayName(const char* localeId,
+ UnicodeString& result) const {
+ return result.remove();
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::languageDisplayName(const char* lang,
+ UnicodeString& result) const {
+ return result = UnicodeString(lang, -1, US_INV);
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::scriptDisplayName(const char* script,
+ UnicodeString& result) const {
+ return result = UnicodeString(script, -1, US_INV);
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode,
+ UnicodeString& result) const {
+ const char* name = uscript_getName(scriptCode);
+ if (name) {
+ return result = UnicodeString(name, -1, US_INV);
+ }
+ return result.remove();
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::regionDisplayName(const char* region,
+ UnicodeString& result) const {
+ return result = UnicodeString(region, -1, US_INV);
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::variantDisplayName(const char* variant,
+ UnicodeString& result) const {
+ return result = UnicodeString(variant, -1, US_INV);
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::keyDisplayName(const char* key,
+ UnicodeString& result) const {
+ return result = UnicodeString(key, -1, US_INV);
+}
+
+UnicodeString&
+DefaultLocaleDisplayNames::keyValueDisplayName(const char* key,
+ const char* value,
+ UnicodeString& result) const {
+ return result = UnicodeString(value, -1, US_INV);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class LocaleDisplayNamesImpl : public LocaleDisplayNames {
+ Locale locale;
+ UDialectHandling dialectHandling;
+ ICUDataTable langData;
+ ICUDataTable regionData;
+ UnicodeString sep;
+ MessageFormat *format;
+
+public:
+ // constructor
+ LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling);
+ virtual ~LocaleDisplayNamesImpl();
+
+ virtual const Locale& getLocale() const;
+ virtual UDialectHandling getDialectHandling() const;
+
+ virtual UnicodeString& localeDisplayName(const Locale& locale,
+ UnicodeString& result) const;
+ virtual UnicodeString& localeDisplayName(const char* localeId,
+ UnicodeString& result) const;
+ virtual UnicodeString& languageDisplayName(const char* lang,
+ UnicodeString& result) const;
+ virtual UnicodeString& scriptDisplayName(const char* script,
+ UnicodeString& result) const;
+ virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode,
+ UnicodeString& result) const;
+ virtual UnicodeString& regionDisplayName(const char* region,
+ UnicodeString& result) const;
+ virtual UnicodeString& variantDisplayName(const char* variant,
+ UnicodeString& result) const;
+ virtual UnicodeString& keyDisplayName(const char* key,
+ UnicodeString& result) const;
+ virtual UnicodeString& keyValueDisplayName(const char* key,
+ const char* value,
+ UnicodeString& result) const;
+private:
+ UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
+};
+
+LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
+ UDialectHandling dialectHandling)
+ : dialectHandling(dialectHandling)
+ , langData(U_ICUDATA_LANG, locale)
+ , regionData(U_ICUDATA_REGION, locale)
+{
+ LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this;
+ nonConstThis->locale = langData.getLocale() == Locale::getRoot()
+ ? regionData.getLocale()
+ : langData.getLocale();
+
+ langData.getNoFallback("localeDisplayPattern", "separator", sep);
+ if (sep.isBogus()) {
+ sep = UnicodeString(", ", -1, US_INV);
+ }
+
+ UnicodeString pattern;
+ langData.getNoFallback("localeDisplayPattern", "pattern", pattern);
+ if (pattern.isBogus()) {
+ pattern = UnicodeString("{0} ({1})", -1, US_INV);
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ format = new MessageFormat(pattern, status);
+}
+
+LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
+}
+
+const Locale&
+LocaleDisplayNamesImpl::getLocale() const {
+ return locale;
+}
+
+UDialectHandling
+LocaleDisplayNamesImpl::getDialectHandling() const {
+ return dialectHandling;
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale,
+ UnicodeString& result) const {
+ UnicodeString resultName;
+
+ const char* lang = locale.getLanguage();
+ const char* script = locale.getScript();
+ const char* country = locale.getCountry();
+ const char* variant = locale.getVariant();
+
+ UBool hasLang = uprv_strlen(lang) > 0;
+ UBool hasScript = uprv_strlen(script) > 0;
+ UBool hasCountry = uprv_strlen(country) > 0;
+ UBool hasVariant = uprv_strlen(variant) > 0;
+
+ if (hasLang) {
+ if (dialectHandling == ULDN_DIALECT_NAMES) {
+ char buffer[ULOC_FULLNAME_CAPACITY];
+ do { // loop construct is so we can break early out of search
+ if (hasScript && hasCountry) {
+ ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0);
+ langData.getNoFallback("Languages", buffer, resultName);
+ if (!resultName.isBogus()) {
+ hasScript = FALSE;
+ hasCountry = FALSE;
+ break;
+ }
+ }
+ if (hasScript) {
+ ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
+ langData.getNoFallback("Languages", buffer, resultName);
+ if (!resultName.isBogus()) {
+ hasScript = FALSE;
+ break;
+ }
+ }
+ if (hasCountry) {
+ ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
+ langData.getNoFallback("Languages", buffer, resultName);
+ if (!resultName.isBogus()) {
+ hasCountry = FALSE;
+ break;
+ }
+ }
+ } while (FALSE);
+ }
+
+ if (resultName.isBogus() || resultName.isEmpty()) {
+ langData.get("Languages", lang, resultName);
+ }
+ }
+
+ if (TRUE) { /* not language only */
+ UnicodeString resultRemainder;
+ UnicodeString temp;
+ StringEnumeration *e = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+
+ if (hasScript) {
+ resultRemainder.append(scriptDisplayName(script, temp));
+ }
+ if (hasCountry) {
+ appendWithSep(resultRemainder, regionDisplayName(country, temp));
+ }
+ if (hasVariant) {
+ appendWithSep(resultRemainder, variantDisplayName(variant, temp));
+ }
+
+ e = locale.createKeywords(status);
+ if (e && U_SUCCESS(status)) {
+ UnicodeString temp2;
+ char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
+ const char* key;
+ while (key = e->next((int32_t *)0, status)) {
+ locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status);
+ appendWithSep(resultRemainder, keyDisplayName(key, temp))
+ .append("=")
+ .append(keyValueDisplayName(key, value, temp2));
+ }
+ delete e;
+ }
+
+ if (!resultRemainder.isEmpty()) {
+ if (!resultName.isEmpty()) {
+ Formattable data[] = {
+ resultName,
+ resultRemainder
+ };
+ FieldPosition fpos;
+ status = U_ZERO_ERROR;
+ format->format(data, 2, result, fpos, status);
+ return result;
+ }
+
+ return result = resultRemainder;
+ }
+ }
+
+ return result = resultName;
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const {
+ if (!buffer.isEmpty()) {
+ buffer.append(sep);
+ }
+ buffer.append(src);
+ return buffer;
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::localeDisplayName(const char* localeId,
+ UnicodeString& result) const {
+ return localeDisplayName(Locale(localeId), result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::languageDisplayName(const char* lang,
+ UnicodeString& result) const {
+ return langData.get("Languages", lang, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
+ UnicodeString& result) const {
+ return langData.get("Scripts", script, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode,
+ UnicodeString& result) const {
+ const char* name = uscript_getName(scriptCode);
+ return langData.get("Scripts", name, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::regionDisplayName(const char* region,
+ UnicodeString& result) const {
+ return regionData.get("Countries", region, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
+ UnicodeString& result) const {
+ return langData.get("Variants", variant, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::keyDisplayName(const char* key,
+ UnicodeString& result) const {
+ return langData.get("Keys", key, result);
+}
+
+UnicodeString&
+LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
+ const char* value,
+ UnicodeString& result) const {
+ return langData.get("Types", key, value, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+LocaleDisplayNames*
+LocaleDisplayNames::createInstance(const Locale& locale,
+ UDialectHandling dialectHandling) {
+ return new LocaleDisplayNamesImpl(locale, dialectHandling);
+}
+
+U_NAMESPACE_END
+
+#endif
diff --git a/icu4c/source/i18n/unicode/locdspnm.h b/icu4c/source/i18n/unicode/locdspnm.h
new file mode 100644
index 00000000000..402cc0ccf8f
--- /dev/null
+++ b/icu4c/source/i18n/unicode/locdspnm.h
@@ -0,0 +1,203 @@
+/*
+******************************************************************************
+* Copyright (C) 2010, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+******************************************************************************
+*/
+
+#ifndef LOCDSPNM_H
+#define LOCDSPNM_H
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C++ API: Provides display names of Locale and its components.
+ */
+
+
+/**
+ * Enum used in LocaleDisplayNames::createInstance.
+ * @draft ICU 4.4
+ */
+typedef enum {
+ /**
+ * Use standard names when generating a locale name,
+ * e.g. en_GB displays as 'English (United Kingdom)'.
+ * @draft ICU 4.4
+ */
+ ULDN_STANDARD_NAMES = 0,
+ /**
+ * Use dialect names, when generating a locale name,
+ * e.g. en_GB displays as 'British English'.
+ * @draft ICU 4.4
+ */
+ ULDN_DIALECT_NAMES
+} UDialectHandling;
+
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/locid.h"
+#include "unicode/uscript.h"
+
+U_NAMESPACE_BEGIN
+
+/**
+ * Returns display names of Locales and components of Locales. For
+ * more information on language, script, region, variant, key, and
+ * values, see Locale.
+ * @draft ICU 4.4
+ */
+class U_I18N_API LocaleDisplayNames : public UMemory {
+public:
+ /**
+ * Destructor.
+ * @draft ICU 4.4
+ */
+ virtual ~LocaleDisplayNames();
+
+ /**
+ * Convenience overload of {@link #createInstance(locale,
+ * UDialectHandling)} that specifies STANDARD dialect handling.
+ * @param locale the display locale
+ * @return a LocaleDisplayNames instance
+ * @draft ICU 4.4
+ */
+ static LocaleDisplayNames* U_EXPORT2 createInstance(const Locale& locale);
+
+ /**
+ * Returns an instance of LocaleDisplayNames that returns names
+ * formatted for the provided locale, using the provided
+ * dialectHandling.
+ *
+ * @param locale the display locale
+ * @param dialectHandling how to select names for locales
+ * @return a LocaleDisplayNames instance
+ * @draft ICU 4.4
+ */
+ static LocaleDisplayNames* U_EXPORT2 createInstance(const Locale& locale,
+ UDialectHandling dialectHandling);
+
+ // getters for state
+ /**
+ * Returns the locale used to determine the display names. This is
+ * not necessarily the same locale passed to {@link #getInstance}.
+ * @return the display locale
+ * @draft ICU 4.4
+ */
+ virtual const Locale& getLocale() const = 0;
+
+ /**
+ * Returns the dialect handling used in the display names.
+ * @return the dialect handling enum
+ * @draft ICU 4.4
+ */
+ virtual UDialectHandling getDialectHandling() const = 0;
+
+ // names for entire locales
+ /**
+ * Returns the display name of the provided locale.
+ * @param locale the locale whose display name to return
+ * @param result receives the locale's display name
+ * @return the display name of the provided locale
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& localeDisplayName(const Locale& locale,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided locale id.
+ * @param localeId the id of the locale whose display name to return
+ * @param result receives the locale's display name
+ * @return the display name of the provided locale
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& localeDisplayName(const char* localeId,
+ UnicodeString& result) const = 0;
+
+ // names for components of a locale id
+ /**
+ * Returns the display name of the provided language code.
+ * @param lang the language code
+ * @param result receives the language code's display name
+ * @return the display name of the provided language code
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& languageDisplayName(const char* lang,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided script code.
+ * @param script the script code
+ * @param result receives the script code's display name
+ * @return the display name of the provided script code
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& scriptDisplayName(const char* script,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided script code.
+ * @param scriptCode the script code number
+ * @param result receives the script code's display name
+ * @return the display name of the provided script code
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided region code.
+ * @param region the region code
+ * @param result receives the region code's display name
+ * @return the display name of the provided region code
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& regionDisplayName(const char* region,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided variant.
+ * @param variant the variant string
+ * @param result receives the variant's display name
+ * @return the display name of the provided variant
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& variantDisplayName(const char* variant,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided locale key.
+ * @param key the locale key name
+ * @param result receives the locale key's display name
+ * @return the display name of the provided locale key
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& keyDisplayName(const char* key,
+ UnicodeString& result) const = 0;
+
+ /**
+ * Returns the display name of the provided value (used with the provided key).
+ * @param key the locale key name
+ * @param value the locale key's value
+ * @param result receives the value's display name
+ * @return the display name of the provided value
+ * @draft ICU 4.4
+ */
+ virtual UnicodeString& keyValueDisplayName(const char* key, const char* value,
+ UnicodeString& result) const = 0;
+};
+
+inline LocaleDisplayNames::~LocaleDisplayNames() {
+}
+
+inline LocaleDisplayNames* LocaleDisplayNames::createInstance(const Locale& locale) {
+ return LocaleDisplayNames::createInstance(locale, ULDN_STANDARD_NAMES);
+}
+
+U_NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/icu4c/source/test/intltest/Makefile.in b/icu4c/source/test/intltest/Makefile.in
index 6d10d43bb2d..6ac9a8412fd 100644
--- a/icu4c/source/test/intltest/Makefile.in
+++ b/icu4c/source/test/intltest/Makefile.in
@@ -1,6 +1,6 @@
#******************************************************************************
#
-# Copyright (C) 1999-2009, International Business Machines
+# Copyright (C) 1999-2010, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@@ -57,7 +57,7 @@ itrbnf.o itrbnfrt.o itrbnfp.o ucaconf.o icusvtst.o \
uobjtest.o idnaref.o idnaconf.o nptrans.o punyref.o testidn.o testidna.o incaltst.o \
calcasts.o v32test.o uvectest.o textfile.o tokiter.o utxttest.o \
windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o tzoffloc.o tzfmttst.o ssearch.o dtifmtts.o \
-tufmtts.o itspoof.o simplethread.o bidiconf.o
+tufmtts.o itspoof.o simplethread.o bidiconf.o locnmtst.o
DEPS = $(OBJECTS:.o=.d)
diff --git a/icu4c/source/test/intltest/intltest.vcproj b/icu4c/source/test/intltest/intltest.vcproj
index ce9723d2ffc..4865b44817f 100644
--- a/icu4c/source/test/intltest/intltest.vcproj
+++ b/icu4c/source/test/intltest/intltest.vcproj
@@ -947,6 +947,14 @@
RelativePath=".\itrbnfrt.h"
>
+
+
+
+
diff --git a/icu4c/source/test/intltest/itformat.cpp b/icu4c/source/test/intltest/itformat.cpp
index 7a7d7564c0b..45676ef0487 100644
--- a/icu4c/source/test/intltest/itformat.cpp
+++ b/icu4c/source/test/intltest/itformat.cpp
@@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2009, International Business Machines
+ * Copyright (c) 1997-2010, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************/
@@ -52,6 +52,7 @@
#include "plurfmts.h" // PluralFormatTest
#include "dtifmtts.h" // DateIntervalFormatTest
#include "tufmtts.h" // TimeUnitTest
+#include "locnmtst.h" // LocaleDisplayNamesTest
#define TESTCLASS(id, TestClass) \
case id: \
@@ -123,6 +124,7 @@ void IntlTestFormat::runIndexedTest( int32_t index, UBool exec, const char* &nam
TESTCLASS(36,PluralFormatTest);
TESTCLASS(37,DateIntervalFormatTest);
TESTCLASS(38,TimeUnitTest);
+ TESTCLASS(39,LocaleDisplayNamesTest);
default: name = ""; break; //needed to end loop
}
diff --git a/icu4c/source/test/intltest/locnmtst.cpp b/icu4c/source/test/intltest/locnmtst.cpp
new file mode 100644
index 00000000000..98ef62cd31e
--- /dev/null
+++ b/icu4c/source/test/intltest/locnmtst.cpp
@@ -0,0 +1,102 @@
+/*********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2010, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ *********************************************************************/
+
+#include "locnmtst.h"
+
+/*
+ Usage:
+ test_assert( Test (should be TRUE) )
+
+ Example:
+ test_assert(i==3);
+
+ the macro is ugly but makes the tests pretty.
+*/
+
+#define test_assert(test) \
+ { \
+ if(!(test)) \
+ errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \
+ else \
+ logln("PASS: asserted " #test); \
+ }
+
+/*
+ Usage:
+ test_assert_print( Test (should be TRUE), printable )
+
+ Example:
+ test_assert(i==3, toString(i));
+
+ the macro is ugly but makes the tests pretty.
+*/
+
+#define test_assert_print(test,print) \
+ { \
+ if(!(test)) \
+ errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \
+ else \
+ logln("PASS: asserted " #test "-> " + UnicodeString(print)); \
+ }
+
+#define test_assert_equal(target,value) \
+ { \
+ if (UnicodeString(target)!=(value)) { \
+ logln("unexpected value '" + (value) + "'"); \
+ errln("FAIL: " #target " == " #value " was not true. In " __FILE__ " on line %d", __LINE__); \
+ } else { \
+ logln("PASS: asserted " #target " == " #value); \
+ } \
+ }
+
+#define test_dumpLocale(l) { logln(#l " = " + UnicodeString(l.getName(), "")); }
+
+LocaleDisplayNamesTest::LocaleDisplayNamesTest() {
+}
+
+LocaleDisplayNamesTest::~LocaleDisplayNamesTest() {
+}
+
+void LocaleDisplayNamesTest::runIndexedTest(int32_t index, UBool exec, const char* &name,
+ char* /*par*/) {
+ switch (index) {
+#if !UCONFIG_NO_FORMATTING
+ TESTCASE(0, TestCreate);
+ TESTCASE(1, TestCreateDialect);
+ TESTCASE(2, TestWithKeywordsAndEverything);
+#endif
+ default:
+ name = "";
+ break;
+ }
+}
+
+void LocaleDisplayNamesTest::TestCreate() {
+ UnicodeString temp;
+ LocaleDisplayNames *ldn = LocaleDisplayNames::createInstance(Locale::getGermany());
+ ldn->localeDisplayName("de_DE", temp);
+ delete ldn;
+ test_assert_equal("Deutsch (Deutschland)", temp);
+}
+
+void LocaleDisplayNamesTest::TestCreateDialect() {
+ UnicodeString temp;
+ LocaleDisplayNames *ldn = LocaleDisplayNames::createInstance(Locale::getUS(), ULDN_DIALECT_NAMES);
+ ldn->localeDisplayName("en_GB", temp);
+ delete ldn;
+ test_assert_equal("British English", temp);
+}
+
+void LocaleDisplayNamesTest::TestWithKeywordsAndEverything() {
+ UnicodeString temp;
+ LocaleDisplayNames *ldn = LocaleDisplayNames::createInstance(Locale::getUS());
+ const char *locname = "en_Hant_US_VALLEY@calendar=gregorian;collation=phonebook";
+ const char *target = "English (Traditional Han, United States, VALLEY, "
+ "calendar=Gregorian Calendar, collation=Phonebook Sort Order)";
+ ldn->localeDisplayName(locname, temp);
+ delete ldn;
+ test_assert_equal(target, temp);
+}
diff --git a/icu4c/source/test/intltest/locnmtst.h b/icu4c/source/test/intltest/locnmtst.h
new file mode 100644
index 00000000000..b3b90699f2d
--- /dev/null
+++ b/icu4c/source/test/intltest/locnmtst.h
@@ -0,0 +1,28 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2010, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+#include "intltest.h"
+#include "unicode/locdspnm.h"
+
+/**
+ * Tests for the LocaleDisplayNames class
+ **/
+class LocaleDisplayNamesTest: public IntlTest {
+public:
+ LocaleDisplayNamesTest();
+ virtual ~LocaleDisplayNamesTest();
+
+ void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL);
+
+#if !UCONFIG_NO_FORMATTING
+ /**
+ * Test methods to set and get data fields
+ **/
+ void TestCreate(void);
+ void TestCreateDialect(void);
+ void TestWithKeywordsAndEverything(void);
+#endif
+};
diff --git a/icu4c/source/test/intltest/loctest.cpp b/icu4c/source/test/intltest/loctest.cpp
index 52fca11dd94..4b5249bda93 100644
--- a/icu4c/source/test/intltest/loctest.cpp
+++ b/icu4c/source/test/intltest/loctest.cpp
@@ -220,6 +220,7 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
TESTCASE(29, TestVariantWithOutCountry);
TESTCASE(30, TestCanonicalization);
TESTCASE(31, TestCurrencyByDate);
+ TESTCASE(32, TestGetVariantWithKeywords);
// keep the last index in sync with the condition in default:
@@ -2492,3 +2493,11 @@ void LocaleTest::TestCurrencyByDate(void)
status = U_ZERO_ERROR; // reset
#endif
}
+
+void LocaleTest::TestGetVariantWithKeywords(void)
+{
+ Locale l("en_US_VALLEY@foo");
+ const char *variant = l.getVariant();
+ logln(variant);
+ test_assert(strcmp("VALLEY", variant) == 0);
+}
diff --git a/icu4c/source/test/intltest/loctest.h b/icu4c/source/test/intltest/loctest.h
index da5a7469f23..a9172b92071 100644
--- a/icu4c/source/test/intltest/loctest.h
+++ b/icu4c/source/test/intltest/loctest.h
@@ -100,6 +100,8 @@ public:
void TestCurrencyByDate(void);
+ void TestGetVariantWithKeywords(void);
+
private:
void _checklocs(const char* label,
const char* req,