Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partially revert LANG-1172. #1271

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions src/main/java/org/apache/commons/lang3/LocaleUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,17 @@ public static List<Locale> localeLookupList(final Locale locale, final Locale de
* </p>
*
* @param str the String to parse as a Locale.
* @param supportDash support strings with '-'.
* @return a Locale parsed from the given String.
* @throws IllegalArgumentException if the given String can not be parsed.
* @see Locale
*/
private static Locale parseLocale(final String str) {
private static Locale parseLocale(final String str, final boolean supportDash) {
if (isISO639LanguageCode(str)) {
return new Locale(str);
}
final int limit = 3;
final char separator = str.indexOf(UNDERSCORE) != -1 ? UNDERSCORE : DASH;
final char separator = (!supportDash || str.indexOf(UNDERSCORE) != -1) ? UNDERSCORE : DASH;
final String[] segments = str.split(String.valueOf(separator), 3);
final String language = segments[0];
if (segments.length == 2) {
Expand Down Expand Up @@ -305,7 +306,6 @@ public static Locale toLocale(final Locale locale) {
* LocaleUtils.toLocale("") = new Locale("", "")
* LocaleUtils.toLocale("en") = new Locale("en", "")
* LocaleUtils.toLocale("en_GB") = new Locale("en", "GB")
* LocaleUtils.toLocale("en-GB") = new Locale("en", "GB")
* LocaleUtils.toLocale("en_001") = new Locale("en", "001")
* LocaleUtils.toLocale("en_GB_xxx") = new Locale("en", "GB", "xxx") (#)
* </pre>
Expand All @@ -317,16 +317,58 @@ public static Locale toLocale(final Locale locale) {
* <p>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.
* </p>
*
* @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.
*
* <p>This method takes a string format of a locale or language tag
* if supportDash is true and creates the locale object from it.</p>
*
* <pre>
* 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") (#)
* </pre>
*
* <p>(#) 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.</p>
*
* <p>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.
* </p>
*
* @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;
Expand All @@ -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);
}
Expand All @@ -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);
}

/**
Expand Down
46 changes: 42 additions & 4 deletions src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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)) {
Expand All @@ -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
Expand Down