Skip to content

Commit

Permalink
Localized inflections are now autoloaded
Browse files Browse the repository at this point in the history
  • Loading branch information
olvlvl committed Jul 16, 2021
1 parent 77a5dfc commit 8458280
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 240 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

A multilingual inflector that transforms words from singular to plural, underscore to camel case, and formats strings in
various ways. Inflections are localized, the default english inflections for pluralization, singularization, and
uncountable words are kept in [lib/inflections/en.php](lib/Inflections/en.php).
uncountable words are kept in [lib/Inflections/en.php](lib/Inflections/en.php).

Inflections are currently available for the following languages:

Expand All @@ -28,7 +28,7 @@ composer require icanboogie/inflector



### Usage
## Usage

These are some examples of the inflector with the `en` locale (default).

Expand Down Expand Up @@ -135,8 +135,15 @@ echo pluralize('üçgen', 'tr'); // "üçgenler"
```


## About inflections

### Acknowledgements
Inflections are localized, the configurators are kept in [lib/Inflections/en.php](lib/Inflections/en.php). Since v2.1,
these configurators are auto-loaded classes, which means, in theory, you could add your own or overwrite those already
defined by specifying another `ICanBoogie\\Inflections\\` in your `composer.json` file.



## Acknowledgements

Most of the code and documentation was adapted from [Ruby On Rails](http://rubyonrails.org/)'s
[Inflector](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html) and
Expand All @@ -155,7 +162,7 @@ Significant differences:



### Getting started
## Getting started

**Inflector** expects to work in UTF-8, which is the default encoding character set starting
PHP 5.6, for older versions please use `mb_internal_encoding()` as follows:
Expand Down
10 changes: 5 additions & 5 deletions lib/Inflections.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ public static function get(string $locale = INFLECTOR_DEFAULT_LOCALE): Inflectio
return self::$inflections[$locale];
}

$instance = new self();
$inflections = new self();

/* @var $inflections callable */
/* @var $configurator InflectionsConfigurator */

$inflections = require __DIR__ . "/Inflections/{$locale}.php";
$inflections($instance);
$configurator = __NAMESPACE__ . "\\Inflections\\$locale";
$configurator::configure($inflections);

return self::$inflections[$locale] = $instance;
return self::$inflections[$locale] = $inflections;
}

/**
Expand Down
139 changes: 74 additions & 65 deletions lib/Inflections/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,73 +9,82 @@
* file that was distributed with this source code.
*/

namespace ICanBoogie;
namespace ICanBoogie\Inflections;

use ICanBoogie\Inflections;
use ICanBoogie\InflectionsConfigurator;

use function explode;

/**
* English Inflections.
*
* @codeCoverageIgnore
*/
//@codeCoverageIgnoreStart
return function (Inflections $inflect): void {
$inflect
->plural('/$/', 's')
->plural('/s$/i', 's')
->plural('/^(ax|test)is$/i', '\1es')
->plural('/(alias|status)$/i', '\1es')
->plural('/(bu)s$/i', '\1ses')
->plural('/(buffal|tomat|potat|volcan|her)o$/i', '\1oes')
->plural('/([ti])um$/i', '\1a')
->plural('/([ti])a$/i', '\1a')
->plural('/sis$/i', 'ses')
->plural('/(?:([^f])fe|([lr])f)$/i', '\1\2ves')
->plural('/(hive)$/i', '\1s')
->plural('/([^aeiouy]|qu)y$/i', '\1ies')
->plural('/(x|ch|ss|sh)$/i', '\1es')
->plural('/(matr|vert|ind)(?:ix|ex)$/i', '\1ices')
->plural('/^(m|l)ouse$/i', '\1ice')
->plural('/^(m|l)ice$/i', '\1ice')
->plural('/^(ox)$/i', '\1en')
->plural('/^(oxen)$/i', '\1')
->plural('/(quiz)$/i', '\1zes')
->singular('/s$/i', '')
->singular('/(ss)$/i', '\1')
->singular('/(n)ews$/i', '\1ews')
->singular('/([ti])a$/i', '\1um')
->singular('/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i', '\1sis')
->singular('/(^analy)(sis|ses)$/i', '\1sis')
->singular('/([^f])ves$/i', '\1fe')
->singular('/(hive)s$/i', '\1')
->singular('/(tive)s$/i', '\1')
->singular('/([lr])ves$/i', '\1f')
->singular('/([^aeiouy]|qu)ies$/i', '\1y')
->singular('/(s)eries$/i', '\1eries')
->singular('/(m)ovies$/i', '\1ovie')
->singular('/(x|ch|ss|sh)es$/i', '\1')
->singular('/^(m|l)ice$/i', '\1ouse')
->singular('/(bus)(es)?$/i', '\1')
->singular('/(o)es$/i', '\1')
->singular('/(shoe)s$/i', '\1')
->singular('/(cris|test)(is|es)$/i', '\1is')
->singular('/^(a)x[ie]s$/i', '\1xis')
->singular('/(alias|status)(es)?$/i', '\1')
->singular('/^(ox)en/i', '\1')
->singular('/(vert|ind)ices$/i', '\1ex')
->singular('/(matr)ices$/i', '\1ix')
->singular('/(quiz)zes$/i', '\1')
->singular('/(database)s$/i', '\1')
->irregular('leaf', 'leaves')
->irregular('loaf', 'loaves')
->irregular('octopus', 'octopuses')
->irregular('virus', 'viruses')
->irregular('person', 'people')
->irregular('man', 'men')
->irregular('child', 'children')
->irregular('sex', 'sexes')
->irregular('move', 'moves')
->irregular('zombie', 'zombies')
->irregular('goose', 'geese')
->irregular('genus', 'genera')
final class en implements InflectionsConfigurator
{
public static function configure(Inflections $inflections): void
{
$inflections
->plural('/$/', 's')
->plural('/s$/i', 's')
->plural('/^(ax|test)is$/i', '\1es')
->plural('/(alias|status)$/i', '\1es')
->plural('/(bu)s$/i', '\1ses')
->plural('/(buffal|tomat|potat|volcan|her)o$/i', '\1oes')
->plural('/([ti])um$/i', '\1a')
->plural('/([ti])a$/i', '\1a')
->plural('/sis$/i', 'ses')
->plural('/(?:([^f])fe|([lr])f)$/i', '\1\2ves')
->plural('/(hive)$/i', '\1s')
->plural('/([^aeiouy]|qu)y$/i', '\1ies')
->plural('/(x|ch|ss|sh)$/i', '\1es')
->plural('/(matr|vert|ind)(?:ix|ex)$/i', '\1ices')
->plural('/^(m|l)ouse$/i', '\1ice')
->plural('/^(m|l)ice$/i', '\1ice')
->plural('/^(ox)$/i', '\1en')
->plural('/^(oxen)$/i', '\1')
->plural('/(quiz)$/i', '\1zes')
->singular('/s$/i', '')
->singular('/(ss)$/i', '\1')
->singular('/(n)ews$/i', '\1ews')
->singular('/([ti])a$/i', '\1um')
->singular('/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i', '\1sis')
->singular('/(^analy)(sis|ses)$/i', '\1sis')
->singular('/([^f])ves$/i', '\1fe')
->singular('/(hive)s$/i', '\1')
->singular('/(tive)s$/i', '\1')
->singular('/([lr])ves$/i', '\1f')
->singular('/([^aeiouy]|qu)ies$/i', '\1y')
->singular('/(s)eries$/i', '\1eries')
->singular('/(m)ovies$/i', '\1ovie')
->singular('/(x|ch|ss|sh)es$/i', '\1')
->singular('/^(m|l)ice$/i', '\1ouse')
->singular('/(bus)(es)?$/i', '\1')
->singular('/(o)es$/i', '\1')
->singular('/(shoe)s$/i', '\1')
->singular('/(cris|test)(is|es)$/i', '\1is')
->singular('/^(a)x[ie]s$/i', '\1xis')
->singular('/(alias|status)(es)?$/i', '\1')
->singular('/^(ox)en/i', '\1')
->singular('/(vert|ind)ices$/i', '\1ex')
->singular('/(matr)ices$/i', '\1ix')
->singular('/(quiz)zes$/i', '\1')
->singular('/(database)s$/i', '\1')
->irregular('leaf', 'leaves')
->irregular('loaf', 'loaves')
->irregular('octopus', 'octopuses')
->irregular('virus', 'viruses')
->irregular('person', 'people')
->irregular('man', 'men')
->irregular('child', 'children')
->irregular('sex', 'sexes')
->irregular('move', 'moves')
->irregular('zombie', 'zombies')
->irregular('goose', 'geese')
->irregular('genus', 'genera')

// http://easenglish.net/Files/Grammar/uncountable%20words.pdf
->uncountable(explode(' ', 'advice aircraft art baggage butter clothing coal cotton deer equipment experience feedback fish flour food furniture gas homework impatience information jeans knowledge leather love luggage management money moose music news oil patience police polish progress research rice salmon sand series sheep silk sms soap spam species staff sugar swine talent toothpaste traffic travel vinegar weather wood wool work'));
};
//@codeCoverageIgnoreEnd
// http://easenglish.net/Files/Grammar/uncountable%20words.pdf
->uncountable(explode(' ', 'advice aircraft art baggage butter clothing coal cotton deer equipment experience feedback fish flour food furniture gas homework impatience information jeans knowledge leather love luggage management money moose music news oil patience police polish progress research rice salmon sand series sheep silk sms soap spam species staff sugar swine talent toothpaste traffic travel vinegar weather wood wool work'));
}
}
65 changes: 36 additions & 29 deletions lib/Inflections/es.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,46 @@
* file that was distributed with this source code.
*/

namespace ICanBoogie;
namespace ICanBoogie\Inflections;

use ICanBoogie\Inflections;
use ICanBoogie\InflectionsConfigurator;

/**
* Spanish Inflections.
*
* @see http://www.studyspanish.com/lessons/plnoun.htm
* @see http://spanish.about.com/cs/writing/a/writing_plurals.htm
*
* @codeCoverageIgnore
*/
//@codeCoverageIgnoreStart
return function (Inflections $inflect): void {
$inflect
->plural('/$/', 's')
->plural('/([^aeéiou])$/i', '\1es')
->plural('/([aeiou]s)$/i', '\1')
->plural('/z$/i', 'ces')
->plural('/á([sn])$/i', 'a\1es')
->plural('/é([sn])$/i', 'e\1es')
->plural('/í([sn])$/i', 'i\1es')
->plural('/ó([sn])$/i', 'o\1es')
->plural('/ú([sn])$/i', 'u\1es')
->singular('/s$/', '')
->singular('/es$/', '')
->singular('/ces$/', 'z')
->singular('/iones$/', 'ión')
->singular('/ereses$/', 'erés')
->irregular('el', 'los')
->irregular('lunes', 'lunes')
->irregular('rompecabezas', 'rompecabezas')
->irregular('crisis', 'crisis')
->irregular('papá', 'papás')
->irregular('mamá', 'mamás')
->irregular('sofá', 'sofás')
// because 'mes' is considered already a plural
->irregular('mes', 'meses');
};
//@codeCoverageIgnoreEnd
final class es implements InflectionsConfigurator
{
public static function configure(Inflections $inflections): void
{
$inflections
->plural('/$/', 's')
->plural('/([^aeéiou])$/i', '\1es')
->plural('/([aeiou]s)$/i', '\1')
->plural('/z$/i', 'ces')
->plural('/á([sn])$/i', 'a\1es')
->plural('/é([sn])$/i', 'e\1es')
->plural('/í([sn])$/i', 'i\1es')
->plural('/ó([sn])$/i', 'o\1es')
->plural('/ú([sn])$/i', 'u\1es')
->singular('/s$/', '')
->singular('/es$/', '')
->singular('/ces$/', 'z')
->singular('/iones$/', 'ión')
->singular('/ereses$/', 'erés')
->irregular('el', 'los')
->irregular('lunes', 'lunes')
->irregular('rompecabezas', 'rompecabezas')
->irregular('crisis', 'crisis')
->irregular('papá', 'papás')
->irregular('mamá', 'mamás')
->irregular('sofá', 'sofás')
// because 'mes' is considered already a plural
->irregular('mes', 'meses');
}
}
49 changes: 28 additions & 21 deletions lib/Inflections/fr.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,37 @@
* file that was distributed with this source code.
*/

namespace ICanBoogie;
namespace ICanBoogie\Inflections;

use ICanBoogie\Inflections;
use ICanBoogie\InflectionsConfigurator;

/**
* French Inflections.
*
* @see http://grammaire.reverso.net/5_5_01_pluriel_des_noms_et_des_adjectifs.shtml
*
* @codeCoverageIgnore
*/
//@codeCoverageIgnoreStart
return function (Inflections $inflect): void {
$inflect
->plural('/$/', 's')
->singular('/s$/', '')
->plural('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/', '\1x')
->singular('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/', '\1')
->plural('/(bleu|émeu|landau|lieu|pneu|sarrau)$/', '\1s')
->plural('/al$/', 'aux')
->plural('/ail$/', 'ails')
->singular('/(journ|chev)aux$/', '\1al')
->singular('/ails$/', 'ail')
->plural('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/', '\1aux')
->singular('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/', '\1ail')
->plural('/(s|x|z)$/', '\1')
->irregular('monsieur', 'messieurs')
->irregular('madame', 'mesdames')
->irregular('mademoiselle', 'mesdemoiselles');
};
//@codeCoverageIgnoreEnd
final class fr implements InflectionsConfigurator
{
public static function configure(Inflections $inflections): void
{
$inflections
->plural('/$/', 's')
->singular('/s$/', '')
->plural('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/', '\1x')
->singular('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/', '\1')
->plural('/(bleu|émeu|landau|lieu|pneu|sarrau)$/', '\1s')
->plural('/al$/', 'aux')
->plural('/ail$/', 'ails')
->singular('/(journ|chev)aux$/', '\1al')
->singular('/ails$/', 'ail')
->plural('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/', '\1aux')
->singular('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/', '\1ail')
->plural('/(s|x|z)$/', '\1')
->irregular('monsieur', 'messieurs')
->irregular('madame', 'mesdames')
->irregular('mademoiselle', 'mesdemoiselles');
}
}
35 changes: 22 additions & 13 deletions lib/Inflections/nb.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,29 @@
* file that was distributed with this source code.
*/

namespace ICanBoogie;
namespace ICanBoogie\Inflections;

use ICanBoogie\Inflections;
use ICanBoogie\InflectionsConfigurator;

use function explode;

/**
* Norwegian Bokmal Inflections.
*
* @codeCoverageIgnore
*/
//@codeCoverageIgnoreStart
return function (Inflections $inflect): void {
$inflect
->plural('/$/', 'er')
->plural('/r$/i', 're')
->plural('/e$/i', 'er')
->singular('/er$/i', '')
->singular('/re$/i', 'r')
->irregular('konto', 'konti')
->uncountable(explode(' ', 'barn fjell hus'));
};
//@codeCoverageIgnoreEnd
final class nb implements InflectionsConfigurator
{
public static function configure(Inflections $inflections): void
{
$inflections
->plural('/$/', 'er')
->plural('/r$/i', 're')
->plural('/e$/i', 'er')
->singular('/er$/i', '')
->singular('/re$/i', 'r')
->irregular('konto', 'konti')
->uncountable(explode(' ', 'barn fjell hus'));
}
}
Loading

0 comments on commit 8458280

Please sign in to comment.