This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-text.git
The following commit(s) were added to refs/heads/master by this push:
new 63f20134 Use locale-independent lowercasing in case conversion helpers
(#753)
63f20134 is described below
commit 63f201341248001752f534b94354200a2e8c45b2
Author: Javid Khan <[email protected]>
AuthorDate: Sun Jun 14 16:59:10 2026 +0530
Use locale-independent lowercasing in case conversion helpers (#753)
* use locale-independent lowercasing in case conversion helpers
* use junit pioneer @DefaultLocale to manage the default locale in tests
* add locale-independent test for default string lookups parsing
---
src/main/java/org/apache/commons/text/CaseUtils.java | 3 ++-
src/main/java/org/apache/commons/text/WordUtils.java | 3 ++-
.../org/apache/commons/text/lookup/StringLookupFactory.java | 2 +-
src/test/java/org/apache/commons/text/CaseUtilsTest.java | 9 +++++++++
src/test/java/org/apache/commons/text/WordUtilsTest.java | 9 +++++++++
.../apache/commons/text/lookup/StringLookupFactoryTest.java | 11 +++++++++++
6 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/apache/commons/text/CaseUtils.java
b/src/main/java/org/apache/commons/text/CaseUtils.java
index d079fb8b..075903a9 100644
--- a/src/main/java/org/apache/commons/text/CaseUtils.java
+++ b/src/main/java/org/apache/commons/text/CaseUtils.java
@@ -17,6 +17,7 @@
package org.apache.commons.text;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
import org.apache.commons.lang3.ArrayUtils;
@@ -70,7 +71,7 @@ public class CaseUtils {
if (StringUtils.isEmpty(str)) {
return str;
}
- str = str.toLowerCase();
+ str = str.toLowerCase(Locale.ROOT);
final int strLen = str.length();
final int[] newCodePoints = new int[strLen];
int outOffset = 0;
diff --git a/src/main/java/org/apache/commons/text/WordUtils.java
b/src/main/java/org/apache/commons/text/WordUtils.java
index 720ca5f9..f76f0288 100644
--- a/src/main/java/org/apache/commons/text/WordUtils.java
+++ b/src/main/java/org/apache/commons/text/WordUtils.java
@@ -17,6 +17,7 @@
package org.apache.commons.text;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
@@ -250,7 +251,7 @@ public class WordUtils {
if (StringUtils.isEmpty(str)) {
return str;
}
- str = str.toLowerCase();
+ str = str.toLowerCase(Locale.ROOT);
return capitalize(str, delimiters);
}
diff --git
a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
index 699b7dea..a9c7b0ba 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -328,7 +328,7 @@ public final class StringLookupFactory {
try {
for (final String lookupName : str.split("[\\s,]+")) {
if (!lookupName.isEmpty()) {
-
addLookup(DefaultStringLookup.valueOf(lookupName.toUpperCase()), lookupMap);
+
addLookup(DefaultStringLookup.valueOf(lookupName.toUpperCase(Locale.ROOT)),
lookupMap);
}
}
} catch (final IllegalArgumentException exc) {
diff --git a/src/test/java/org/apache/commons/text/CaseUtilsTest.java
b/src/test/java/org/apache/commons/text/CaseUtilsTest.java
index 899e5e8d..f9d7237d 100644
--- a/src/test/java/org/apache/commons/text/CaseUtilsTest.java
+++ b/src/test/java/org/apache/commons/text/CaseUtilsTest.java
@@ -26,6 +26,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.DefaultLocale;
/**
* Tests {@link CaseUtils} class.
@@ -77,4 +78,12 @@ class CaseUtilsTest {
assertEquals("\uD800\uDF00\uD800\uDF01\uD800\uDF02\uD800\uDF03",
CaseUtils.toCamelCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03",
true, '\uD800', '\uDF14'));
}
+
+ @Test
+ @DefaultLocale(language = "tr", country = "TR")
+ void testToCamelCaseLocaleIndependent() {
+ // Turkish lower-cases 'I' (U+0049) to dotless 'i' (U+0131), which
would otherwise leak into the result.
+ assertEquals("TipTop", CaseUtils.toCamelCase("TIP.TOP", true, '.'));
+ assertEquals("toCamelCase", CaseUtils.toCamelCase("TO CAMEL CASE",
false, null));
+ }
}
diff --git a/src/test/java/org/apache/commons/text/WordUtilsTest.java
b/src/test/java/org/apache/commons/text/WordUtilsTest.java
index 429a8934..85b8d1d4 100644
--- a/src/test/java/org/apache/commons/text/WordUtilsTest.java
+++ b/src/test/java/org/apache/commons/text/WordUtilsTest.java
@@ -32,6 +32,7 @@ import java.util.stream.IntStream;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.DefaultLocale;
/**
* Tests {@link WordUtils}.
@@ -124,6 +125,14 @@ class WordUtilsTest {
}
+ @Test
+ @DefaultLocale(language = "tr", country = "TR")
+ void testCapitalizeFully_LocaleIndependent() {
+ // Turkish lower-cases 'I' (U+0049) to dotless 'i' (U+0131), which
would otherwise leak into the result.
+ assertEquals("Heli World", WordUtils.capitalizeFully("HELI WORLD"));
+ assertEquals("I Am Here 123", WordUtils.capitalizeFully("I AM HERE
123"));
+ }
+
@Test
void testCapitalizeFully_Text88() {
assertEquals("I am fine now", WordUtils.capitalizeFully("i am fine
now", new char[] {}));
diff --git
a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
index caeccd82..e0fdf8ab 100644
--- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
+++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
@@ -32,6 +32,7 @@ import java.util.Set;
import javax.xml.XMLConstants;
import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.DefaultLocale;
import org.junitpioneer.jupiter.SetSystemProperty;
/**
@@ -173,6 +174,16 @@ class StringLookupFactoryTest {
checkDefaultStringLookupsHolder(props, "base64",
StringLookupFactory.KEY_BASE64_ENCODER);
}
+ @Test
+ @DefaultLocale(language = "tr", country = "TR")
+ void testDefaultStringLookupsHolder_givenSingleLookup_localeIndependent() {
+ // Turkish upper-cases 'i' (U+0069) to dotted 'İ' (U+0130), so "file"
would fold to "FİLE"
+ // and fail to resolve against the DefaultStringLookup enum without
Locale.ROOT.
+ final Properties props = new Properties();
+ props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY,
"file");
+ checkDefaultStringLookupsHolder(props, StringLookupFactory.KEY_FILE);
+ }
+
@Test
void testDefaultStringLookupsHolder_givenSingleLookup_weirdString() {
final Properties props = new Properties();