Skip to content

Use locale-independent lowercasing in case conversion helpers#753

Open
dxbjavid wants to merge 3 commits into
apache:masterfrom
dxbjavid:locale-independent-case-conversion
Open

Use locale-independent lowercasing in case conversion helpers#753
dxbjavid wants to merge 3 commits into
apache:masterfrom
dxbjavid:locale-independent-case-conversion

Conversation

@dxbjavid

Copy link
Copy Markdown
Contributor

CaseUtils.toCamelCase and WordUtils.capitalizeFully fold their input to lower case with the no-arg String.toLowerCase(), so the output depends on the JVM default locale; under a Turkish locale an ASCII 'I' becomes the dotless 'ı' (U+0131), so capitalizeFully("HELI WORLD") comes back as "Helı World" rather than "Heli World" and toCamelCase("TIP.TOP", true, '.') yields "TıpTop". StringLookupFactory has the same issue when it upper-cases the default-lookups system property to match the enum names, which can stop a valid value like "file" from resolving on a Turkish JVM. I have switched all three sites to Locale.ROOT, matching the Locale.ROOT already used in StringLookupFactory.toKey, and added tests that pin the behaviour under a Turkish default locale.

  • Read the contribution guidelines for this project.
  • Read the ASF Generative Tooling Guidance if you use Artificial Intelligence (AI).
  • I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute?
  • Run a successful build using the default Maven goal with mvn; that's mvn on the command line by itself.
  • Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process.

@garydgregory garydgregory left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dxbjavid
You'll want to use JUnit Pioneer's annotations to manage the default Locale.

@dxbjavid

Copy link
Copy Markdown
Contributor Author

good point, done. switched both tests over to @DefaultLocale(language = "tr", country = "TR") and dropped the manual setDefault/finally dance, so pioneer handles save and restore now. tests still pass.

@garydgregory garydgregory changed the title use locale-independent lowercasing in case conversion helpers Use locale-independent lowercasing in case conversion helpers Jun 13, 2026

@garydgregory garydgregory left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comment.

for (final String lookupName : str.split("[\\s,]+")) {
if (!lookupName.isEmpty()) {
addLookup(DefaultStringLookup.valueOf(lookupName.toUpperCase()), lookupMap);
addLookup(DefaultStringLookup.valueOf(lookupName.toUpperCase(Locale.ROOT)), lookupMap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @dxbjavid
This change is untested, either remove it or create a test for it.
TY

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a test for it. testDefaultStringLookupsHolder_givenSingleLookup_localeIndependent feeds a lowercase "file" through the holder under a tr-TR default locale; without Locale.ROOT the upper-case folds the i to dotted İ and valueOf throws, so the test fails on the unpatched code and passes with the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants