Skip to content

Commit 55563c1

Browse files
committed
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)
1 parent ae1d500 commit 55563c1

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

spring-core/src/main/java/org/springframework/util/StringUtils.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -772,19 +772,23 @@ public static String uriDecode(String source, Charset charset) {
772772
public static Locale parseLocale(String localeValue) {
773773
String[] tokens = tokenizeLocaleSource(localeValue);
774774
if (tokens.length == 1) {
775-
return Locale.forLanguageTag(localeValue);
775+
Locale resolved = Locale.forLanguageTag(localeValue);
776+
return (resolved.getLanguage().length() > 0 ? resolved : null);
776777
}
777778
return parseLocaleTokens(localeValue, tokens);
778779
}
779780

780781
/**
781782
* Parse the given {@code String} representation into a {@link Locale}.
782-
* <p>This is the inverse operation of {@link Locale#toString Locale's toString}.
783+
* <p>For many parsing scenarios, this is an inverse operation of
784+
* {@link Locale#toString Locale's toString}, in a lenient sense.
785+
* This method does not aim for strict {@code Locale} design compliance;
786+
* it is rather specifically tailored for typical Spring parsing needs.
787+
* <p><b>Note: This delegate does not accept the BCP 47 language tag format.
788+
* Please use {@link #parseLocale} for lenient parsing of both formats.</b>
783789
* @param localeString the locale {@code String}: following {@code Locale's}
784790
* {@code toString()} format ("en", "en_UK", etc), also accepting spaces as
785791
* separators (as an alternative to underscores)
786-
* <p>Note: This variant does not accept the BCP 47 language tag format.
787-
* Please use {@link #parseLocale} for lenient parsing of both formats.
788792
* @return a corresponding {@code Locale} instance, or {@code null} if none
789793
* @throws IllegalArgumentException in case of an invalid locale specification
790794
*/
@@ -815,6 +819,12 @@ private static Locale parseLocaleTokens(String localeString, String[] tokens) {
815819
variant = trimLeadingCharacter(variant, '_');
816820
}
817821
}
822+
823+
if ("".equals(variant) && country.startsWith("#")) {
824+
variant = country;
825+
country = "";
826+
}
827+
818828
return (language.length() > 0 ? new Locale(language, country, variant) : null);
819829
}
820830

spring-core/src/test/java/org/springframework/util/StringUtilsTests.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,35 @@ public void testParseLocaleWithVariantContainingCountryCode() {
734734
assertEquals("Variant containing country code not extracted correctly", variant, locale.getVariant());
735735
}
736736

737-
@Test // SPR-14718
737+
@Test // SPR-14718, SPR-7598
738738
public void testParseJava7Variant() {
739-
assertEquals("sr_#LATN", StringUtils.parseLocaleString("sr_#LATN").toString());
739+
assertEquals("sr__#LATN", StringUtils.parseLocaleString("sr__#LATN").toString());
740+
}
741+
742+
@Test // SPR-16651
743+
public void testAvailableLocalesWithLocaleString() {
744+
for (Locale locale : Locale.getAvailableLocales()) {
745+
Locale parsedLocale = StringUtils.parseLocaleString(locale.toString());
746+
if (parsedLocale == null) {
747+
assertEquals("", locale.getLanguage());
748+
}
749+
else {
750+
assertEquals(parsedLocale.toString(), locale.toString());
751+
}
752+
}
753+
}
754+
755+
@Test // SPR-16651
756+
public void testAvailableLocalesWithLanguageTag() {
757+
for (Locale locale : Locale.getAvailableLocales()) {
758+
Locale parsedLocale = StringUtils.parseLocale(locale.toLanguageTag());
759+
if (parsedLocale == null) {
760+
assertEquals("", locale.getLanguage());
761+
}
762+
else {
763+
assertEquals(parsedLocale.toLanguageTag(), locale.toLanguageTag());
764+
}
765+
}
740766
}
741767

742768
}

0 commit comments

Comments
 (0)