Changelog¶
Changelog¶
[Unreleased]¶
[2.2.0] - 2025-07-13¶
Added¶
join()— join words into a natural-language list with configurable conjunction and separatorsordinal()— convert a number to its ordinal string representation (1 → “1st”, 2 → “2nd”, 11 → “11th”)template()— interpolate pluralize/singularize into string templates with count-aware supportpluralio.utilsmodule with full docstrings and type hints90 tests covering all utility functions, including property-based tests with hypothesis
Sphinx documentation page for utility functions
Cookbook recipes for join, ordinal, and template
[2.1.2] - 2025-07-13¶
Fixed¶
restore()now clears thelru_cachevia lazy import of_clear_regex_cache, preventing stale results after registry restoration (critical for test isolation inconftest.py)_match_case()no longer lowercases target when source contains no uppercase letters (e.g. digit-only sources like"123")register_language()removed redundant_clear_regex_cache()call —register()already handles cache clearing
Added¶
Regression tests for all three bug fixes
[2.1.1] - 2025-07-13¶
Fixed¶
Esperanto:
pluralize("librojn")no longer produces"librojjn"— added no-op rules for-jnand-jto prevent double pluralization of already-plural formsregister()now clears thelru_cachevia lazy import of_clear_regex_cache, preventing stale results when language rules are replaced at runtime_match_case()no longer raisesIndexErrorwhen the target string is empty (e.g.add_irregular("Test", ""))
Added¶
Regression tests for all three bug fixes
[2.1.0] - 2025-07-13¶
Added¶
Esperanto (
eo) language support — simplest pluralization system:-jsuffix for plural,-jnfor accusative plural. Zero irregulars, zero exceptions.Esperanto uncountables: pronouns (
mi,vi,li,ŝi,ĝi,ni,ili,oni,si), correlatives (kio,tio,ĉio,nenio,iom), particles (kaj,aŭ,sed,la, etc.)Tests:
test_eo_plurals.py,test_eo_singles.py, round-trip tests
Changed¶
pyproject.tomldescription updated to includeEOKeywords updated with
esperanto
[2.0.2] - 2025-07-13¶
Changed¶
is_plural/is_singularsimplified: removed redundant irregular checks, delegate tosingularize/pluralizeREADME: coverage badge corrected to 97%, Python 3.14 added to feature list
release.ymlbuild Python bumped from 3.12 to 3.14
[2.0.1] - 2025-07-13¶
Fixed¶
mypy CI:
warn_unused_ignoresdisabled fortests.test_property(hypothesis decorators vary across Python versions)tests/__init__.pyadded for proper module resolution
Changed¶
Deduplicated
_pluralize_hyphenated/_singularize_hyphenatedinto shared_transform_hyphenatedCONTRIBUTING.mdupdated with newrules/subpackage structure and all test filessupported_languages()docstring now lists all 5 languagesPython 3.14 added to CI matrix
[2.0.0] - 2025-07-13¶
Breaking¶
Language rule modules moved from
pluralio/rules_en.pytopluralio/rules/en.py(same fores,fr,it,pt). Useimport pluralioas before — the public API is unchanged. If you imported rule modules directly (e.g.from pluralio import rules_en), update tofrom pluralio.rules import en.
Changed¶
pluralio/rules/is now a subpackage with its own__init__.pythat triggers registration of all built-in languages_match_caseoptimized withislower()short-circuit (~5% faster on lowercase inputs)
[1.8.3] - 2025-07-13¶
Fixed¶
_match_casenow guards against empty strings, preventingIndexErroron edge-case inputsis_singularnow usespluralize(x) != xinstead ofsingularize(x) == x, fixing inconsistency withis_plural
Added¶
__all__exports incore.pyandregistry.pyfor explicit public API surfacesnapshot()andrestore()functions inregistry.pyfor test-safe registry isolationmypytype checking now coverstests/directory in CIrufflint rules expanded:B(bugbear),C4(comprehensions),SIM(simplifications),PT(pytest style).hypothesis/added to.gitignore
Changed¶
Extracted
_transform()incore.pyto deduplicatepluralize/singularizelogicconftest.pynow uses publicsnapshot/restoreAPI instead of accessing private_REGISTRYtest_edge_cases.py(2948 lines) split into 6 per-language files:test_cross_edge_cases.py,test_en_edge_cases.py,test_es_edge_cases.py,test_pt_edge_cases.py,test_fr_edge_cases.py,test_it_edge_cases.py__version__fallback reads frompyproject.tomlwhen package metadata is unavailableModule docstring documents side-effect import requirement for language registration
LanguageRulesdocstring improved with.. warning::block about intentional container mutability
[1.8.2] - 2025-07-13¶
Fixed¶
Italian
-tàabstract nouns (verità,felicità,libertà) now invariable via newà$plural ruleItalian
-esenationality words (inglese,francese,giapponese,cinese,portoghese,olandese,svedese,norvegese,finlandese,danese) now round-trip correctly via newesi$ → esesingular ruleItalian round-trip for 27 common
-ewords:piede,fine,margine,bottone,gigante,santone,difensore,attaccante,esemplare,necessario,sufficiente,importante,evidente,intelligente,potente,urgente,simile,facile,difficile,utile,inutile,possibile,impossibile,probabile,improbabile,portatile,turbinesangue,peggio,week-endadded to uncountablesMonths (
gennaio–dicembre), seasons (primavera,estate,autunno,inverno), and numbers (due,tre,cinque,sei,sette,nove,dieci,mille) added to uncountables
Added¶
New plural rule:
à$→ invariable (for abstract nouns ending in-tà)New singular rule:
esi$ → ese(for nationality words)27 new Italian irregular plurals for common
-ewords27 new Italian uncountables (months, seasons, numbers, invariable nouns)
Changed¶
Italian irregulars expanded: 239 (was 212)
Italian uncountables expanded: 144 (was 117)
Italian plural rules: 19 (was 18)
Italian singular rules: 12 (was 11)
[1.8.1] - 2025-07-13¶
Fixed¶
Italian round-trip for
bicchiere,giornale,mare,padre,madre,re(masculine-ewords that singularized to-oinstead of-e)Italian round-trip for
zio→zii(was singularizing tozo)societàadded to uncountables (invariable noun, was being pluralized incorrectly)
Added¶
13 new Italian irregular plurals:
bicchiere,giornale,mare,padre,madre,re,zio,zia,fratello,nonno,nonna,cugino,cugina
Changed¶
Italian irregulars expanded: 212 (was 199)
Italian uncountables expanded: 117 (was 116)
[1.8.0] - 2025-07-13¶
Added¶
54 new Italian irregular plurals: Greek-origin masculine
-a(schema,dogma,emblema,idioma,fantasma), profession nouns in-ista(artista,autista,giornalista,linguista,turista,astronauta), masculine-enouns (fiume,ponte,cliente,residente,presidente,generale,animale,fossile,fucile,cortile), adjectives in-are(volgare,regolare,singolare,particolare), feminine-anouns (borsa,coppia,porta,torta,tazza,sala,ruota,penna,palla,tela,sorella,frusta), body part irregulars (braccio → braccia,lenzuolo → lenzuola,ciglio → ciglia),-ciowords (laccio,straccio,sacrificio,abbraccio),-gopiana (obbligo → obblighi), and feminine-enouns (torre,corte,sorte,morte,canzone)60 new Italian uncountables: tech loanwords (
streaming,download,upload,hashtag,follower,like,share,tweet,link,click,login,logout,reset,backup,input,output,format,record,report,budget), media terms (show,preview,trailer,remake,sequel,break,flop,sketch,spot), sports (tennis,golf,hockey,rugby,match,round,ring,volley,sprint,set), accented invariables (città,virtù,tè,perché,cioè,sé), days of the week (lunedì–domenica), and misc (shock,stop,start,loop,cross,short,staff)
Changed¶
Italian irregulars expanded: 199 (was 145)
Italian uncountables expanded: 116 (was 56)
[1.7.2] - 2025-07-13¶
Fixed¶
Italian masculine
-ewords (cuore,studente,dente,nome,sole,colore,valore,dottore,signore,attore,professore,imperatore,scultore,pittore,scrittore) now round-trip correctlyItalian feminine
-zione/-sionewords (nazione,stazione,lezione,funzione, etc.) now round-trip correctly via-ioni → -ionesingular ruleItalian masculine
-torewords now singularize correctly via-tori → -toreregex ruleItalian feminine
-cia/-giawords after consonant (pioggia → piogge,roccia → rocce,fascia → fasce,ascia → asce) now pluralize correctly via consonant-aware regexItalian feminine
-cia/-giawords after vowel (valigia → valigie,camicia → camicie) now pluralize correctly via vowel-aware regexItalian
-iefeminine words (superficie → superfici,effigie → effigi) now pluralize correctly via-ie → -iregex ruleItalian Greek-origin masculine
-awords (problema → problemi,sistema → sistemi,clima → climi,dramma → drammi,programma → programmi, etc.) now pluralize correctly as irregularsItalian masculine
-iowords (studio → studi,esercizio → esercizi) now round-trip correctly as irregularsItalian feminine
-aplurals (sedie,chiavi,isole,stelle,barche, etc.) now idempotent as irregularsis_singular/is_pluralnow correct for masculine-ewords (cuore,studente, etc.)Removed 19 loanwords from
_IRREGULAR_PLURALS(already in_UNCOUNTABLE, no duplication needed)
Changed¶
Italian regex rules expanded: 18 plural rules (was 15), 11 singular rules (was 8)
Italian irregulars expanded: 145 (was 121)
[1.7.1] - 2025-07-13¶
Fixed¶
Italian feminine
-esingulars (notte,mente,fronte,sede,parte,classe,noce,fede,pace,croce,gente,nave,valle,parete,radice) now round-trip correctlyItalian masculine
-io/-cio/-giowords (bacio,spazio,ufficio,socio,cambio,esempio,principio,stadio,negozio,formaggio,viaggio,raggio,coraggio,passaggio,messaggio) now round-trip correctlyItalian feminine
-aplurals (case,scuole,banane,gatte,paste,piante,famiglie,squadre,feste,donne,ragazze,macchine,piazze,pizze,bambine) now idempotentvocemoved from uncountable to irregular plurals (voce → voci)noiradded to uncountable forfilm-noircompoundRemoved 18 redundant
_EXTRA_SINGLES(all auto-generated from inverse mapping)is_singular/is_pluralnow correct for feminine-ewords
[1.7.0] - 2025-07-13¶
Added¶
Italian (
it) language support with 15 plural rules and 8 singular rules121 irregular plurals covering sdrucciola
-co → -ci(amico → amici), sdrucciola-go → -gi(asparago → asparagi), piana-go → -ghiexplicit mappings (lago → laghi), completely irregular words (uomo → uomini, dio → dei, uovo → uova), foreign loanwords (film, bar, computer), common-e/-iowords for round-trip correctness (cane → cani, vizio → vizi), feminine-esingulars (notte → notti, mente → menti), masculine-io/-cio/-giowords (bacio → baci, formaggio → formaggi, viaggio → viaggi), and feminine-awords for plural idempotency (casa → case, scuola → scuole)56 uncountable/invariable words including foreign loanwords, Greek-origin forms in
-i(analisi, crisi), pluralia tantum (occhiali, forbici), truncated forms (foto, auto), accented-vowel words (caffè), and invariable loanwords (noir)Italian test suite:
test_it_plurals.py,test_it_singles.py, and Italian edge cases intest_edge_cases.py
[1.6.2] - 2025-07-13¶
Added¶
9 pluralia tantum words:
ciseaux,lunettes,jumelles,pincettes,arrérages,ambages,fraîtures,mœurs,condoléances,frais,gens2
-ou → -ouxirregulars:gnou → gnoux,bayou → bayoux4
-al → -alsexceptions:étal → étals,val → vals,gal → gals,recal → recalscour → coursirregular mapping for round-trip correctness7 accentless variant mappings:
generaux → general,hopitaux → hopital,metaux → metal,signaux → signal,regaux → regal,recitaux → recital,voeux → voeuaux → auextra single for compound singularization (pots-aux-feux → pot-au-feu)French hyphenated compound pluralization: all noun segments are now pluralized/singularized (e.g.
café-théâtre → cafés-théâtres,chou-fleur → choux-fleurs,pot-au-feu → pots-aux-feux)
Changed¶
French hyphenated compound handling in
core.py: pluralizes/singularizes all noun segments, skipping function words (de,en,et, etc.) and fixed parts (vie,ciel)Removed
coursfrom uncountable (now handled viacour → coursirregular)Updated supported languages table with accurate rule counts (104 irregulars, 27 extra singles, 81 uncountables)
[1.6.1] - 2025-07-13¶
Fixed¶
bleu,pneu,émeunow pluralize tobleus,pneus,émeusinstead ofbleux,pneux,émeux(were incorrectly caught byeu$ → euxregex; added as irregulars with+s)tuyau,noyau,boyau,sarraunow pluralize totuyaux,noyaux,boyaux,sarrauxinstead oftuyaus,noyaus, etc. (addedau$ → auxregex rule and irregular mappings)tuyaux,noyaux,boyaux,sarrauxnow singularize back totuyau,noyau,boyau,sarrauinstead oftuyal,noyal, etc. (added to_EXTRA_SINGLES)bailnow pluralizes tobauxinstead ofbails(was missing from-ail → -auxirregulars)endroitremoved from uncountable — now correctly pluralizes toendroitsparisremoved from uncountable — now correctly singularizes toparifilsadded to uncountable (pluralia tantum) — no longer singularizes tofilideaux,émaux(accentless variants) now singularize toideal,emailvia_EXTRA_SINGLES
Added¶
au$ → auxpluralization regex rule (betweeneau$andeu$)Accentless variant mappings for
ideaux → idealandemaux → emailTests for all new irregulars and fixed cases
[1.6.0] - 2025-07-13¶
Added¶
French (
fr) language support: 5 regex rules (-al → -aux,-eau → -eaux,-eu → -eux,-s/-x/-z → invariable, default+s), 90 irregular plurals (cheval → chevaux,travail → travaux,bijou → bijoux,œil → yeux,monsieur → messieurs, etc.), 20 extra singles for singularization restoration (travaux → travail,yeux → œil, etc.), 60 uncountable/invariable words (information,temps,riz,croix,nez, etc.)French edge case tests: case preservation (title, all caps), mixed case, hyphenated words, idempotency, round-trip (50+ words), count-aware pluralization, whitespace preservation, single letters, uncountable consistency (70+ words),
is_singular/is_pluralchecks
Changed¶
Updated
pyproject.tomldescription to include French (EN/ES/PT/FR)Added
frenchto keywords inpyproject.tomlUpdated README to reflect French language support
[1.5.5] - 2025-07-12¶
Fixed¶
dinamarquesesnow singularizes todinamarqués(wasdinamarques— missing accent restoration in_EXTRA_SINGLES)fracesnow singularizes tofrac(wasfraz— incorrectly caught byces$→zsingularization rule; addedfrac→fracesto irregular plurals)
Added¶
452 Spanish edge case tests: case preservation (title, all caps), mixed case, hyphenated words (noun+noun, leading/double hyphen), idempotency (45+ already-plural words), round-trip (45+ words), count-aware pluralization, whitespace preservation, single letters, uncountable consistency (70+ words),
is_singular/is_pluralchecks150 English edge case tests: count-aware pluralization (18 words × 3 counts), mixed case, single letters, uncountable consistency (40+ words),
is_singular/is_pluralchecks, hyphenated compound round-trip (13 compounds)
[1.5.4] - 2025-07-12¶
Fixed¶
Portuguese verb+noun hyphenated compounds now pluralize the last segment (noun) instead of the first (verb):
quebra-cabeça→quebra-cabeças(wasquebras-cabeça),guarda-chuva→guarda-chuvas,beija-flor→beija-flores,arranha-céu→arranha-céus,passa-tempo→passa-tempos,guarda-roupa→guarda-roupasAdded 28 Portuguese verb prefixes to
_LAST_SEGMENT_PLURAL_FIRST_WORDS:quebra,guarda,arranha,limpa,mata,saca,abre,corta,lança,trava,cata,chupa,espanta,passa,pisa,salta,adivinha,roí,cai,sobe,desce,para,pára,bota,tira,pega,leva,traz,beija
Changed¶
Moved 3 Portuguese compound words from uncountable to pluralizable:
guarda-chuva,beija-flor,passa-tempo— these are verb+noun compounds that pluralize the noun, not invariable wordsPortuguese uncountable count adjusted from 91 to 88
Added¶
725 Portuguese edge case tests: case preservation (title, all caps, mixed), hyphenated words (noun+noun, verb+noun), idempotency (140+ already-plural words), round-trip (140+ words), NFD normalization,
is_plural/is_singularchecks, count-aware pluralization, whitespace preservation, single letters, uncountable consistency
[1.5.3] - 2025-07-12¶
Added¶
291 additional Portuguese irregular plurals (97 → 388): expanded
-ão→-õesgroup with ~80 common words (criação,emoção,região,questão,lição, etc.), added-ês→-esesgentilicios (freguês,português,japonês,inglês,francês,holandês,dinamarquês,chinês,norueguês,polonês), added monosyllables (som,flor,cor,mar,paz,luz,cruz,rapaz,arroz), added-el→-éis(anel,pincel,painel,pastel,coronel), added-ol→-óis(girassol), added-ãesgroup (catalão,guardião,sotão,caimão,tecelão), and ~130 tech/business loanwords (framework,endpoint,callback,middleware,hash,bucket,pipeline,build,ticket,socket,fixture,mock,diff,commit,driver,buffer,proxy,header,footer,script,backlog,kanban,scrum,review,merge,branch,fork,push,pull,tag,log,bug,hack,patch,release,deploy,rollback,backup,snapshot,dashboard,plugin,addon,snippet,template,theme,skin,layout,form,input,output,flag,switch,toggle,hook,trigger,handler,listener,observer,wrapper,adapter,parser,lexer,compiler,debugger,profiler,linter,runner,worker,master,slave,leader,follower,node,host,peer,client,broker,shard,replica,pod,volume,image,registry,chart,graph,test,suite,case,stub,spy,coverage,report,alert,event,message,webhook,payload,request,response,session,cookie,query,cursor,field,schema,migration,seed,job,task,queue,stack,heap,pool,cache,stream,pipe,port,channel,signal,beacon,sensor,device,badge,card,menu,tab,icon,button,label,filter,sort,block,section,item,element,post,comment,user,account,profile,role,group,team,project,issue,plan,tier,quota,limit,invoice,payment,charge,refund,license,subscription,monitor,scanner,manager,browser,printer,computer,sender,receiver,editor,visitor,sponsor,partner,provider,supplier,investor,founder,developer)56 additional Portuguese extra singles (32 → 88): accent restoration for all new
-ões,-ães,-éis,-óis,-eses,-ãos, and-eisplural forms
Changed¶
Moved 14 tech loanwords from uncountable to irregular plurals (
framework,pipeline,build,socket,commit,proxy,deploy,backup,switch,node,host,cookie,cache,post) — these are pluralizable with+s, not invariablePortuguese uncountable count adjusted from 92 to 91
[1.5.2] - 2025-07-12¶
Changed¶
Optimized
_split_whitespace: fast path for words without surrounding whitespace (common case), skips 3 string operationsSkip
.lower()allocation for already-lowercase strings viaislower()checkInlined
unicodedata.normalizecall to avoid redundant variable assignmentPerformance: ~30% faster across all languages (EN/ES/PT pluralize and singularize)
[1.5.1] - 2025-07-12¶
Added¶
62 additional Portuguese uncountables (30 → 92):
-xinvariables (fax,complex,suplex, etc.), anatomical-ps(bíceps,tríceps,fórceps), Greek/biblical-is(oásis,gênesis),-sinvariables (pires,ourives,cosmos,seis), adverbs (menos,jamais), music genres (blues,soul,funk,reggae,folk,metal), sports (rugby,skate,poker,darts), and tech/foreign loanwords (deploy,commit,cloud,kernel,streaming, etc.)
Changed¶
Test suite: 3,116 → 3,188 tests
100% coverage maintained
[1.5.0] - 2025-07-12¶
Added¶
Portuguese (
pt) pluralization and singularization supportPortuguese regex rules:
-ão→-ões,-m→-ns,-il→-is,-l→-is,-r→-res,-z→-zes,-x→invariable, vowel→+sPortuguese singularization rules:
-ões→-ão,-ães→-ão,-zes→-z,-ns→-m, consonant+-is→-il,-is→-l, double consonant+-es→strips,-tes/-des/-mes/-les→strips,-res→-r, default strips97 Portuguese irregular plurals covering
-ão→-ões/-ães/-ãossplits, accent shifts (-el→-éis,-ol→-óis),-ilparoxítona→-eis, and foreign loanwords32 Portuguese extra singles for accent restoration (
papéis→papel,sóis→sol,méis→mel,fiéis→fiel, etc.)92 Portuguese uncountables including
-xinvariables (tórax,látex,fax,complex), anatomical-ps(bíceps,tríceps,fórceps), Greek/biblical-is(oásis,gênesis),-sinvariables (lápis,vírus,óculos,férias,pires,ourives), pronouns (nós,vós), adverbs (menos,jamais), compound words, music genres (blues,soul,funk,reggae), sports (rugby,skate,poker), and foreign/tech loanwords (software,deploy,commit,cloud,kernel)Portuguese test suite: pluralization, singularization, and round-trip tests
Fixed¶
cantil→cantiis(should becantis): addedil$→isrule beforel$→isleis→lel,reis→rel,pais→pal: added consonant+is→ilrule and extra singles for vowel+iswordsmel→meis(should beméis),fiel→fieis(should befiéis): added to irregularsárvores→árvor(should beárvore): added to extra singleschaves→chav,chefes→chef,peixes→peix: replaced overly aggressive consonant+esrule with specific-res→-rrulegrão→grões(should begrãos),são→sões(should besãos): added to irregularsnós→nó,vós→vó: added to uncountables
Changed¶
Test suite: 2,859 → 3,116 tests
100% coverage maintained across all modules
[1.4.2] - 2025-07-12¶
Changed¶
Optimized
_match_case: single-pass case detection instead of 3 passes, with fast path for all-lowercase wordsSkip
unicodedata.normalizefor ASCII-only strings (most English words)Eliminated redundant
.lower()call in_apply_rules— caller passes pre-computed lowercaseSimplified
_apply_rulessignature (removed unusedirregularsandrule_listparams)Streamlined
_split_whitespaceto avoid redundant string operationsPerformance: ~145K → ~285K ops/sec (~96% faster)
[1.4.1] - 2025-07-12¶
Added¶
19 English uncountable
-icsdisciplines:politics,ethics,gymnastics,linguistics,athletics,civics,statistics,informatics,classics,mechanics,dynamics,genetics,obstetrics,pediatrics,psychiatrics,orthopaedics,academics,logistics,hysterics4 English uncountable games:
billiards,darts,checkers,craps5 Spanish compound uncountables:
quitamanchas,matasanos,guardabosques,guardacostasSpanish invariable adjective
gristo uncountables
Fixed¶
annexround-trip:annexessingularized toannexe(British) instead ofannex(American English)finesseround-trip:finessessingularized tofinessinstead offinessebellyacheround-trip:bellyachessingularized tobellyachinstead ofbellyachepeineround-trip:peinessingularized topeininstead ofpeine(vowel+consonant+e pattern)rolround-trip:rolessingularized torole(English loanword) instead ofrol(Spanish singular)
Changed¶
Test suite: 2,817 → 2,859 tests
Deep validation: 1,141 English words + 466 Spanish words, 0 failures
[1.4.0] - 2025-07-11¶
Added¶
compás→compasesirregular plural (was incorrectly handled by regex)17 Spanish loanwords ending in
-rwith-spluralization:monitor,scanner,manager,browser,printer,computer,editor,visitor,sponsor,partner,provider,supplier,investor,founder,developer,sender,receiver9 Spanish words ending in
-éas explicit irregulars:café,té,bebé,puré,cliché,paté,rosé,bidé,frappé10 Spanish accent restoration mappings in
_EXTRA_SINGLES:caimanes→caimán,guardianes→guardián,sotanes→sotán,comodines→comodín,edenes→edén,limones→limón,melones→melón,dragones→dragón,campeones→campeón20 Spanish uncountables: medical/scientific (
parálisis,tuberculosis,psoriasis,elefantiasis,pediculosis,rabies,mumps), biblical (génesis,apocalipsis), anatomical (biceps,triceps,cuádriceps,forceps), compound words (lavacoches,sacamuelas,cortaplumas,abrelatas,parachoques,rompecorazones,sacaorchos)5 Spanish
-ywords:ley,rey,buey,hoy,convoy4 non-tech loanwords:
sandwich,whisky,ponche,parche
Fixed¶
Idempotency bug:
pluralize(pluralize("café", lang="es"), lang="es")returned"cafeses"instead of"cafés". The regex rule-és$→-eseswas incorrectly matching already-plural forms likecafés,tés,bebés. Fixed by adding these words as explicit irregulars.
Changed¶
Spanish irregular plurals: 61 → 351
Spanish extra singles: 34 → 80
Spanish uncountables: 62 → 87
Test suite: 2,799 → 2,817 tests
Updated comparison table in README to include
pluralsingularas competitorUpdated roadmap to reflect actual release history
[1.3.0] - 2025-07-11¶
Added¶
~130 Latin/Greek classical irregular plurals (Fase 1): -um→-a, -a→-ata, -a→-ae, -en→-ina, -is→-ides, -itis→-itides, -on→-a, -ix/ex→-ices, Hebrew -im, Arabic -i, and other irregulars
~40 English uncountables (Fase 2): herd animals, fish, and other invariable nouns
~300 explicit inverse singularizations (Fase 3): -uses→-use, -eses→-esis, -oes→-oe, -xes→-xe, -zzes→-zz, -ois→-oi
~98 foreign -o words with -os pluralization (Fase 4): musical terms, food, animals, and general loanwords
~130 proper noun irregulars with case preservation (Fase 5): names ending in -ie/-y→-ies
~22 singular -s words with -es pluralization (Fase 6): acropolis, aegis, alias, cosmos, ethos, etc.
~52 suffix-based uncountables (Fase 7): demonyms in -ese, fish names, pox diseases
rhinocerosto_UNCOUNTABLEoctopi,hippopotami,platypito_IRREGULAR_SINGLESfor correct singularization of Latin plural forms
Changed¶
Roadmap Fase 8 (verbs/pronouns) evaluated and explicitly marked as out of scope
[1.2.0] - 2025-07-11¶
Changed¶
pluralize()andsingularize()now preserve leading and trailing whitespace around the input wordEnglish
-chewords handled as explicit irregulars instead of a regex rule, fixing singularization for words likecaches,niches,quichesExpanded compound prefix detection for hyphenated words:
meta,post,re,pre,anti,pro,non,sub,co,ex,inter,intra,multi,semi,pseudo,proto,neo
Added¶
20+ new English
-cheirregulars (ache,cliche,quiche,brioche,pastiche,douche,gouache,cloche,barouche,cartouche,caliche,huarache,seiche,troche,microfiche,attache,synecdoche, etc.)6 compound
-achewords (headache,earache,toothache,backache,heartache,stomachache)13 demonyms ending in
-eseas uncountables (japanese,chinese,vietnamese,burmese,lebanese,portuguese,javanese,sundanese,senegalese,congolese,sudanese,maltese,siamese)ref/ROADMAP-INFLECT.md— roadmap to reach feature parity withinflectin English word coverageComprehensive edge-case tests for whitespace preservation,
-chesingularization, and compound prefixes
[0.1.0] - 2025-07-10¶
Added¶
pluralize()andsingularize()for English and Spanishcountparameter for count-aware pluralizationCase preservation (title case, all caps)
Hyphenated word support (
mother-in-law→mothers-in-law)Extensibility API:
add_irregular,add_plural,add_singular,add_uncountable,add_plural_rule,add_singular_rule,register_languagesupported_languages()to list registered languagesLanguageRulesdataclass for custom language registrationpy.typedmarker for PEP 561CI workflow (lint + type check + test on Python 3.10–3.13)
Release workflow (trusted publishing to PyPI)
95% coverage requirement enforced in CI