Skip to content

Fix incorrect singularization for words ending with -ves (arrives/drives/curves/behaves) and add tests#1704

Open
jesi318 wants to merge 2 commits intoHumanizr:mainfrom
jesi318:ve_plural_fix
Open

Fix incorrect singularization for words ending with -ves (arrives/drives/curves/behaves) and add tests#1704
jesi318 wants to merge 2 commits intoHumanizr:mainfrom
jesi318:ve_plural_fix

Conversation

@jesi318
Copy link
Copy Markdown

@jesi318 jesi318 commented Apr 3, 2026

Here is a checklist you should tick through before submitting a pull request:

  • Implementation is clean
  • Code adheres to the existing coding standards; e.g. no curlies for one-line blocks, no redundant empty lines between methods or code blocks, spaces rather than tabs, etc.
  • No Code Analysis warnings
  • There is proper unit test coverage
  • If the code is copied from StackOverflow (or a blog or OSS) full disclosure is included. That includes required license files and/or file headers explaining where the code came from with proper attribution
  • There are very few or no comments (because comments shouldn't be needed if you write clean code)
  • Xml documentation is added/updated for the addition/change
  • Your PR is (re)based on top of the latest commits from the main branch (more info below)
  • Link to the issue(s) you're fixing from your PR description. Use fixes #<the issue number>
  • Readme is updated if you change an existing feature or add a new one
  • Run either build.cmd or build.ps1 and ensure there are no test failures

Summary

Fixes a bug where arrives.Singularize() → arrife (and similar: drives → drife, curves → curf, behaves → behafe etc) by adjusting the singularization rule set and ordering.
Adds unit tests that assert correct singular forms for common -ves cases and true -fe exceptions.

Why this change was made/ Root Cause
_default.AddSingular("([^f])ves$", "$1fe"); is a greedy rule which matched other strings mentioned in the issue above

What I changed

Reworked -ves singular rules in Vocabularies.Defaultso exceptions for nouns that map to -f/-fe (knife→knives, wife→wives, leaf→leaves, etc.) are handled before the general catch-all that converts -ves → -ve (verbs/adjectives like arrive/drive/curve/behave).
Replaced overly-generic pattern(s) that caused verbs to be mis-singularized with a combination of:

  • Explicit stem-based rules for known -f/-fe nouns, and

  • A general (.+)ves$ -> $1ve catch-all for remaining -ves cases.

  • Corrected the incorrect test yield return ["safe", "saves"]; to yield return ["safe", "safes"]; (which makes it grammattically correct according to me) and added a rule for it since it was an edge case . Please let me know if I'm wrong.

  • Added a focused unit test method Singularize_Ves_EdgeCases in InflectorTests.cs

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 864f993ce9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

_default.AddSingular("(hive)s$", "$1");
_default.AddSingular("(tive)s$", "$1");
_default.AddSingular("([lr]|hoo|lea|loa|thie)ves$", "$1f");
_default.AddSingular("(lea|loa|cal|hal|sel|el|shel|wol|thie|dwar|hoo)ves$", "$1f");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve -rves nouns when singularizing

The new allow-list in the -ves -> -f singular rule is now narrower than the existing plural rule, which creates a regression for words ending in -rf/-lf that are not enumerated here. For example, "scarf".Pluralize() still becomes "scarves" via (?:([^f])fe|([lr])f)$, but "scarves".Singularize() now misses this rule and falls through to (.+)ves$ -> $1ve, returning "scarve". This breaks round-tripping for valid inflections and should be fixed by restoring generic coverage (or adding the missing stems) in the singular rules.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant