diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
index 39b81a49042..176a4372710 100644
--- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java
+++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
@@ -255,16 +255,17 @@ public static List
This method validates the input strictly. * The language code must be lowercase. * The country code must be uppercase. - * The separator must be an underscore or a dash. + * The separator must be an underscore. * The length must be correct. *
* * @param str the locale String to convert, null returns null * @return a Locale, null if null input * @throws IllegalArgumentException if the string is an invalid format - * @see Locale#forLanguageTag(String) + * @see Locale */ public static Locale toLocale(final String str) { + return toLocale(str, false); + } + + /** + * Converts a String to a Locale. + * + *This method takes a string format of a locale or language tag + * if supportDash is true and creates the locale object from it.
+ * + *+ * LocaleUtils.toLocale("", false) = new Locale("", "") + * LocaleUtils.toLocale("", true) = new Locale("", "") + * LocaleUtils.toLocale("en", false) = new Locale("en", "") + * LocaleUtils.toLocale("en", true) = new Locale("en", "") + * LocaleUtils.toLocale("en_GB", false) = new Locale("en", "GB") + * LocaleUtils.toLocale("en_GB", true) = new Locale("en", "GB") + * LocaleUtils.toLocale("en-GB", false) = throws IllegalArgumentException() + * LocaleUtils.toLocale("en-GB", true) = new Locale("en", "GB") + * LocaleUtils.toLocale("en_001", false) = new Locale("en", "001") + * LocaleUtils.toLocale("en_001", true) = new Locale("en", "001") + * LocaleUtils.toLocale("en_GB_xxx", false) = new Locale("en", "GB", "xxx") (#) + * LocaleUtils.toLocale("en_GB_xxx", true) = new Locale("en", "GB", "xxx") (#) + *+ * + *
(#) The behavior of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.
+ * + *This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *
+ * + * @param str the locale String to convert, null returns null + * @param supportDash support strings with '-'. + * @return a Locale, null if null input + * @throws IllegalArgumentException if the string is an invalid format + * @see Locale + */ + protected static Locale toLocale(final String str, final boolean supportDash) { if (str == null) { // TODO Should this return the default locale? return null; @@ -342,7 +384,7 @@ public static Locale toLocale(final String str) { throw new IllegalArgumentException("Invalid locale format: " + str); } final char ch0 = str.charAt(0); - if (ch0 == UNDERSCORE || ch0 == DASH) { + if (ch0 == UNDERSCORE || (supportDash && ch0 == DASH)) { if (len < 3) { throw new IllegalArgumentException("Invalid locale format: " + str); } @@ -363,7 +405,7 @@ public static Locale toLocale(final String str) { return new Locale(StringUtils.EMPTY, str.substring(1, 3), str.substring(4)); } - return parseLocale(str); + return parseLocale(str, supportDash); } /** diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java index dc9e3969d0b..0b82ac62297 100644 --- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java @@ -157,7 +157,7 @@ private static void assertValidToLocale(final String language) { } /** - * Pass in a valid language, test toLocale. + * Pass in a valid locale, test toLocale. * * @param localeString to pass to toLocale() * @param language of the resulting Locale @@ -173,7 +173,23 @@ private static void assertValidToLocale(final String localeString, final String } /** - * Pass in a valid language, test toLocale. + * Pass in a valid language tag, test toLocale. + * + * @param localeString to pass to toLocale() + * @param language of the resulting Locale + * @param country of the resulting Locale + */ + private static void assertValidToLocaleIncludingDash(final String localeString, final String language, final String country) { + final Locale locale = LocaleUtils.toLocale(localeString, true); + assertNotNull(locale, "valid locale"); + assertEquals(language, locale.getLanguage()); + assertEquals(country, locale.getCountry()); + //variant is empty + assertTrue(StringUtils.isEmpty(locale.getVariant())); + } + + /** + * Pass in a valid locale, test toLocale. * * @param localeString to pass to toLocale() * @param language of the resulting Locale @@ -190,6 +206,23 @@ private static void assertValidToLocale( assertEquals(variant, locale.getVariant()); } + /** + * Pass in a valid language tag, test toLocale. + * + * @param localeString to pass to toLocale() + * @param language of the resulting Locale + * @param country of the resulting Locale + * @param variant of the resulting Locale + */ + private static void assertValidToLocaleIncludingDash( + final String localeString, final String language, + final String country, final String variant) { + final Locale locale = LocaleUtils.toLocale(localeString, true); + assertNotNull(locale, "valid locale"); + assertEquals(language, locale.getLanguage()); + assertEquals(country, locale.getCountry()); + assertEquals(variant, locale.getVariant()); + } @BeforeEach public void setUp() { // Testing #LANG-304. Must be called before availableLocaleSet is called. @@ -496,10 +529,14 @@ public void testToLocale_1Part() { @Test public void testToLocale_2Part() { assertValidToLocale("us_EN", "us", "EN"); - assertValidToLocale("us-EN", "us", "EN"); + assertValidToLocaleIncludingDash("us-EN", "us", "EN"); //valid though doesn't exist assertValidToLocale("us_ZH", "us", "ZH"); + assertThrows( + IllegalArgumentException.class, + () -> LocaleUtils.toLocale("us-EN"), + "Should fail dash not supported"); assertThrows( IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_En"), @@ -528,7 +565,7 @@ public void testToLocale_2Part() { @Test public void testToLocale_3Part() { assertValidToLocale("us_EN_A", "us", "EN", "A"); - assertValidToLocale("us-EN-A", "us", "EN", "A"); + assertValidToLocaleIncludingDash("us-EN-A", "us", "EN", "A"); // this isn't pretty, but was caused by a jdk bug it seems // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4210525 if (SystemUtils.isJavaVersionAtLeast(JAVA_1_4)) { @@ -538,6 +575,7 @@ public void testToLocale_3Part() { assertValidToLocale("us_EN_a", "us", "EN", "A"); assertValidToLocale("us_EN_SFsafdFDsdfF", "us", "EN", "SFSAFDFDSDFF"); } + assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("us-EN-A"), "Should fail as dash is not supported"); assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_EN-a"), "Should fail as no consistent delimiter"); assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("uu_UU_"), "Must be 3, 5 or 7+ in length"); // LANG-1741