Skip to content

Commit a6f7849

Browse files
authored
Fix title-case logic for contractions and possessives (#962)
Python's built-in .title() incorrectly capitalizes letters following an apostrophe. This commit adds a regex post-processor to capitalization levels 2 (Tie) and 3 (Gerrish) to lowercase common English contractions and possessives while preserving proper names like O'Reilly.
1 parent 985ba92 commit a6f7849

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

castervoice/lib/textformat.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
from builtins import str
23

34
from castervoice.lib import settings
@@ -34,8 +35,17 @@ def formatted_text(cls, capitalization, spacing, t):
3435
t = t.upper()
3536
elif capitalization == 2:
3637
t = t.title()
38+
# Python's built-in .title() treats apostrophes as word boundaries,
39+
# incorrectly capitalizing contractions (e.g., "don't" becomes "Don'T").
40+
# This regex lowercases common contractions and possessives, while
41+
# safely preserving proper names like "O'Reilly" or "D'Angelo".
42+
# (?<=[a-zA-Z]) : Ensures a letter precedes the apostrophe.
43+
# '(S|T|M|D|Re|Ve|Ll)\b : Matches the contraction at a word boundary.
44+
t = re.sub(r"(?<=[a-zA-Z])'(S|T|M|D|Re|Ve|Ll)\b", lambda m: m.group(0).lower(), t)
3745
elif capitalization == 3:
38-
t = t[0].lower() + t.title()[1:]
46+
t = t.title()
47+
t = re.sub(r"(?<=[a-zA-Z])'(S|T|M|D|Re|Ve|Ll)\b", lambda m: m.group(0).lower(), t)
48+
t = t[0].lower() + t[1:]
3949
elif capitalization == 4:
4050
t = t.capitalize()
4151
elif capitalization == 5:

0 commit comments

Comments
 (0)