Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2eb46eb

Browse filesBrowse files
committed
bug #54634 [String] Fix #54611 pluralization of -on ending words + singularization of -a ending foreign words (Geordie, DesLynx)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [String] Fix #54611 pluralization of -on ending words + singularization of -a ending foreign words | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #54611 | License | MIT * fix the pluralization of -on ending words as -ons (with exception for "criterion" and "phenomenon") * fix singularization of -a ending foreign words (see https://english-zone.com/spelling/plurals.html) ![image](https://github.com/symfony/symfony/assets/72632819/ee32d12d-63b6-49ef-a815-4d9f1dc2d405) note: I left "data" uninflected because it seems to me that changing it to the datum/data inflection could cause side effects as "data" is a widely used word (especially in the coding world). * update the test suites (String component + deprecated Inflector component) according to the changes Commits ------- 91325ea [String] Fix #54611 pluralization of -on ending words + singularization of -a ending foreign words
2 parents 82bb267 + 91325ea commit 2eb46eb
Copy full SHA for 2eb46eb

File tree

4 files changed

+76
-40
lines changed
Filter options

4 files changed

+76
-40
lines changed

‎src/Symfony/Component/Inflector/Tests/InflectorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Inflector/Tests/InflectorTest.php
+20-7Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static function singularizeProvider()
3737
['atlases', ['atlas', 'atlase', 'atlasis']],
3838
['axes', ['ax', 'axe', 'axis']],
3939
['babies', 'baby'],
40-
['bacteria', ['bacterion', 'bacterium']],
40+
['bacteria', 'bacterium'],
4141
['bases', ['bas', 'base', 'basis']],
4242
['batches', ['batch', 'batche']],
4343
['beaux', 'beau'],
@@ -48,6 +48,7 @@ public static function singularizeProvider()
4848
['bureaux', 'bureau'],
4949
['buses', ['bus', 'buse', 'busis']],
5050
['bushes', ['bush', 'bushe']],
51+
['buttons', 'button'],
5152
['calves', ['calf', 'calve', 'calff']],
5253
['cars', 'car'],
5354
['cassettes', ['cassett', 'cassette']],
@@ -58,10 +59,12 @@ public static function singularizeProvider()
5859
['circuses', ['circus', 'circuse', 'circusis']],
5960
['cliffs', 'cliff'],
6061
['committee', 'committee'],
62+
['corpora', 'corpus'],
63+
['coupons', 'coupon'],
6164
['crises', ['cris', 'crise', 'crisis']],
62-
['criteria', ['criterion', 'criterium']],
65+
['criteria', 'criterion'],
6366
['cups', 'cup'],
64-
['coupons', 'coupon'],
67+
['curricula', 'curriculum'],
6568
['data', 'data'],
6669
['days', 'day'],
6770
['discos', 'disco'],
@@ -87,6 +90,7 @@ public static function singularizeProvider()
8790
['funguses', ['fungus', 'funguse', 'fungusis']],
8891
['garages', ['garag', 'garage']],
8992
['geese', 'goose'],
93+
['genera', 'genus'],
9094
['halves', ['half', 'halve', 'halff']],
9195
['hats', 'hat'],
9296
['heroes', ['hero', 'heroe']],
@@ -107,6 +111,8 @@ public static function singularizeProvider()
107111
['lives', 'life'],
108112
['matrices', ['matrex', 'matrix', 'matrice']],
109113
['matrixes', 'matrix'],
114+
['media', 'medium'],
115+
['memoranda', 'memorandum'],
110116
['men', 'man'],
111117
['mice', 'mouse'],
112118
['moves', 'move'],
@@ -120,7 +126,7 @@ public static function singularizeProvider()
120126
['parties', 'party'],
121127
['people', 'person'],
122128
['persons', 'person'],
123-
['phenomena', ['phenomenon', 'phenomenum']],
129+
['phenomena', 'phenomenon'],
124130
['photos', 'photo'],
125131
['pianos', 'piano'],
126132
['plateaux', 'plateau'],
@@ -144,7 +150,7 @@ public static function singularizeProvider()
144150
['spies', 'spy'],
145151
['staves', ['staf', 'stave', 'staff']],
146152
['stories', 'story'],
147-
['strata', ['straton', 'stratum']],
153+
['strata', 'stratum'],
148154
['suitcases', ['suitcas', 'suitcase', 'suitcasis']],
149155
['syllabi', 'syllabus'],
150156
['tags', 'tag'],
@@ -195,7 +201,9 @@ public static function pluralizeProvider()
195201
['bureau', ['bureaus', 'bureaux']],
196202
['bus', 'buses'],
197203
['bush', 'bushes'],
204+
['button', 'buttons'],
198205
['calf', ['calfs', 'calves']],
206+
['campus', 'campuses'],
199207
['car', 'cars'],
200208
['cassette', 'cassettes'],
201209
['cave', 'caves'],
@@ -205,10 +213,11 @@ public static function pluralizeProvider()
205213
['circus', 'circuses'],
206214
['cliff', 'cliffs'],
207215
['committee', 'committees'],
216+
['coupon', 'coupons'],
208217
['crisis', 'crises'],
209-
['criteria', 'criterion'],
218+
['criterion', 'criteria'],
210219
['cup', 'cups'],
211-
['coupon', 'coupons'],
220+
['curriculum', 'curricula'],
212221
['data', 'data'],
213222
['day', 'days'],
214223
['disco', 'discos'],
@@ -232,10 +241,12 @@ public static function pluralizeProvider()
232241
['half', ['halfs', 'halves']],
233242
['hat', 'hats'],
234243
['hero', 'heroes'],
244+
['hippocampus', 'hippocampi'],
235245
['hippopotamus', 'hippopotami'], // hippopotamuses
236246
['hoax', 'hoaxes'],
237247
['hoof', ['hoofs', 'hooves']],
238248
['house', 'houses'],
249+
['icon', 'icons'],
239250
['index', ['indicies', 'indexes']],
240251
['ion', 'ions'],
241252
['iris', 'irises'],
@@ -248,6 +259,8 @@ public static function pluralizeProvider()
248259
['louse', 'lice'],
249260
['man', 'men'],
250261
['matrix', ['matricies', 'matrixes']],
262+
['medium', 'media'],
263+
['memorandum', 'memoranda'],
251264
['mouse', 'mice'],
252265
['move', 'moves'],
253266
['movie', 'movies'],

