|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace Doctrine\Inflector\Rules\Italian; |
| 6 | + |
| 7 | +use Doctrine\Inflector\Rules\Pattern; |
| 8 | +use Doctrine\Inflector\Rules\Substitution; |
| 9 | +use Doctrine\Inflector\Rules\Transformation; |
| 10 | +use Doctrine\Inflector\Rules\Word; |
| 11 | + |
| 12 | +class Inflectible |
| 13 | +{ |
| 14 | + /** @return iterable<Transformation> */ |
| 15 | + public static function getSingular(): iterable |
| 16 | + { |
| 17 | + // Reverse of -sce → -scia (fasce → fascia) |
| 18 | + yield new Transformation(new Pattern('([aeiou])sce$'), '\\1scia'); |
| 19 | + |
| 20 | + // Reverse of -cie → -cia (farmacia → farmacie) |
| 21 | + yield new Transformation(new Pattern('cie$'), 'cia'); |
| 22 | + |
| 23 | + // Reverse of -gie → -gia (bugia → bugie) |
| 24 | + yield new Transformation(new Pattern('gie$'), 'gia'); |
| 25 | + |
| 26 | + // Reverse of -ce → -cia (arance → arancia) |
| 27 | + yield new Transformation(new Pattern('([^aeiou])ce$'), '\1cia'); |
| 28 | + |
| 29 | + // Reverse of -ge → -gia (valige → valigia) |
| 30 | + yield new Transformation(new Pattern('([^aeiou])ge$'), '\1gia'); |
| 31 | + |
| 32 | + // Reverse of -chi → -co (bachi → baco) |
| 33 | + yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])chi$'), '\1co'); |
| 34 | + |
| 35 | + // Reverse of -ghi → -go (laghi → lago) |
| 36 | + yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])ghi$'), '\1go'); |
| 37 | + |
| 38 | + // Reverse of -ci → -co (medici → medico) |
| 39 | + yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])ci$'), '\1co'); |
| 40 | + |
| 41 | + // Reverse of -gi → -go (psicologi → psicologo) |
| 42 | + yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])gi$'), '\1go'); |
| 43 | + |
| 44 | + // Reverse of -i → -io (zii → zio, negozi → negozio) |
| 45 | + // This is more complex due to Italian's stress patterns, but we'll handle the basic case |
| 46 | + yield new Transformation(new Pattern('([^aeiou])i$'), '\1io'); |
| 47 | + |
| 48 | + // Handle words that end with -i but should go to -co/-go (amici → amico, not amice) |
| 49 | + yield new Transformation(new Pattern('([^aeiou])ci$'), '\1co'); |
| 50 | + yield new Transformation(new Pattern('([^aeiou])gi$'), '\1go'); |
| 51 | + |
| 52 | + // Reverse of -a → -e |
| 53 | + yield new Transformation(new Pattern('e$'), 'a'); |
| 54 | + |
| 55 | + // Reverse of -e → -i |
| 56 | + yield new Transformation(new Pattern('i$'), 'e'); |
| 57 | + |
| 58 | + // Reverse of -o → -i |
| 59 | + yield new Transformation(new Pattern('i$'), 'o'); |
| 60 | + } |
| 61 | + |
| 62 | + /** @return iterable<Transformation> */ |
| 63 | + public static function getPlural(): iterable |
| 64 | + { |
| 65 | + // Words ending in -scia without stress on 'i' become -sce (e.g. fascia → fasce) |
| 66 | + yield new Transformation(new Pattern('([aeiou])scia$'), '\\1sce'); |
| 67 | + |
| 68 | + // Words ending in -cia/gia with stress on 'i' keep the 'i' in plural |
| 69 | + yield new Transformation(new Pattern('cia$'), 'cie'); // e.g. farmacia → farmacie |
| 70 | + yield new Transformation(new Pattern('gia$'), 'gie'); // e.g. bugia → bugie |
| 71 | + |
| 72 | + // Words ending in -cia/gia without stress on 'i' lose the 'i' in plural |
| 73 | + yield new Transformation(new Pattern('([^aeiou])cia$'), '\\1ce'); // e.g. arancia → arance |
| 74 | + yield new Transformation(new Pattern('([^aeiou])gia$'), '\\1ge'); // e.g. valigia → valige |
| 75 | + |
| 76 | + // Words ending in -co/-go with stress on 'o' become -chi/-ghi |
| 77 | + yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])co$'), '\\1chi'); // e.g. baco → bachi |
| 78 | + yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])go$'), '\\1ghi'); // e.g. lago → laghi |
| 79 | + |
| 80 | + // Words ending in -co/-go with stress on the penultimate syllable become -ci/-gi |
| 81 | + yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])co$'), '\\1ci'); // e.g. medico → medici |
| 82 | + yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])go$'), '\\1gi'); // e.g. psicologo → psicologi |
| 83 | + |
| 84 | + // Words ending in -io with stress on 'i' keep the 'i' in plural |
| 85 | + yield new Transformation(new Pattern('([^aeiou])io$'), '\\1i'); // e.g. zio → zii |
| 86 | + |
| 87 | + // Words ending in -io with stress on 'o' lose the 'i' in plural |
| 88 | + yield new Transformation(new Pattern('([aeiou])io$'), '\\1i'); // e.g. negozio → negozi |
| 89 | + |
| 90 | + // Standard ending rules |
| 91 | + yield new Transformation(new Pattern('a$'), 'e'); // -a → -e |
| 92 | + yield new Transformation(new Pattern('e$'), 'i'); // -e → -i |
| 93 | + yield new Transformation(new Pattern('o$'), 'i'); // -o → -i |
| 94 | + } |
| 95 | + |
| 96 | + /** @return iterable<Substitution> */ |
| 97 | + public static function getIrregular(): iterable |
| 98 | + { |
| 99 | + // Irregular substitutions (singular => plural) |
| 100 | + $irregulars = [ |
| 101 | + 'ala' => 'ali', |
| 102 | + 'albergo' => 'alberghi', |
| 103 | + 'amica' => 'amiche', |
| 104 | + 'amico' => 'amici', |
| 105 | + 'ampio' => 'ampi', |
| 106 | + 'arancia' => 'arance', |
| 107 | + 'arma' => 'armi', |
| 108 | + 'asparago' => 'asparagi', |
| 109 | + 'banca' => 'banche', |
| 110 | + 'belga' => 'belgi', |
| 111 | + 'braccio' => 'braccia', |
| 112 | + 'budello' => 'budella', |
| 113 | + 'bue' => 'buoi', |
| 114 | + 'caccia' => 'cacce', |
| 115 | + 'calcagno' => 'calcagna', |
| 116 | + 'camicia' => 'camicie', |
| 117 | + 'cane' => 'cani', |
| 118 | + 'capitale' => 'capitali', |
| 119 | + 'carcere' => 'carceri', |
| 120 | + 'casa' => 'case', |
| 121 | + 'cavaliere' => 'cavalieri', |
| 122 | + 'centinaio' => 'centinaia', |
| 123 | + 'cerchio' => 'cerchia', |
| 124 | + 'cervello' => 'cervella', |
| 125 | + 'chiave' => 'chiavi', |
| 126 | + 'chirurgo' => 'chirurgi', |
| 127 | + 'ciglio' => 'ciglia', |
| 128 | + 'città' => 'città', |
| 129 | + 'corno' => 'corna', |
| 130 | + 'corpo' => 'corpi', |
| 131 | + 'crisi' => 'crisi', |
| 132 | + 'dente' => 'denti', |
| 133 | + 'dio' => 'dei', |
| 134 | + 'dito' => 'dita', |
| 135 | + 'dottore' => 'dottori', |
| 136 | + 'fiore' => 'fiori', |
| 137 | + 'fratello' => 'fratelli', |
| 138 | + 'fuoco' => 'fuochi', |
| 139 | + 'gamba' => 'gambe', |
| 140 | + 'ginocchio' => 'ginocchia', |
| 141 | + 'gioco' => 'giochi', |
| 142 | + 'giornale' => 'giornali', |
| 143 | + 'giraffa' => 'giraffe', |
| 144 | + 'labbro' => 'labbra', |
| 145 | + 'lenzuolo' => 'lenzuola', |
| 146 | + 'libro' => 'libri', |
| 147 | + 'madre' => 'madri', |
| 148 | + 'maestro' => 'maestri', |
| 149 | + 'magico' => 'magici', |
| 150 | + 'mago' => 'maghi', |
| 151 | + 'maniaco' => 'maniaci', |
| 152 | + 'manico' => 'manici', |
| 153 | + 'mano' => 'mani', |
| 154 | + 'medico' => 'medici', |
| 155 | + 'membro' => 'membri', |
| 156 | + 'metropoli' => 'metropoli', |
| 157 | + 'migliaio' => 'migliaia', |
| 158 | + 'miglio' => 'miglia', |
| 159 | + 'mille' => 'mila', |
| 160 | + 'mio' => 'miei', |
| 161 | + 'moglie' => 'mogli', |
| 162 | + 'mosaico' => 'mosaici', |
| 163 | + 'muro' => 'muri', |
| 164 | + 'nemico' => 'nemici', |
| 165 | + 'nome' => 'nomi', |
| 166 | + 'occhio' => 'occhi', |
| 167 | + 'orecchio' => 'orecchi', |
| 168 | + 'osso' => 'ossa', |
| 169 | + 'paio' => 'paia', |
| 170 | + 'pane' => 'pani', |
| 171 | + 'papa' => 'papi', |
| 172 | + 'pasta' => 'paste', |
| 173 | + 'penna' => 'penne', |
| 174 | + 'pesce' => 'pesci', |
| 175 | + 'piede' => 'piedi', |
| 176 | + 'pittore' => 'pittori', |
| 177 | + 'poeta' => 'poeti', |
| 178 | + 'porco' => 'porci', |
| 179 | + 'porto' => 'porti', |
| 180 | + 'problema' => 'problemi', |
| 181 | + 'ragazzo' => 'ragazzi', |
| 182 | + 're' => 're', |
| 183 | + 'rene' => 'reni', |
| 184 | + 'riso' => 'risa', |
| 185 | + 'rosa' => 'rosa', |
| 186 | + 'sale' => 'sali', |
| 187 | + 'sarto' => 'sarti', |
| 188 | + 'scuola' => 'scuole', |
| 189 | + 'serie' => 'serie', |
| 190 | + 'serramento' => 'serramenta', |
| 191 | + 'sorella' => 'sorelle', |
| 192 | + 'specie' => 'specie', |
| 193 | + 'staio' => 'staia', |
| 194 | + 'stazione' => 'stazioni', |
| 195 | + 'strido' => 'strida', |
| 196 | + 'strillo' => 'strilla', |
| 197 | + 'studio' => 'studi', |
| 198 | + 'suo' => 'suoi', |
| 199 | + 'superficie' => 'superfici', |
| 200 | + 'tavolo' => 'tavoli', |
| 201 | + 'tempio' => 'templi', |
| 202 | + 'treno' => 'treni', |
| 203 | + 'tuo' => 'tuoi', |
| 204 | + 'uomo' => 'uomini', |
| 205 | + 'uovo' => 'uova', |
| 206 | + 'urlo' => 'urla', |
| 207 | + 'valigia' => 'valigie', |
| 208 | + 'vestigio' => 'vestigia', |
| 209 | + 'vino' => 'vini', |
| 210 | + 'viola' => 'viola', |
| 211 | + 'zio' => 'zii', |
| 212 | + ]; |
| 213 | + |
| 214 | + foreach ($irregulars as $singular => $plural) { |
| 215 | + yield new Substitution(new Word($singular), new Word($plural)); |
| 216 | + } |
| 217 | + } |
| 218 | +} |
0 commit comments