From: Frank Tang Date: Fri, 21 Dec 2018 22:45:47 +0000 (-0800) Subject: ICU-20320 Fix the missing digit singleton extension X-Git-Tag: release-64-rc~116 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f46605a437dc55f8874284453beedeebd14ef9f0;p=icu ICU-20320 Fix the missing digit singleton extension Add space add test cases for Java and fix Java code --- diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp index bdc0652df0a..9b5de7f1d9c 100644 --- a/icu4c/source/common/uloc_tag.cpp +++ b/icu4c/source/common/uloc_tag.cpp @@ -507,11 +507,17 @@ static UBool _isExtensionSingleton(const char* s, int32_t len) { /* * extension = singleton 1*("-" (2*8alphanum)) + * + * singleton = DIGIT ; 0 - 9 + * / %x41-57 ; A - W + * / %x59-5A ; Y - Z + * / %x61-77 ; a - w + * / %x79-7A ; y - z */ if (len < 0) { len = (int32_t)uprv_strlen(s); } - if (len == 1 && ISALPHA(*s) && (uprv_tolower(*s) != PRIVATEUSE)) { + if (len == 1 && (ISALPHA(*s) || ISNUMERIC(*s)) && (uprv_tolower(*s) != PRIVATEUSE)) { return TRUE; } return FALSE; diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c index 99f9970a82b..a5b6fe09885 100644 --- a/icu4c/source/test/cintltst/cloctst.c +++ b/icu4c/source/test/cintltst/cloctst.c @@ -5968,6 +5968,7 @@ const char* const locale_to_langtag[][3] = { {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"}, {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo"}, {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"}, + {"en@9=efg;a=baz", "en-9-efg-a-baz", "en-9-efg-a-baz"}, {NULL, NULL, NULL} }; @@ -6154,6 +6155,7 @@ static const struct { {"sgn-br-u-co-phonebk", "bzs@collation=phonebook", FULL_LENGTH}, {"ja-latn-hepburn-heploc", "ja_Latn__ALALC97", FULL_LENGTH}, {"ja-latn-hepburn-heploc-u-ca-japanese", "ja_Latn__ALALC97@calendar=japanese", FULL_LENGTH}, + {"en-a-bcde-0-fgh", "en@0=fgh;a=bcde", FULL_LENGTH}, }; static void TestForLanguageTag(void) { diff --git a/icu4c/source/test/intltest/loctest.cpp b/icu4c/source/test/intltest/loctest.cpp index 08513917bab..0a0855ca71a 100644 --- a/icu4c/source/test/intltest/loctest.cpp +++ b/icu4c/source/test/intltest/loctest.cpp @@ -2977,12 +2977,14 @@ void LocaleTest::TestForLanguageTag() { static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo"; static const char tag_ill[] = "!"; static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' }; + static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz"; static const Locale loc_en("en_US"); static const Locale loc_oed("en_GB_OXENDICT"); static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo"); static const Locale loc_null(""); static const Locale loc_gb("en_GB"); + static const Locale loc_ext("en_GB@1=abc-efg;a=xyz"); Locale result_en = Locale::forLanguageTag(tag_en, status); status.errIfFailureAndReset("\"%s\"", tag_en); @@ -3015,6 +3017,10 @@ void LocaleTest::TestForLanguageTag() { status.errIfFailureAndReset("\"%.*s\"", sp_no_nul.size(), sp_no_nul.data()); assertEquals(CharString(sp_no_nul, status).data(), loc_gb.getName(), result_no_nul.getName()); + + Locale result_ext = Locale::forLanguageTag(tag_ext, status); + status.errIfFailureAndReset("\"%s\"", tag_ext); + assertEquals(tag_ext, loc_ext.getName(), result_ext.getName()); } void LocaleTest::TestToLanguageTag() { @@ -3023,12 +3029,14 @@ void LocaleTest::TestToLanguageTag() { static const Locale loc_c("C"); static const Locale loc_en("en_US"); static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo"); + static const Locale loc_ext("en@0=abc;a=xyz"); static const Locale loc_empty(""); static const Locale loc_ill("!"); static const char tag_c[] = "en-US-u-va-posix"; static const char tag_en[] = "en-US"; static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo"; + static const char tag_ext[] = "en-0-abc-a-xyz"; static const char tag_und[] = "und"; std::string result; @@ -3049,6 +3057,10 @@ void LocaleTest::TestToLanguageTag() { status.errIfFailureAndReset("\"%s\"", loc_af.getName()); assertEquals(loc_af.getName(), tag_af, result_af.c_str()); + std::string result_ext = loc_ext.toLanguageTag(status); + status.errIfFailureAndReset("\"%s\"", loc_ext.getName()); + assertEquals(loc_ext.getName(), tag_ext, result_ext.c_str()); + std::string result_empty = loc_empty.toLanguageTag(status); status.errIfFailureAndReset("\"%s\"", loc_empty.getName()); assertEquals(loc_empty.getName(), tag_und, result_empty.c_str()); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LanguageTag.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LanguageTag.java index 0b3d532c0e5..2618b0ee7a4 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LanguageTag.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LanguageTag.java @@ -622,7 +622,7 @@ public class LanguageTag { // / %x79-7A ; y - z return (s.length() == 1) - && AsciiUtil.isAlphaString(s) + && AsciiUtil.isAlphaNumericString(s) && !AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s); } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java index 8ffc478c7ba..26c419daa91 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java @@ -4068,6 +4068,8 @@ public class ULocaleTest extends TestFmwk { {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil"}, {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo"}, {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"}, + /* ICU-20320*/ + {"en@9=efg;a=baz", "en-9-efg-a-baz"}, }; for (int i = 0; i < locale_to_langtag.length; i++) { @@ -4093,6 +4095,13 @@ public class ULocaleTest extends TestFmwk { } } + @Test + public void TestDigitSingletonExtensionBug20320() { + ULocale uloc = ULocale.forLanguageTag("en-0-abc-a-xyz"); + assertEquals("getExtension(\'a\')", "xyz", uloc.getExtension('a')); + assertEquals("getExtension(\'0\')", "abc", uloc.getExtension('0')); + } + @Test public void TestForLanguageTag() { final Integer NOERROR = Integer.valueOf(-1);