Skip to content

Commit 00c71e3

Browse files
committed
HHH-14032 Parse Locales with scripts properly in LocaleTypeDescriptor.fromString
Locales with scripts (e.g. zh-Hant-HK) were not parsed properly by LocaleTypeDescriptor, causing the script part to get lost.
1 parent 084f713 commit 00c71e3

File tree

2 files changed

+35
-41
lines changed

2 files changed

+35
-41
lines changed

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java

+22-32
Original file line numberDiff line numberDiff line change
@@ -51,43 +51,33 @@ public Locale fromString(String string) {
5151
return Locale.ROOT;
5252
}
5353

54-
boolean separatorFound = false;
55-
int position = 0;
56-
char[] chars = string.toCharArray();
57-
58-
for ( int i = 0; i < chars.length; i++ ) {
59-
// We just look for separators
60-
if ( chars[i] == '_' ) {
61-
if ( !separatorFound ) {
62-
// On the first separator we know that we have at least a language
63-
string = new String( chars, position, i - position );
64-
position = i + 1;
65-
}
66-
else {
67-
// On the second separator we have to check whether there are more chars available for variant
68-
if ( chars.length > i + 1 ) {
69-
// There is a variant so add it to the constructor
70-
return new Locale( string, new String( chars, position, i - position ), new String( chars,
71-
i + 1, chars.length - i - 1 ) );
54+
Locale.Builder builder = new Locale.Builder();
55+
String[] parts = string.split("_");
56+
57+
for (int i = 0; i < parts.length; i++) {
58+
String s = parts[i];
59+
switch (i) {
60+
case 0:
61+
builder.setLanguage(s);
62+
break;
63+
case 1:
64+
builder.setRegion(s);
65+
break;
66+
case 2:
67+
if (i < parts.length - 1 || !s.startsWith("#")) {
68+
builder.setVariant(s);
69+
break;
7270
}
73-
else {
74-
// No variant given, we just have language and country
75-
return new Locale( string, new String( chars, position, i - position ), "" );
71+
case 3:
72+
if (s.startsWith("#")) {
73+
s = s.substring(1);
7674
}
77-
}
78-
79-
separatorFound = true;
75+
builder.setScript(s);
76+
break;
8077
}
8178
}
8279

83-
if ( !separatorFound ) {
84-
// No separator found, there is only a language
85-
return new Locale( string );
86-
}
87-
else {
88-
// Only one separator found, there is a language and a country
89-
return new Locale( string, new String( chars, position, chars.length - position ) );
90-
}
80+
return builder.build();
9181
}
9282

9383
@SuppressWarnings({ "unchecked" })

hibernate-core/src/test/java/org/hibernate/test/type/descriptor/java/LocaleTypeDescriptorTest.java

+13-9
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,19 @@ public class LocaleTypeDescriptorTest extends BaseUnitTestCase {
2525

2626
@Test
2727
public void testConversionFromString() {
28-
assertEquals( toLocale( "de", null, null ), LocaleTypeDescriptor.INSTANCE.fromString( "de" ) );
29-
assertEquals( toLocale( "de", "DE", null ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE" ) );
30-
assertEquals( toLocale( null, "DE", null ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE" ) );
31-
assertEquals( toLocale( null, null, "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "__ch123" ) );
32-
assertEquals( toLocale( null, "DE", "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE_ch123" ) );
33-
assertEquals( toLocale( "de", null, "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "de__ch123" ) );
34-
assertEquals( toLocale( "de", "DE", "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE_ch123" ) );
35-
assertEquals( toLocale( "", "", "" ), LocaleTypeDescriptor.INSTANCE.fromString( "" ) );
28+
assertEquals( toLocale( "de", null, null, null ), LocaleTypeDescriptor.INSTANCE.fromString( "de" ) );
29+
assertEquals( toLocale( "de", "DE", null, null ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE" ) );
30+
assertEquals( toLocale( null, "DE", null, null ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE" ) );
31+
assertEquals( toLocale( null, null, "ch123", null ), LocaleTypeDescriptor.INSTANCE.fromString( "__ch123" ) );
32+
assertEquals( toLocale( null, "DE", "ch123", null ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE_ch123" ) );
33+
assertEquals( toLocale( "de", null, "ch123", null ), LocaleTypeDescriptor.INSTANCE.fromString( "de__ch123" ) );
34+
assertEquals( toLocale( "de", "DE", "ch123", null ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE_ch123" ) );
35+
assertEquals( toLocale( "zh", "HK", null, "Hant"), LocaleTypeDescriptor.INSTANCE.fromString( "zh_HK_#Hant" ) );
36+
assertEquals( toLocale( "", "", "", null ), LocaleTypeDescriptor.INSTANCE.fromString( "" ) );
3637
assertEquals( Locale.ROOT, LocaleTypeDescriptor.INSTANCE.fromString( "" ) );
3738
}
3839

39-
public Locale toLocale(String lang, String region, String variant) {
40+
public Locale toLocale(String lang, String region, String variant, String script) {
4041
final Locale.Builder builder = new Locale.Builder();
4142
if ( StringHelper.isNotEmpty( lang ) ) {
4243
builder.setLanguage( lang );
@@ -47,6 +48,9 @@ public Locale toLocale(String lang, String region, String variant) {
4748
if ( StringHelper.isNotEmpty( variant ) ) {
4849
builder.setVariant( variant );
4950
}
51+
if ( StringHelper.isNotEmpty( script ) ) {
52+
builder.setScript( script );
53+
}
5054
return builder.build();
5155
}
5256
}

0 commit comments

Comments
 (0)