‎src/Symfony/Component/Inflector/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Inflector/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"php": ">=7.2.5",
2727
"symfony/deprecation-contracts": "^2.1|^3",
2828
"symfony/polyfill-php80": "^1.16",
29-
"symfony/string": "^5.3.10|^6.0"
29+
"symfony/string": "^5.4.41|^6.4.9"
3030
},
3131
"autoload": {
3232
"psr-4": { "Symfony\\Component\\Inflector\\": "" },

‎src/Symfony/Component/String/Inflector/EnglishInflector.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/String/Inflector/EnglishInflector.php
+34-25Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,32 @@ final class EnglishInflector implements InflectorInterface
2525
// Fourth entry: Whether the suffix may succeed a consonant
2626
// Fifth entry: singular suffix, normal
2727

28-
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
29-
['a', 1, true, true, ['on', 'um']],
28+
// bacteria (bacterium)
29+
['airetcab', 8, true, true, 'bacterium'],
30+
31+
// corpora (corpus)
32+
['aroproc', 7, true, true, 'corpus'],
33+
34+
// criteria (criterion)
35+
['airetirc', 8, true, true, 'criterion'],
36+
37+
// curricula (curriculum)
38+
['alucirruc', 9, true, true, 'curriculum'],
39+
40+
// genera (genus)
41+
['areneg', 6, true, true, 'genus'],
42+
43+
// media (medium)
44+
['aidem', 5, true, true, 'medium'],
45+
46+
// memoranda (memorandum)
47+
['adnaromem', 9, true, true, 'memorandum'],
48+
49+
// phenomena (phenomenon)
50+
['anemonehp', 9, true, true, 'phenomenon'],
51+
52+
// strata (stratum)
53+
['atarts', 6, true, true, 'stratum'],
3054

3155
// nebulae (nebula)
3256
['ea', 2, true, true, 'a'],
@@ -141,7 +165,7 @@ final class EnglishInflector implements InflectorInterface
141165
// shoes (shoe)
142166
['se', 2, true, true, ['', 'e']],
143167

144-
// status (status)
168+
// status (status)
145169
['sutats', 6, true, true, 'status'],
146170

147171
// tags (tag)
@@ -241,7 +265,7 @@ final class EnglishInflector implements InflectorInterface
241265
// albums (album)
242266
['mubla', 5, true, true, 'albums'],
243267

244-
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
268+
// bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum)
245269
['mu', 2, true, true, 'a'],
246270

247271
// men (man), women (woman)
@@ -250,20 +274,11 @@ final class EnglishInflector implements InflectorInterface
250274
// people (person)
251275
['nosrep', 6, true, true, ['persons', 'people']],
252276

253-
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
254-
['noi', 3, true, true, 'ions'],
255-
256-
// coupon (coupons)
257-
['nop', 3, true, true, 'pons'],
258-
259-
// seasons (season), treasons (treason), poisons (poison), lessons (lesson)
260-
['nos', 3, true, true, 'sons'],
261-
262-
// icons (icon)
263-
['noc', 3, true, true, 'cons'],
277+
// criteria (criterion)
278+
['noiretirc', 9, true, true, 'criteria'],
264279

265-
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
266-
['no', 2, true, true, 'a'],
280+
// phenomena (phenomenon)
281+
['nonemonehp', 10, true, true, 'phenomena'],
267282

268283
// echoes (echo)
269284
['ohce', 4, true, true, 'echoes'],
@@ -404,9 +419,6 @@ final class EnglishInflector implements InflectorInterface
404419
'erawdrah',
405420
];
406421

