├── sample.txt ├── test.txt ├── style.css ├── README.md ├── index.html └── script.js /sample.txt: -------------------------------------------------------------------------------- 1 | As he enters the room, he announces that his favorite food is hot sauce. When he was younger, he disliked spicy food. Now all that drives him is his desire to acquire more hot sauce. People say that he's a hot sauce maniac. He flies around the world seeking new recipes. He marches to the beat of his own drum. He doesn't care about others' perception of him. SOMETIMES HE LIKES TO WRITE IN ALL CAPS. His wife is sometimes concerned about him. 2 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | He likes cats. He She likes cats. HE SHE he she 2 | Himself Herself. himself herself. She's a banana. He's a potato. 3 | Give her a banana. He'd have liked a potato. 4 | his apple. Her apple 5 | He flies 6 | He boxes 7 | He marches 8 | HE FLIES 9 | She dances 10 | She was at the shop 11 | after he graduates, 12 | he doesn't like pie. 13 | he isn't a banana. 14 | She is a person 15 | She has a pineapple 16 | She does dancing 17 | She goes shopping 18 | Fireman her firewomen girl boy girls girl's fiancée fiance fiancee husbands 19 | wives airmen girls males, male's actress actor ACTOR dress duress brewster 20 | actresses ms Mr. Mister Madams lad's lasses usherette washlet feminine chairman 21 | lady ladies male model femme gentlemen 22 | grace hopper award 23 | grace murray hopper 24 | anita borg 25 | girlfriend 26 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | textarea#input.form-control, textarea#output.form-control, div#output { 2 | height:50%; 3 | width:40%; 4 | float: left; 5 | margin:10px 0; 6 | margin-right:20px; 7 | } 8 | #output { 9 | white-space: pre-wrap; 10 | overflow:auto; 11 | resize: both; 12 | user-select: all; 13 | -moz-user-select: all; 14 | -webkit-user-select: all; 15 | -ms-user-select: all; 16 | } 17 | .highlighttext { 18 | background-color: #ff0; 19 | } 20 | .her { 21 | background-color: #0ff; 22 | } 23 | .changetext { 24 | background-color:#ededed; 25 | } 26 | h1 { 27 | font-size:30px !important; 28 | } 29 | button.btn { 30 | display:block; 31 | clear:both; 32 | } 33 | .footer { 34 | position: absolute; 35 | left: 0; 36 | bottom: 0; 37 | width: 100%; 38 | background-color: #f5f5f5; 39 | padding-top:10px; 40 | } 41 | span.muted { 42 | font-size:14px; 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Live version on GitHub pages!](https://jewang.github.io/gender-neutral-text-converter/) 2 | 3 | # What is Gender Neutral Text Converter? 4 | 5 | This website converts gendered text into gender-neutral text using 6 | singular they. It 7 | runs in client-side Javascript. 8 | 9 | # Why does this exist? 10 | 11 | Screening and interview processes often include a written component. By using gender-neutral language, we can reduce [unconscious gender 12 | bias](https://diversity.ucsf.edu/resources/unconscious-bias) in hiring 13 | processes. Because this kind of content is often sensitive, this script runs 14 | on the user's local machine. No Internet connection is required. Text never touches a server or the cloud. 15 | 16 | I would love to hear other use cases for this script. Feel free to email me. 17 | 18 | # Limitations 19 | 20 | A linguistics library would be necessary to fix most of the below known issues. 21 | 22 | * Cannot distinguish her to their/them: her apple vs. say hello to her. 23 | * Misses some irregular verbs. 24 | * Misses verbs that do not immediately follow subject: She really likes hot sauce. She dances and prances. 25 | * Cannot handle some foreign location names: he'shan 26 | 27 | # Feature requests 28 | 29 | Pull requests are welcome. 30 | 31 | * Find a client-side language processing library to correct limitations 32 | * Correct [gender-specific job 33 | titles](https://en.wikipedia.org/wiki/Gender_marking_in_job_titles): policeman 34 | to police officer, fireman to firefighter 35 | * Hash candidate name 36 | * Support [alternative gender-neutral third-person 37 | pronouns](https://en.wikipedia.org/wiki/Gender-specific_and_gender-neutral_third-person_pronouns#Summary) 38 | 39 | # Thanks 40 | 41 | Thanks to [Jitu D](https://github.com/r2jitu), Peter G, Joseph O, Omari S, [Momo W](https://github.com/maurwang), and [Alex W](http://oldspeak.us/) for brainstorming and feedback. 42 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gender Neutral Text Converter 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 38 |

Makes English text gender-neutral: he/she → they (Sample input)
39 | 40 | Make sure to proofread after converting. Has trouble with some verb conjugations and her/her 42 | → them/their.
Highlights possible gendered terms and changes. 43 |
44 |

