Skip to content

TextInfo.ToTitleCase does not handle U+2019 correctly #133034

Closed

Description

@rjgotten

Description

TextInfo.ToTitleCase does not handle the ’ aka U+2019 RIGHT SINGLE QUOTATION MARK correctly as a non-word separator. It is classified in Unicode's word-break data as MidNumLet which forbids being treated as a word break when flanked by letters or numbers on both sides.

U+2019 is often used as a typographic curly apostrophe (with a long history of fonts and character sets that mapped them to the same code point and generally made this into a mess).

Reproduction Steps

CultureInfo.GetCultureInfo("en").TextInfo.ToTitleCase("Grandma’s pictures")
// ⛔ "Grandma’S Pictures"

Expected behavior

U+2019 should not be treated as a word separator and should not result in the next character being treated as the beginning of a new word.

Actual behavior

U+2019 is being treated as a word separator and results in the next character being treated as the beginning of a new word.

Regression?

No response

Known Workarounds

None.

Configuration

.NET version: v10.0.11

Other information

Note: when flanked by - is strictly speaking load-bearing and non-optional. Unicode doesn't define word break simply via separator characters. It may require such characters to have a particular ante/post context. U+2019 is non-breaking when it is flanked on both sides, ante and post, by a letter or number. And it is breaking in other cases. That's iirc how the MidNumLet-type word-break is classified. TextInfo is using an oversimplification and is wrong. And not just on U+2019 - it's just one of the more directly overt cases.

Activity

  1. added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Sep 1, 2026
  2. dotnet-policy-service commented on Sep 1, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
    See info in area-owners.md if you want to be subscribed.

  3. added and removed
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Sep 1, 2026
  4. dotnet-policy-service commented on Sep 1, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/area-system-globalization
    See info in area-owners.md if you want to be subscribed.

  5. added a commit that references this issue on Sep 1, 2026
    0df7e34
  6. removed
    untriagedNew issue has not been triaged by the area owner
    on Sep 2, 2026
  7. added this to the 12.0.0 milestone on Sep 2, 2026
  8. added a commit that references this issue on Sep 3, 2026
    56c2598
  9. locked and limited conversation to collaborators on Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions