PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.3
MailPoet – Newsletters, Email Marketing, and Automation v5.34.3
5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor-prefixed / symfony / string / Inflector / EnglishInflector.php
mailpoet / vendor-prefixed / symfony / string / Inflector Last commit date
EnglishInflector.php 9 months ago FrenchInflector.php 2 years ago InflectorInterface.php 2 years ago index.php 2 years ago
EnglishInflector.php
401 lines
1 <?php
2 namespace MailPoetVendor\Symfony\Component\String\Inflector;
3 if (!defined('ABSPATH')) exit;
4 final class EnglishInflector implements InflectorInterface
5 {
6 private const PLURAL_MAP = [
7 // First entry: plural suffix, reversed
8 // Second entry: length of plural suffix
9 // Third entry: Whether the suffix may succeed a vowel
10 // Fourth entry: Whether the suffix may succeed a consonant
11 // Fifth entry: singular suffix, normal
12 // bacteria (bacterium)
13 ['airetcab', 8, \true, \true, 'bacterium'],
14 // corpora (corpus)
15 ['aroproc', 7, \true, \true, 'corpus'],
16 // criteria (criterion)
17 ['airetirc', 8, \true, \true, 'criterion'],
18 // curricula (curriculum)
19 ['alucirruc', 9, \true, \true, 'curriculum'],
20 // genera (genus)
21 ['areneg', 6, \true, \true, 'genus'],
22 // media (medium)
23 ['aidem', 5, \true, \true, 'medium'],
24 // memoranda (memorandum)
25 ['adnaromem', 9, \true, \true, 'memorandum'],
26 // phenomena (phenomenon)
27 ['anemonehp', 9, \true, \true, 'phenomenon'],
28 // strata (stratum)
29 ['atarts', 6, \true, \true, 'stratum'],
30 // nebulae (nebula)
31 ['ea', 2, \true, \true, 'a'],
32 // services (service)
33 ['secivres', 8, \true, \true, 'service'],
34 // mice (mouse), lice (louse)
35 ['eci', 3, \false, \true, 'ouse'],
36 // geese (goose)
37 ['esee', 4, \false, \true, 'oose'],
38 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
39 ['i', 1, \true, \true, 'us'],
40 // men (man), women (woman)
41 ['nem', 3, \true, \true, 'man'],
42 // children (child)
43 ['nerdlihc', 8, \true, \true, 'child'],
44 // oxen (ox)
45 ['nexo', 4, \false, \false, 'ox'],
46 // indices (index), appendices (appendix), prices (price)
47 ['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
48 // codes (code)
49 ['sedoc', 5, \false, \true, 'code'],
50 // selfies (selfie)
51 ['seifles', 7, \true, \true, 'selfie'],
52 // zombies (zombie)
53 ['seibmoz', 7, \true, \true, 'zombie'],
54 // movies (movie)
55 ['seivom', 6, \true, \true, 'movie'],
56 // names (name)
57 ['seman', 5, \true, \false, 'name'],
58 // conspectuses (conspectus), prospectuses (prospectus)
59 ['sesutcep', 8, \true, \true, 'pectus'],
60 // feet (foot)
61 ['teef', 4, \true, \true, 'foot'],
62 // geese (goose)
63 ['eseeg', 5, \true, \true, 'goose'],
64 // teeth (tooth)
65 ['hteet', 5, \true, \true, 'tooth'],
66 // news (news)
67 ['swen', 4, \true, \true, 'news'],
68 // series (series)
69 ['seires', 6, \true, \true, 'series'],
70 // babies (baby)
71 ['sei', 3, \false, \true, 'y'],
72 // accesses (access), addresses (address), kisses (kiss)
73 ['sess', 4, \true, \false, 'ss'],
74 // statuses (status)
75 ['sesutats', 8, \true, \true, 'status'],
76 // article (articles), ancle (ancles)
77 ['sel', 3, \true, \true, 'le'],
78 // analyses (analysis), ellipses (ellipsis), fungi (fungus),
79 // neuroses (neurosis), theses (thesis), emphases (emphasis),
80 // oases (oasis), crises (crisis), houses (house), bases (base),
81 // atlases (atlas)
82 ['ses', 3, \true, \true, ['s', 'se', 'sis']],
83 // objectives (objective), alternative (alternatives)
84 ['sevit', 5, \true, \true, 'tive'],
85 // drives (drive)
86 ['sevird', 6, \false, \true, 'drive'],
87 // lives (life), wives (wife)
88 ['sevi', 4, \false, \true, 'ife'],
89 // moves (move)
90 ['sevom', 5, \true, \true, 'move'],
91 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
92 ['sev', 3, \true, \true, ['f', 've', 'ff']],
93 // axes (axis), axes (ax), axes (axe)
94 ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']],
95 // indexes (index), matrixes (matrix)
96 ['sex', 3, \true, \false, 'x'],
97 // quizzes (quiz)
98 ['sezz', 4, \true, \false, 'z'],
99 // bureaus (bureau)
100 ['suae', 4, \false, \true, 'eau'],
101 // fees (fee), trees (tree), employees (employee)
102 ['see', 3, \true, \true, 'ee'],
103 // edges (edge)
104 ['segd', 4, \true, \true, 'dge'],
105 // roses (rose), garages (garage), cassettes (cassette),
106 // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
107 // shoes (shoe)
108 ['se', 2, \true, \true, ['', 'e']],
109 // status (status)
110 ['sutats', 6, \true, \true, 'status'],
111 // tags (tag)
112 ['s', 1, \true, \true, ''],
113 // chateaux (chateau)
114 ['xuae', 4, \false, \true, 'eau'],
115 // people (person)
116 ['elpoep', 6, \true, \true, 'person'],
117 ];
118 private const SINGULAR_MAP = [
119 // First entry: singular suffix, reversed
120 // Second entry: length of singular suffix
121 // Third entry: Whether the suffix may succeed a vowel
122 // Fourth entry: Whether the suffix may succeed a consonant
123 // Fifth entry: plural suffix, normal
124 // axes (axis)
125 ['sixa', 4, \false, \false, 'axes'],
126 // criterion (criteria)
127 ['airetirc', 8, \false, \false, 'criterion'],
128 // nebulae (nebula)
129 ['aluben', 6, \false, \false, 'nebulae'],
130 // children (child)
131 ['dlihc', 5, \true, \true, 'children'],
132 // prices (price)
133 ['eci', 3, \false, \true, 'ices'],
134 // services (service)
135 ['ecivres', 7, \true, \true, 'services'],
136 // lives (life), wives (wife)
137 ['efi', 3, \false, \true, 'ives'],
138 // selfies (selfie)
139 ['eifles', 6, \true, \true, 'selfies'],
140 // movies (movie)
141 ['eivom', 5, \true, \true, 'movies'],
142 // lice (louse)
143 ['esuol', 5, \false, \true, 'lice'],
144 // mice (mouse)
145 ['esuom', 5, \false, \true, 'mice'],
146 // geese (goose)
147 ['esoo', 4, \false, \true, 'eese'],
148 // houses (house), bases (base)
149 ['es', 2, \true, \true, 'ses'],
150 // geese (goose)
151 ['esoog', 5, \true, \true, 'geese'],
152 // caves (cave)
153 ['ev', 2, \true, \true, 'ves'],
154 // drives (drive)
155 ['evird', 5, \false, \true, 'drives'],
156 // objectives (objective), alternative (alternatives)
157 ['evit', 4, \true, \true, 'tives'],
158 // moves (move)
159 ['evom', 4, \true, \true, 'moves'],
160 // staves (staff)
161 ['ffats', 5, \true, \true, 'staves'],
162 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
163 ['ff', 2, \true, \true, 'ffs'],
164 // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
165 ['f', 1, \true, \true, ['fs', 'ves']],
166 // arches (arch)
167 ['hc', 2, \true, \true, 'ches'],
168 // bushes (bush)
169 ['hs', 2, \true, \true, 'shes'],
170 // teeth (tooth)
171 ['htoot', 5, \true, \true, 'teeth'],
172 // albums (album)
173 ['mubla', 5, \true, \true, 'albums'],
174 // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum)
175 ['mu', 2, \true, \true, 'a'],
176 // men (man), women (woman)
177 ['nam', 3, \true, \true, 'men'],
178 // people (person)
179 ['nosrep', 6, \true, \true, ['persons', 'people']],
180 // criteria (criterion)
181 ['noiretirc', 9, \true, \true, 'criteria'],
182 // phenomena (phenomenon)
183 ['nonemonehp', 10, \true, \true, 'phenomena'],
184 // echoes (echo)
185 ['ohce', 4, \true, \true, 'echoes'],
186 // heroes (hero)
187 ['oreh', 4, \true, \true, 'heroes'],
188 // atlases (atlas)
189 ['salta', 5, \true, \true, 'atlases'],
190 // aliases (alias)
191 ['saila', 5, \true, \true, 'aliases'],
192 // irises (iris)
193 ['siri', 4, \true, \true, 'irises'],
194 // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
195 // theses (thesis), emphases (emphasis), oases (oasis),
196 // crises (crisis)
197 ['sis', 3, \true, \true, 'ses'],
198 // accesses (access), addresses (address), kisses (kiss)
199 ['ss', 2, \true, \false, 'sses'],
200 // syllabi (syllabus)
201 ['suballys', 8, \true, \true, 'syllabi'],
202 // buses (bus)
203 ['sub', 3, \true, \true, 'buses'],
204 // circuses (circus)
205 ['suc', 3, \true, \true, 'cuses'],
206 // hippocampi (hippocampus)
207 ['supmacoppih', 11, \false, \false, 'hippocampi'],
208 // campuses (campus)
209 ['sup', 3, \true, \true, 'puses'],
210 // status (status)
211 ['sutats', 6, \true, \true, ['status', 'statuses']],
212 // conspectuses (conspectus), prospectuses (prospectus)
213 ['sutcep', 6, \true, \true, 'pectuses'],
214 // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
215 ['su', 2, \true, \true, 'i'],
216 // news (news)
217 ['swen', 4, \true, \true, 'news'],
218 // feet (foot)
219 ['toof', 4, \true, \true, 'feet'],
220 // chateaux (chateau), bureaus (bureau)
221 ['uae', 3, \false, \true, ['eaus', 'eaux']],
222 // oxen (ox)
223 ['xo', 2, \false, \false, 'oxen'],
224 // hoaxes (hoax)
225 ['xaoh', 4, \true, \false, 'hoaxes'],
226 // indices (index)
227 ['xedni', 5, \false, \true, ['indicies', 'indexes']],
228 // fax (faxes, faxxes)
229 ['xaf', 3, \true, \true, ['faxes', 'faxxes']],
230 // boxes (box)
231 ['xo', 2, \false, \true, 'oxes'],
232 // indexes (index), matrixes (matrix), appendices (appendix)
233 ['x', 1, \true, \false, ['ces', 'xes']],
234 // babies (baby)
235 ['y', 1, \false, \true, 'ies'],
236 // quizzes (quiz)
237 ['ziuq', 4, \true, \false, 'quizzes'],
238 // waltzes (waltz)
239 ['z', 1, \true, \true, 'zes'],
240 ];
241 private const UNINFLECTED = [
242 '',
243 // data
244 'atad',
245 // deer
246 'reed',
247 // equipment
248 'tnempiuqe',
249 // feedback
250 'kcabdeef',
251 // fish
252 'hsif',
253 // health
254 'htlaeh',
255 // history
256 'yrotsih',
257 // info
258 'ofni',
259 // information
260 'noitamrofni',
261 // money
262 'yenom',
263 // moose
264 'esoom',
265 // series
266 'seires',
267 // sheep
268 'peehs',
269 // species
270 'seiceps',
271 // traffic
272 'ciffart',
273 // aircraft
274 'tfarcria',
275 // hardware
276 'erawdrah',
277 ];
278 public function singularize(string $plural) : array
279 {
280 $pluralRev = \strrev($plural);
281 $lowerPluralRev = \strtolower($pluralRev);
282 $pluralLength = \strlen($lowerPluralRev);
283 // Check if the word is one which is not inflected, return early if so
284 if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) {
285 return [$plural];
286 }
287 // The outer loop iterates over the entries of the plural table
288 // The inner loop $j iterates over the characters of the plural suffix
289 // in the plural table to compare them with the characters of the actual
290 // given plural suffix
291 foreach (self::PLURAL_MAP as $map) {
292 $suffix = $map[0];
293 $suffixLength = $map[1];
294 $j = 0;
295 // Compare characters in the plural table and of the suffix of the
296 // given plural one by one
297 while ($suffix[$j] === $lowerPluralRev[$j]) {
298 // Let $j point to the next character
299 ++$j;
300 // Successfully compared the last character
301 // Add an entry with the singular suffix to the singular array
302 if ($j === $suffixLength) {
303 // Is there any character preceding the suffix in the plural string?
304 if ($j < $pluralLength) {
305 $nextIsVowel = \str_contains('aeiou', $lowerPluralRev[$j]);
306 if (!$map[2] && $nextIsVowel) {
307 // suffix may not succeed a vowel but next char is one
308 break;
309 }
310 if (!$map[3] && !$nextIsVowel) {
311 // suffix may not succeed a consonant but next char is one
312 break;
313 }
314 }
315 $newBase = \substr($plural, 0, $pluralLength - $suffixLength);
316 $newSuffix = $map[4];
317 // Check whether the first character in the plural suffix
318 // is uppercased. If yes, uppercase the first character in
319 // the singular suffix too
320 $firstUpper = \ctype_upper($pluralRev[$j - 1]);
321 if (\is_array($newSuffix)) {
322 $singulars = [];
323 foreach ($newSuffix as $newSuffixEntry) {
324 $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
325 }
326 return $singulars;
327 }
328 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
329 }
330 // Suffix is longer than word
331 if ($j === $pluralLength) {
332 break;
333 }
334 }
335 }
336 // Assume that plural and singular is identical
337 return [$plural];
338 }
339 public function pluralize(string $singular) : array
340 {
341 $singularRev = \strrev($singular);
342 $lowerSingularRev = \strtolower($singularRev);
343 $singularLength = \strlen($lowerSingularRev);
344 // Check if the word is one which is not inflected, return early if so
345 if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) {
346 return [$singular];
347 }
348 // The outer loop iterates over the entries of the singular table
349 // The inner loop $j iterates over the characters of the singular suffix
350 // in the singular table to compare them with the characters of the actual
351 // given singular suffix
352 foreach (self::SINGULAR_MAP as $map) {
353 $suffix = $map[0];
354 $suffixLength = $map[1];
355 $j = 0;
356 // Compare characters in the singular table and of the suffix of the
357 // given plural one by one
358 while ($suffix[$j] === $lowerSingularRev[$j]) {
359 // Let $j point to the next character
360 ++$j;
361 // Successfully compared the last character
362 // Add an entry with the plural suffix to the plural array
363 if ($j === $suffixLength) {
364 // Is there any character preceding the suffix in the plural string?
365 if ($j < $singularLength) {
366 $nextIsVowel = \str_contains('aeiou', $lowerSingularRev[$j]);
367 if (!$map[2] && $nextIsVowel) {
368 // suffix may not succeed a vowel but next char is one
369 break;
370 }
371 if (!$map[3] && !$nextIsVowel) {
372 // suffix may not succeed a consonant but next char is one
373 break;
374 }
375 }
376 $newBase = \substr($singular, 0, $singularLength - $suffixLength);
377 $newSuffix = $map[4];
378 // Check whether the first character in the singular suffix
379 // is uppercased. If yes, uppercase the first character in
380 // the singular suffix too
381 $firstUpper = \ctype_upper($singularRev[$j - 1]);
382 if (\is_array($newSuffix)) {
383 $plurals = [];
384 foreach ($newSuffix as $newSuffixEntry) {
385 $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
386 }
387 return $plurals;
388 }
389 return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
390 }
391 // Suffix is longer than word
392 if ($j === $singularLength) {
393 break;
394 }
395 }
396 }
397 // Assume that plural is singular with a trailing `s`
398 return [$singular . 's'];
399 }
400 }
401