45 | 46 |
Gender-neutral output will appear here
48 | 49 |
50 |
51 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | var PRONOUNS = [ 2 | ["she's", "they're"], 3 | ["he's", "they're"], 4 | ['he', 'they'], 5 | ['she', 'they'], 6 | ['him', 'them'], 7 | ['hers', 'theirs'], 8 | ['her', 'them'], 9 | ['herself', 'themselves'], 10 | ['himself', 'themselves'], 11 | ['his', 'their'], 12 | ]; 13 | var IRREGULAR_VERBS = [ 14 | ['was', 'were'], 15 | ['has', 'have'], 16 | ['is', 'are'], 17 | ['does', 'do'], 18 | ['doesn', 'don'], 19 | ['hasn', 'haven'], 20 | ['isn', 'aren'], 21 | ['goes', 'go'], 22 | ]; 23 | var FORMAT_TAG_OPEN = '' 24 | var FORMAT_TAG_CLOSE = "" 25 | 26 | var VERB_ES_SUFFIXES = ['ses', 'zes', 'xes', 'ches', 'shes']; 27 | 28 | function convert(s) { 29 | s = pluralize_verbs(s); 30 | for(i = 0; i < PRONOUNS.length; i++) { 31 | s = pronoun_replace(s, PRONOUNS[i][0], PRONOUNS[i][1]); 32 | } 33 | s = highlight_gendered(s); 34 | return s; 35 | } 36 | 37 | function highlight_gendered(s) { 38 | var regexstr = ''; 39 | // TODO: Make accents work 40 | var others = ['girl[a-z]*', 41 | 'boy[a-z]*', 'female[a-z]*', 'male', 42 | 'fianc(e|é|é)e?', 'husband', 43 | 'wife', 'wive', 'actor', '[a-z]*ess(es)?', '[a-z]*ster', 'ms', 44 | 'mr', 'miss(es)?', 'mister', 'madam', 'maiden', 'lad', 45 | 'lass(es)?', 'latin(o|a)', '[a-z]*ette', 'comedienne', '(lady|ladies)', 'femme', 46 | 'feminine', 'masculine', 'masseuse', 'ghc', 'anita([a-z]| )*borg', 'grace([a-z]| )*hopper', 47 | 'ghc', 'ncwit', 'ada', 'lovelace']; 48 | for (i = 0; i'; 56 | s = s.substring(0, match.index) + replace + s.substring(re.lastIndex, s.length); 57 | re.lastIndex += replace.length - match[0].length; 58 | } 59 | return s; 60 | } 61 | 62 | function pluralize_verbs(s) { 63 | var re = new RegExp('\\bs?he\\b\\s+(.+?)\\b', 'gi'); 64 | var sep = /\b/gi; 65 | while((match = re.exec(s)) != null) { 66 | split = match[0].split(sep); 67 | replace = split[0] + split[1] + pluralize_verb(split[2]); 68 | s = s.replace(match[0], replace); 69 | } 70 | return s; 71 | } 72 | 73 | function pluralize_verb(verb) { 74 | var uppercase = verb === verb.toUpperCase(); 75 | var new_verb = pluralize_lowercase_verb(verb.toLowerCase()); 76 | if (uppercase) { 77 | new_verb = new_verb.toUpperCase(); 78 | } 79 | if (verb != new_verb) { 80 | new_verb = FORMAT_TAG_OPEN + new_verb + FORMAT_TAG_CLOSE; 81 | } 82 | return new_verb; 83 | } 84 | 85 | function pluralize_lowercase_verb(verb) { 86 | for (i = 0; i < IRREGULAR_VERBS.length; i++) { 87 | if (verb == IRREGULAR_VERBS[i][0]) { 88 | return IRREGULAR_VERBS[i][1]; 89 | } 90 | } 91 | if (verb.endsWith('ies')) { 92 | return verb.substring(0, verb.length - 3) + 'y'; 93 | } 94 | for (i = 0; i < VERB_ES_SUFFIXES.length; i++) { 95 | var suffix = VERB_ES_SUFFIXES[i]; 96 | if (verb.endsWith(suffix)) { 97 | return verb.substring(0, verb.length - 2); 98 | } 99 | } 100 | if (verb.endsWith('s')) { 101 | return verb.substring(0, verb.length - 1); 102 | } 103 | return verb; 104 | } 105 | 106 | function pronoun_replace(s, p, r) { 107 | replace_map = [[p, r]]; 108 | replace_map.push([capitalize(p), capitalize(r)]); 109 | replace_map.push([p.toUpperCase(), r.toUpperCase()]); 110 | for (j = 0; j < replace_map.length; j++) { 111 | if (p == 'her') { 112 | replace_map[j][1] = '' + replace_map[j][1] + ''; 113 | } else { 114 | replace_map[j][1] = FORMAT_TAG_OPEN + replace_map[j][1] + FORMAT_TAG_CLOSE; 115 | } 116 | } 117 | 118 | for (j = 0; j < replace_map.length; j++) { 119 | var re = new RegExp('\\b' + replace_map[j][0] + '\\b', 'g'); 120 | s = s.replace(re, replace_map[j][1]); 121 | } 122 | return s 123 | } 124 | 125 | function capitalize(string) { 126 | return string.charAt(0).toUpperCase() + string.slice(1); 127 | } 128 | 129 | $(document).ready(function() { 130 | var button = $('button'); 131 | button.click(function() { 132 | $("#output").html(convert($('#input').val())); 133 | }); 134 | $('#example').click(function() { 135 | jQuery.get('sample.txt', function(data) { 136 | $("#input").val(data); 137 | }); 138 | }); 139 | }); 140 | --------------------------------------------------------------------------------