in packages/libs/codegen/src/pluralization.ts [950:1175]
private internalSingularize(word: string): string {
// words that we know of
if (this.userDictionary.existsInSecond(word)) {
return this.userDictionary.getFirstValue(word);
}
if (this.isNoOpWord(word)) {
return word;
}
const { prefixWord, suffixWord } = this.getSuffixWord(word);
if (this.isNoOpWord(suffixWord)) {
return prefixWord + suffixWord;
}
// handle the word that is the same as the plural form
if (this.isUninflective(suffixWord)) {
return prefixWord + suffixWord;
}
// if word is one of the known singular words, then just return
if (this.knownSingluarWords.includes(suffixWord.toLowerCase())) {
return prefixWord + suffixWord;
}
// handle simple irregular verbs, e.g. was -> were
if (this.irregularVerbPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.irregularVerbPluralizationService.getFirstValue(suffixWord);
}
// handle irregular plurals, e.g. "ox" -> "oxen"
if (this.irregularPluralsPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.irregularPluralsPluralizationService.getFirstValue(suffixWord);
}
// handle singluarization for words ending with sis and pluralized to ses,
// e.g. "ses" -> "sis"
if (this.wordsEndingWithSisPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.wordsEndingWithSisPluralizationService.getFirstValue(suffixWord);
}
// handle words ending with se, e.g. "ses" -> "se"
if (this.wordsEndingWithSePluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.wordsEndingWithSePluralizationService.getFirstValue(suffixWord);
}
// handle words ending with sus, e.g. "suses" -> "sus"
if (this.wordsEndingWithSusPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.wordsEndingWithSusPluralizationService.getFirstValue(suffixWord);
}
let newSuffixWord: string | null;
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["men"],
(s) => `${s.slice(0, -2)}an`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// handle irregular inflections for common suffixes, e.g. "mouse" -> "mice"
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["lice", "mice"],
(s) => `${s.slice(0, -3)}ouse`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["teeth"],
(s) => `${s.slice(0, -4)}ooth`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["geese"],
(s) => `${s.slice(0, -4)}oose`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["feet"],
(s) => `${s.slice(0, -3)}oot`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["zoa"],
(s) => `${s.slice(0, -2)}oon`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// [cs]h and ss that take es as plural form, this is being moved up since the sses will be override by the ses
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["ches", "shes", "sses"], (s) =>
s.slice(0, -2),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// handle assimilated classical inflections, e.g. vertebra -> vertebrae
if (this.assimilatedClassicalInflectionPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.assimilatedClassicalInflectionPluralizationService.getFirstValue(suffixWord);
}
// Handle the classical variants of modern inflections
//
if (this.classicalInflectionPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.classicalInflectionPluralizationService.getFirstValue(suffixWord);
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["trices"],
(s) => `${s.slice(0, -3)}x`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["eaux", "ieux"], (s) =>
s.slice(0, -1),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
if (this.wordsEndingWithInxAnxYnxPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.wordsEndingWithInxAnxYnxPluralizationService.getFirstValue(suffixWord);
}
// f, fe that take ves as plural form
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["alves", "elves", "olves", "eaves", "arves"],
(s) => `${s.slice(0, -3)}f`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["nives", "lives", "wives"],
(s) => `${s.slice(0, -3)}fe`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// y takes ys as plural form if preceded by a vowel, but ies if preceded by a consonant, e.g. stays, skies
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["ays", "eys", "iys", "oys", "uys"],
(s) => s.slice(0, -1),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
//
if (endsWithIgnoreCase(suffixWord, "ies")) {
return prefixWord + suffixWord.slice(0, -3) + "y";
}
// handle some of the words o -> os, and [vowel]o -> os, and the rest are o->oes
if (this.oSuffixPluralizationService.existsInSecond(suffixWord)) {
return prefixWord + this.oSuffixPluralizationService.getFirstValue(suffixWord);
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["aos", "eos", "ios", "oos", "uos"],
(s) => s.slice(0, -1),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
//
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["ces"], (s) => s.slice(0, -1));
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["ces", "ses", "xes"], (s) =>
s.slice(0, -2),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
if (endsWithIgnoreCase(suffixWord, "oes")) {
return prefixWord + suffixWord.slice(0, -2);
}
if (endsWithIgnoreCase(suffixWord, "ss")) {
return prefixWord + suffixWord;
}
if (endsWithIgnoreCase(suffixWord, "s")) {
return prefixWord + suffixWord.slice(0, -1);
}
// word is a singlar
return prefixWord + suffixWord;
}