diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs b/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs
index 2fdc9f9885..f789764c4e 100644
--- a/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs
+++ b/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs
@@ -1,21 +1,25 @@
-using System;
-using System.Globalization;
+using System.Globalization;
+using StringToTitleCase;
-namespace StringToTitleCase
-{
- class Program
- {
- static void Main(string[] args)
- {
- var textinfo = new CultureInfo("en-US", false).TextInfo;
+var textinfo = new CultureInfo("en-US", false).TextInfo;
- var textInfo = CultureInfo.CurrentCulture.TextInfo;
+Console.WriteLine(textinfo.ToTitleCase("a tale oF tWo citIes"));
+Console.WriteLine(textinfo.ToTitleCase("harry potter and the Deathly hallows"));
- Console.WriteLine(textinfo.ToTitleCase("a tale oF tWo citIes"));
+Console.WriteLine(textinfo.ToTitleCase("OLIVER TWIST"));
+Console.WriteLine(textinfo.ToTitleCase(textinfo.ToLower("OLIVER TWIST")));
+Console.WriteLine(textinfo.ToTitleCase(textinfo.ToLower("THE NASA MISSION")));
- Console.WriteLine(textinfo.ToTitleCase("harry potter and the Deathly hallows"));
+Console.WriteLine("a tale oF tWo citIes".ToTitleCaseWithMinorWords(textinfo));
+Console.WriteLine("harry potter and the Deathly hallows".ToTitleCaseWithMinorWords(textinfo));
- Console.WriteLine(textinfo.ToTitleCase("OLIVER TWIST".ToLower()));
- }
- }
-}
+Console.OutputEncoding = System.Text.Encoding.UTF8;
+var turkish = new CultureInfo("tr-TR", false).TextInfo;
+Console.WriteLine(turkish.ToTitleCase("a tale oF tWo citIes"));
+Console.WriteLine(turkish.ToTitleCase("istanbul"));
+Console.WriteLine(CultureInfo.InvariantCulture.TextInfo.ToTitleCase("a tale oF tWo citIes"));
+
+Console.WriteLine(textinfo.ToTitleCase("the 2nd edition"));
+Console.WriteLine(textinfo.ToTitleCase("my iPhone"));
+Console.WriteLine(textinfo.ToTitleCase("mcdonald's menu"));
+Console.WriteLine(textinfo.ToTitleCase("x-ray vision"));
diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj b/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj
index 41f1d5ad4b..dfb40caafc 100644
--- a/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj
+++ b/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj
@@ -2,7 +2,9 @@
Exe
- net6.0
+ net10.0
+ enable
+ enable
diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs b/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs
new file mode 100644
index 0000000000..debd77993b
--- /dev/null
+++ b/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs
@@ -0,0 +1,26 @@
+using System.Globalization;
+
+namespace StringToTitleCase;
+
+public static class TitleCaseExtensions
+{
+ private static readonly HashSet MinorWords = new(StringComparer.OrdinalIgnoreCase)
+ {
+ "a", "an", "and", "as", "at", "but", "by", "for", "in", "nor", "of", "on", "or", "the", "to"
+ };
+
+ public static string ToTitleCaseWithMinorWords(this string input, TextInfo textInfo)
+ {
+ var words = textInfo.ToTitleCase(textInfo.ToLower(input)).Split(' ');
+
+ for (var i = 1; i < words.Length - 1; i++)
+ {
+ if (MinorWords.Contains(words[i]))
+ {
+ words[i] = textInfo.ToLower(words[i]);
+ }
+ }
+
+ return string.Join(' ', words);
+ }
+}
diff --git a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs
index 4c20206d1b..3f6c8ce173 100644
--- a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs
+++ b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs
@@ -1,31 +1,84 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Globalization;
+using StringToTitleCase;
-namespace StringToTitleCaseUnitTest
+namespace StringToTitleCaseUnitTest;
+
+[TestClass]
+public class StringToTitleCaseUnitTest
{
- [TestClass]
- public class StringToTitleCaseUnitTest
+ private readonly TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
+
+ [TestMethod]
+ public void GivenToTitleCase_WhenStringIsPassed_ConversionToTitleCaseSuccessful()
{
- private readonly TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
+ Assert.AreEqual("A Tale Of Two Cities", textInfo.ToTitleCase("a tale oF tWo citIes"));
- [TestMethod]
- public void GivenToTitleCase_WhenStringIsPassed_CoversionToTitleCaseSuccessful()
- {
- Assert.AreEqual("A Tale Of Two Cities", textInfo.ToTitleCase("a tale oF tWo citIes"));
+ Assert.AreEqual("Harry Potter And The Deathly Hallows", textInfo.ToTitleCase("harry potter and the Deathly hallows"));
+ }
- Assert.AreEqual("Harry Potter And The Deathly Hallows", textInfo.ToTitleCase("harry potter and the Deathly hallows"));
- }
+ [TestMethod]
+ public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseNotSuccessful()
+ {
+ Assert.AreEqual("OLIVER TWIST", textInfo.ToTitleCase("OLIVER TWIST"));
+ }
- [TestMethod]
- public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseNotSuccessful()
+ [TestMethod]
+ public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseSuccessful()
+ {
+ Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase(textInfo.ToLower("OLIVER TWIST")));
+ }
+
+ [TestMethod]
+ public void GivenToTitleCase_WhenAcronymIsLowercasedFirst_AcronymIsLost()
+ {
+ Assert.AreEqual("The NASA Mission", textInfo.ToTitleCase("the NASA mission"));
+
+ Assert.AreEqual("The Nasa Mission", textInfo.ToTitleCase(textInfo.ToLower("THE NASA MISSION")));
+ }
+
+ [TestMethod]
+ public void GivenCurrentCultureIsTurkish_WhenStringToLowerIsUsed_DotlessIAppears()
+ {
+ var original = CultureInfo.CurrentCulture;
+ try
{
- Assert.AreNotEqual("Oliver Twist", textInfo.ToTitleCase("OLIVER TWIST"));
- }
+ CultureInfo.CurrentCulture = new CultureInfo("tr-TR");
- [TestMethod]
- public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseSuccessful()
+ Assert.AreEqual("Olıver Twıst", textInfo.ToTitleCase("OLIVER TWIST".ToLower()));
+ Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase(textInfo.ToLower("OLIVER TWIST")));
+ }
+ finally
{
- Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase("OLIVER TWIST".ToLower()));
+ CultureInfo.CurrentCulture = original;
}
}
+
+ [TestMethod]
+ public void GivenToTitleCaseWithMinorWords_WhenStringIsPassed_MinorWordsStayLowercase()
+ {
+ Assert.AreEqual("A Tale of Two Cities", "a tale oF tWo citIes".ToTitleCaseWithMinorWords(textInfo));
+
+ Assert.AreEqual("Harry Potter and the Deathly Hallows", "harry potter and the Deathly hallows".ToTitleCaseWithMinorWords(textInfo));
+
+ Assert.AreEqual("The Lord of the Rings", "the lord of the rings".ToTitleCaseWithMinorWords(textInfo));
+ }
+
+ [TestMethod]
+ public void GivenToTitleCase_WhenCultureIsTurkish_ResultUsesTurkishCasing()
+ {
+ var turkish = new CultureInfo("tr-TR", false).TextInfo;
+
+ Assert.AreEqual("A Tale Of Two Citıes", turkish.ToTitleCase("a tale oF tWo citIes"));
+ Assert.AreEqual("İstanbul", turkish.ToTitleCase("istanbul"));
+ Assert.AreEqual("A Tale Of Two Cities", CultureInfo.InvariantCulture.TextInfo.ToTitleCase("a tale oF tWo citIes"));
+ }
+
+ [TestMethod]
+ public void GivenToTitleCase_WhenWordHasDigitsOrInnerCapitals_ResultIsNotWhatAHumanWrites()
+ {
+ Assert.AreEqual("The 2Nd Edition", textInfo.ToTitleCase("the 2nd edition"));
+ Assert.AreEqual("My Iphone", textInfo.ToTitleCase("my iPhone"));
+ Assert.AreEqual("Mcdonald's Menu", textInfo.ToTitleCase("mcdonald's menu"));
+ Assert.AreEqual("X-Ray Vision", textInfo.ToTitleCase("x-ray vision"));
+ }
}
diff --git a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj
index 0ef0e0cb63..4df3b9a29c 100644
--- a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj
+++ b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj
@@ -1,16 +1,21 @@
- net6.0
-
+ net10.0
+ enable
+ enable
false
-
-
-
-
+
+
+
+
+
+
+
+