private internalPluralize()

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`;
  }