| | 1 | | namespace Songhay.Globalization; |
| | 2 | |
|
| | 3 | | /// <summary> |
| | 4 | | /// Helper members for <see cref="System.Globalization.TextInfo" />. |
| | 5 | | /// </summary> |
| | 6 | | public static class TextInfoUtility |
| | 7 | | { |
| | 8 | | /// <summary> |
| | 9 | | /// Wraps <see cref="System.Globalization.TextInfo.ToTitleCase"/> |
| | 10 | | /// to add support for articles, conjunctions and prepositions. |
| | 11 | | /// </summary> |
| | 12 | | /// <param name="input">The input.</param> |
| | 13 | | [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", |
| | 14 | | Justification = "This member is not making a security decision based on the result.")] |
| | 15 | | public static string ToTitleCase(string input) |
| 3 | 16 | | { |
| 3 | 17 | | var culture = Thread.CurrentThread.CurrentCulture; |
| 3 | 18 | | var textInfo = culture.TextInfo; |
| 3 | 19 | | input = textInfo.ToTitleCase(input); |
| | 20 | |
|
| 3 | 21 | | var firstWord = input.Split(' ').First(); |
| 3 | 22 | | var wordsAfterFirstWord = string.Join(" ", |
| 3 | 23 | | input.Split(' ').Skip(1).ToArray()); |
| | 24 | |
|
| 3 | 25 | | EnglishWordsNotCapitalized |
| 450 | 26 | | .Where(word => word.Contains(' ')) |
| 3 | 27 | | .ForEachInEnumerable(word => |
| 108 | 28 | | { |
| 108 | 29 | | wordsAfterFirstWord = wordsAfterFirstWord |
| 108 | 30 | | .Replace(textInfo.ToTitleCase(word), word); |
| 111 | 31 | | }); |
| | 32 | |
|
| 3 | 33 | | input = $"{firstWord} {wordsAfterFirstWord}"; |
| | 34 | |
|
| 3 | 35 | | var words = input.Split(' ') |
| 3 | 36 | | .Skip(1) |
| 16 | 37 | | .Select(word => EnglishWordsNotCapitalized |
| 16 | 38 | | .Contains(word.ToLowerInvariant()) |
| 16 | 39 | | ? word.ToLowerInvariant() |
| 16 | 40 | | : word); |
| 3 | 41 | | input = $"{firstWord} {string.Join(" ", words.ToArray())}"; |
| | 42 | |
|
| 3 | 43 | | return input; |
| 3 | 44 | | } |
| | 45 | |
|
| | 46 | | /// <summary> |
| | 47 | | /// “A virtually complete list of English words that are are NOT capitalized in titles.” |
| | 48 | | /// [http://www.cumbrowski.com/CarstenC/articles/20070623_Title_Capitalization_in_the_English_Language.asp] |
| | 49 | | /// </summary> |
| | 50 | | public static ReadOnlyCollection<string> EnglishWordsNotCapitalized => |
| 16 | 51 | | new ReadOnlyCollection<string>(new List<string> |
| 16 | 52 | | { |
| 16 | 53 | | //Articles: |
| 16 | 54 | | "a", "an", "the", |
| 16 | 55 | |
|
| 16 | 56 | | //Conjunctions |
| 16 | 57 | | "and", "but", "or", "so", "after", |
| 16 | 58 | | "before", "when", "while", "since", |
| 16 | 59 | | "until", "although", "even if", |
| 16 | 60 | | "because", "both", "not only", "but also", |
| 16 | 61 | |
|
| 16 | 62 | | //Prepositions |
| 16 | 63 | | "aboard", "about", "above", "absent", "across", |
| 16 | 64 | | "after", "against", "along", "alongside", "amid", |
| 16 | 65 | | "amidst", "among", "amongst", "around", "as", "aslant", |
| 16 | 66 | | "astride", "at", "atop", "barring", "before", "behind", |
| 16 | 67 | | "below", "beneath", "beside", "besides", "between", |
| 16 | 68 | | "beyond", "but", "by", "despite", "down", "during", "except", |
| 16 | 69 | | "failing", "following", "for", "from", "in", "inside", "into", |
| 16 | 70 | | "like", "merry", "mid", "minus", "near", "next", "notwithstanding", |
| 16 | 71 | | "of", "off", "on", "onto", "opposite", "outside", "over", "past", "plus", |
| 16 | 72 | | "regarding", "round", "save", "since", "than", "through", "throughout", |
| 16 | 73 | | "till", "times", "to", "toward", "towards", "under", "underneath", "unlike", |
| 16 | 74 | | "until", "up", "upon", "via", "with", "within", "without", |
| 16 | 75 | |
|
| 16 | 76 | | //Prepositions; Two words: |
| 16 | 77 | | "according to", "ahead of", "as to", "aside from", |
| 16 | 78 | | "because of", "close to", "due to", "far from", "in to", |
| 16 | 79 | | "inside of", "instead of", "near to", "next to", "on to", "out of", |
| 16 | 80 | | "outside of", "owing to", "prior to", "subsequent to", |
| 16 | 81 | |
|
| 16 | 82 | | //Prepositions; Three words: |
| 16 | 83 | | "as far as", "as well as", "by means of", "in accordance with", |
| 16 | 84 | | "in addition to", "in front of", "in place of", "in spite of", |
| 16 | 85 | | "on account of", "on behalf of", "on top of", "with regard to", "in case of", |
| 16 | 86 | |
|
| 16 | 87 | | //Prepositions; Archaic or infrequently used: |
| 16 | 88 | | "anti", "betwixt", "circa", "cum", "in lieu of", |
| 16 | 89 | | "per", "qua", "sans", "unto", "versus", "vis-a-vis", |
| 16 | 90 | |
|
| 16 | 91 | | //Prepositions; Postpositions: |
| 16 | 92 | | "ago", "apart", "aside", "away", "hence", |
| 16 | 93 | | "notwithstanding", "on", "through", "withal" |
| 16 | 94 | | }); |
| | 95 | | } |