in packages/libs/codegen/src/pluralization.ts [743:933]
private internalPluralize(word: string): string {
// words that we know of
if (this.userDictionary.existsInFirst(word)) {
return this.userDictionary.getSecondValue(word);
}
if (this.isNoOpWord(word)) {
return word;
}
const { prefixWord, suffixWord } = this.getSuffixWord(word);
// by me -> by me
if (this.isNoOpWord(suffixWord)) {
return prefixWord + suffixWord;
}
// handle the word that do not inflect in the plural form
if (this.isUninflective(suffixWord)) {
return prefixWord + suffixWord;
}
// if word is one of the known plural forms, then just return
if (this.knownPluralWords.includes(suffixWord.toLowerCase()) || this.isPlural(suffixWord)) {
return prefixWord + suffixWord;
}
// handle irregular plurals, e.g. "ox" -> "oxen"
if (this.irregularPluralsPluralizationService.existsInFirst(suffixWord)) {
return prefixWord + this.irregularPluralsPluralizationService.getSecondValue(suffixWord);
}
let newSuffixWord: string | null;
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["man"],
(s) => `${s.slice(0, -2)}en`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// handle irregular inflections for common suffixes, e.g. "mouse" -> "mice"
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["louse", "mouse"],
(s) => `${s.slice(0, -4)}ice`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["tooth"],
(s) => `${s.slice(0, -4)}eeth`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["goose"],
(s) => `${s.slice(0, -4)}eese`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["foot"],
(s) => `${s.slice(0, -3)}eet`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["zoon"],
(s) => `${s.slice(0, -3)}oa`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["cis", "sis", "xis"],
(s) => `${s.slice(0, -2)}es`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// handle assimilated classical inflections, e.g. vertebra -> vertebrae
if (this.assimilatedClassicalInflectionPluralizationService.existsInFirst(suffixWord)) {
return prefixWord + this.assimilatedClassicalInflectionPluralizationService.getSecondValue(suffixWord);
}
// Handle the classical variants of modern inflections
//
if (this.classicalInflectionPluralizationService.existsInFirst(suffixWord)) {
return prefixWord + this.classicalInflectionPluralizationService.getSecondValue(suffixWord);
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["trix"],
(s) => `${s.slice(0, -1)}ces`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["eau", "ieu"], (s) => `${s}x`);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
if (this.wordsEndingWithInxAnxYnxPluralizationService.existsInFirst(suffixWord)) {
return prefixWord + this.wordsEndingWithInxAnxYnxPluralizationService.getSecondValue(suffixWord);
}
// [cs]h and ss that take es as plural form
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ["ch", "sh", "ss"], (s) => `${s}es`);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
// f, fe that take ves as plural form
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["alf", "elf", "olf", "eaf", "arf"],
(s) => (endsWithIgnoreCase(s, "deaf") ? s : `${s.slice(0, -1)}ves`),
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["nife", "life", "wife"],
(s) => `${s.slice(0, -2)}ves`,
);
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,
["ay", "ey", "iy", "oy", "uy"],
(s) => `${s}s`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
//
if (endsWithIgnoreCase(suffixWord, "y")) {
return prefixWord + suffixWord.slice(0, -1) + "ies";
}
// handle some of the words o -> os, and [vowel]o -> os, and the rest are o->oes
if (this.oSuffixPluralizationService.existsInFirst(suffixWord)) {
return prefixWord + this.oSuffixPluralizationService.getSecondValue(suffixWord);
}
newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(
suffixWord,
["ao", "eo", "io", "oo", "uo"],
(s) => `${s}s`,
);
if (newSuffixWord !== null) {
return prefixWord + newSuffixWord;
}
if (endsWithIgnoreCase(suffixWord, "o") || endsWithIgnoreCase(suffixWord, "s")) {
return `${prefixWord}${suffixWord}es`;
}
if (endsWithIgnoreCase(suffixWord, "x")) {
return `${prefixWord}${suffixWord}es`;
}
// cats, bags, hats, speakers
return `${prefixWord}${suffixWord}s`;
}