Those are all general rules (and good ones) but English is not a language for the faint of heart :-).
My own preference would be to have a transformation engine along with a set of transformations (surprisingly enough) for doing the actual work.
You would run through the transformations (from specific to general) and, when a match was found, apply the transformation to the word.
Regular expressions would be an ideal approach to this due to their expressiveness. An example rule set:
1. If the word is fish, return fish.
2. If the word is sheep, return sheep.
3. If the word is "radii", return "radius".
4. If the word is "types", return "type".
3. If the word ends in "ii", replace that "ii" with "us" (octopii,virii).
: : : : :
97. If a word ends with -ies, I replace the ending with -y
98. If a word ends with -es, I remove this ending.
99. Otherwise, I just remove the trailing -s.
Note that, when we found the problem with "types" at 98, we created a higher-priority transformation at 4. You'll basically need to keep this transformation table updated as you find all those wondrous exceptions that English has spawned.
The other possibility is to not waste your time with a general rule. Since the names of the tables will be relatively limited, just create another table (or some sort of data structure) called singulars
which maps all the relevant plural table names (employees
) to singular object names (employee
).
Then every time a table is added, add an entry to the singulars "table" so you can singularize it.