StringUtils.parseLocaleString detects variant without country

The parseLocale method also turns an empty locale into null now, compatible with parseLocaleString behavior.

Includes tests for parsing all available locales on the JVM, checking toString/toLanguageTag equality between parsed and original locale.

Issue: SPR-7598
Issue: SPR-16651

(cherry picked from commit cab35aa)
This commit is contained in:
Juergen Hoeller 2018-07-18 11:10:26 +02:00
parent ae1d500bc3
commit 55563c16b5
2 changed files with 42 additions and 6 deletions

View File

@ -772,19 +772,23 @@ public abstract class StringUtils {
public static Locale parseLocale(String localeValue) { public static Locale parseLocale(String localeValue) {
String[] tokens = tokenizeLocaleSource(localeValue); String[] tokens = tokenizeLocaleSource(localeValue);
if (tokens.length == 1) { if (tokens.length == 1) {
return Locale.forLanguageTag(localeValue); Locale resolved = Locale.forLanguageTag(localeValue);
return (resolved.getLanguage().length() > 0 ? resolved : null);
} }
return parseLocaleTokens(localeValue, tokens); return parseLocaleTokens(localeValue, tokens);
} }
/** /**
* Parse the given {@code String} representation into a {@link Locale}. * Parse the given {@code String} representation into a {@link Locale}.
* <p>This is the inverse operation of {@link Locale#toString Locale's toString}. * <p>For many parsing scenarios, this is an inverse operation of
* {@link Locale#toString Locale's toString}, in a lenient sense.
* This method does not aim for strict {@code Locale} design compliance;
* it is rather specifically tailored for typical Spring parsing needs.
* <p><b>Note: This delegate does not accept the BCP 47 language tag format.
* Please use {@link #parseLocale} for lenient parsing of both formats.</b>
* @param localeString the locale {@code String}: following {@code Locale's} * @param localeString the locale {@code String}: following {@code Locale's}
* {@code toString()} format ("en", "en_UK", etc), also accepting spaces as * {@code toString()} format ("en", "en_UK", etc), also accepting spaces as
* separators (as an alternative to underscores) * separators (as an alternative to underscores)
* <p>Note: This variant does not accept the BCP 47 language tag format.
* Please use {@link #parseLocale} for lenient parsing of both formats.
* @return a corresponding {@code Locale} instance, or {@code null} if none * @return a corresponding {@code Locale} instance, or {@code null} if none
* @throws IllegalArgumentException in case of an invalid locale specification * @throws IllegalArgumentException in case of an invalid locale specification
*/ */
@ -815,6 +819,12 @@ public abstract class StringUtils {
variant = trimLeadingCharacter(variant, '_'); variant = trimLeadingCharacter(variant, '_');
} }
} }
if ("".equals(variant) && country.startsWith("#")) {
variant = country;
country = "";
}
return (language.length() > 0 ? new Locale(language, country, variant) : null); return (language.length() > 0 ? new Locale(language, country, variant) : null);
} }

View File

@ -734,9 +734,35 @@ public class StringUtilsTests {
assertEquals("Variant containing country code not extracted correctly", variant, locale.getVariant()); assertEquals("Variant containing country code not extracted correctly", variant, locale.getVariant());
} }
@Test // SPR-14718 @Test // SPR-14718, SPR-7598
public void testParseJava7Variant() { public void testParseJava7Variant() {
assertEquals("sr_#LATN", StringUtils.parseLocaleString("sr_#LATN").toString()); assertEquals("sr__#LATN", StringUtils.parseLocaleString("sr__#LATN").toString());
}
@Test // SPR-16651
public void testAvailableLocalesWithLocaleString() {
for (Locale locale : Locale.getAvailableLocales()) {
Locale parsedLocale = StringUtils.parseLocaleString(locale.toString());
if (parsedLocale == null) {
assertEquals("", locale.getLanguage());
}
else {
assertEquals(parsedLocale.toString(), locale.toString());
}
}
}
@Test // SPR-16651
public void testAvailableLocalesWithLanguageTag() {
for (Locale locale : Locale.getAvailableLocales()) {
Locale parsedLocale = StringUtils.parseLocale(locale.toLanguageTag());
if (parsedLocale == null) {
assertEquals("", locale.getLanguage());
}
else {
assertEquals(parsedLocale.toLanguageTag(), locale.toLanguageTag());
}
}
} }
} }