407-
/**
408-
* {@inheritdoc}
409-
*/
410422
public function singularize(string $plural): array
411423
{
412424
$pluralRev = strrev($plural);
@@ -438,7 +450,7 @@ public function singularize(string $plural): array
438450
if ($j === $suffixLength) {
439451
// Is there any character preceding the suffix in the plural string?
440452
if ($j < $pluralLength) {
441-
$nextIsVowel = false !== strpos('aeiou', $lowerPluralRev[$j]);
453+
$nextIsVowel = str_contains('aeiou', $lowerPluralRev[$j]);
442454

443455
if (!$map[2] && $nextIsVowel) {
444456
// suffix may not succeed a vowel but next char is one
@@ -483,9 +495,6 @@ public function singularize(string $plural): array
483495
return [$plural];
484496
}
485497

486-
/**
487-
* {@inheritdoc}
488-
*/
489498
public function pluralize(string $singular): array
490499
{
491500
$singularRev = strrev($singular);
@@ -518,7 +527,7 @@ public function pluralize(string $singular): array
518527
if ($j === $suffixLength) {
519528
// Is there any character preceding the suffix in the plural string?
520529
if ($j < $singularLength) {
521-
$nextIsVowel = false !== strpos('aeiou', $lowerSingularRev[$j]);
530+
$nextIsVowel = str_contains('aeiou', $lowerSingularRev[$j]);
522531

523532
if (!$map[2] && $nextIsVowel) {
524533
// suffix may not succeed a vowel but next char is one

‎src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php
+21-7Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static function singularizeProvider()
3535
['atlases', ['atlas', 'atlase', 'atlasis']],
3636
['axes', ['ax', 'axe', 'axis']],
3737
['babies', 'baby'],
38-
['bacteria', ['bacterion', 'bacterium']],
38+
['bacteria', 'bacterium'],
3939
['bases', ['bas', 'base', 'basis']],
4040
['batches', ['batch', 'batche']],
4141
['beaux', 'beau'],
@@ -46,6 +46,7 @@ public static function singularizeProvider()
4646
['bureaux', 'bureau'],
4747
['buses', ['bus', 'buse', 'busis']],
4848
['bushes', ['bush', 'bushe']],
49+
['buttons', 'button'],
4950
['calves', ['calf', 'calve', 'calff']],
5051
['cars', 'car'],
5152
['cassettes', ['cassett', 'cassette']],
@@ -57,10 +58,12 @@ public static function singularizeProvider()
5758
['cliffs', 'cliff'],
5859
['codes', 'code'],
5960
['committee', 'committee'],
61+
['corpora', 'corpus'],
62+
['coupons', 'coupon'],
6063
['crises', ['cris', 'crise', 'crisis']],
61-
['criteria', ['criterion', 'criterium']],
64+
['criteria', 'criterion'],
6265
['cups', 'cup'],
63-
['coupons', 'coupon'],
66+
['curricula', 'curriculum'],
6467
['data', 'data'],
6568
['days', 'day'],
6669
['discos', 'disco'],
@@ -86,6 +89,7 @@ public static function singularizeProvider()
8689
['funguses', ['fungus', 'funguse', 'fungusis']],
8790
['garages', ['garag', 'garage']],
8891
['geese', 'goose'],
92+
['genera', 'genus'],
8993
['halves', ['half', 'halve', 'halff']],
9094
['hats', 'hat'],
9195
['heroes', ['hero', 'heroe']],
@@ -106,6 +110,8 @@ public static function singularizeProvider()
106110
['lives', 'life'],
107111
['matrices', ['matrex', 'matrix', 'matrice']],
108112
['matrixes', 'matrix'],
113+
['media', 'medium'],
114+
['memoranda', 'memorandum'],
109115
['men', 'man'],
110116
['mice', 'mouse'],
111117
['moves', 'move'],
@@ -120,7 +126,7 @@ public static function singularizeProvider()
120126
['parties', 'party'],
121127
['people', 'person'],
122128
['persons', 'person'],
123-
['phenomena', ['phenomenon', 'phenomenum']],
129+
['phenomena', 'phenomenon'],
124130
['photos', 'photo'],
125131
['pianos', 'piano'],
126132
['plateaux', 'plateau'],
@@ -146,7 +152,7 @@ public static function singularizeProvider()
146152
['status', 'status'],
147153
['statuses', 'status'],
148154
['stories', 'story'],
149-
['strata', ['straton', 'stratum']],
155+
['strata', 'stratum'],
150156
['suitcases', ['suitcas', 'suitcase', 'suitcasis']],
151157
['syllabi', 'syllabus'],
152158
['tags', 'tag'],
@@ -200,7 +206,9 @@ public static function pluralizeProvider()
200206
['bureau', ['bureaus', 'bureaux']],
201207
['bus', 'buses'],
202208
['bush', 'bushes'],
209+
['button', 'buttons'],
203210
['calf', ['calfs', 'calves']],
211+
['campus', 'campuses'],
204212
['car', 'cars'],
205213
['cassette', 'cassettes'],
206214
['cave', 'caves'],
@@ -210,10 +218,11 @@ public static function pluralizeProvider()
210218
['circus', 'circuses'],
211219
['cliff', 'cliffs'],
212220
['committee', 'committees'],
221+
['coupon', 'coupons'],
213222
['crisis', 'crises'],
214-
['criteria', 'criterion'],
223+
['criterion', 'criteria'],
215224
['cup', 'cups'],
216-
['coupon', 'coupons'],
225+
['curriculum', 'curricula'],
217226
['data', 'data'],
218227
['day', 'days'],
219228
['disco', 'discos'],
@@ -237,10 +246,12 @@ public static function pluralizeProvider()
237246
['half', ['halfs', 'halves']],
238247
['hat', 'hats'],
239248
['hero', 'heroes'],
249+
['hippocampus', 'hippocampi'],
240250
['hippopotamus', 'hippopotami'], // hippopotamuses
241251
['hoax', 'hoaxes'],
242252
['hoof', ['hoofs', 'hooves']],
243253
['house', 'houses'],
254+
['icon', 'icons'],
244255
['index', ['indicies', 'indexes']],
245256
['ion', 'ions'],
246257
['iris', 'irises'],
@@ -253,6 +264,8 @@ public static function pluralizeProvider()
253264
['louse', 'lice'],
254265
['man', 'men'],
255266
['matrix', ['matricies', 'matrixes']],
267+
['medium', 'media'],
268+
['memorandum', 'memoranda'],
256269
['mouse', 'mice'],
257270
['move', 'moves'],
258271
['movie', 'movies'],
@@ -286,6 +299,7 @@ public static function pluralizeProvider()
286299
['shoe', 'shoes'],
287300
['species', 'species'],
288301
['status', ['status', 'statuses']],
302+
['stratum', 'strata'],
289303
['spy', 'spies'],
290304
['staff', 'staves'],
291305
['story', 'stories'],

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.