Commit 26afb000 authored by Taylor Otwell's avatar Taylor Otwell

Added in automatic inflection on english strings. Non-english strings may be...

Added in automatic inflection on english strings. Non-english strings may be added to the "irregular" array.
parent d80730cf
...@@ -11,22 +11,90 @@ return array( ...@@ -11,22 +11,90 @@ return array(
| the "singular" and "plural" methods on the Str class to convert a given | the "singular" and "plural" methods on the Str class to convert a given
| word from singular to plural and vice versa. | word from singular to plural and vice versa.
| |
| This simple array is in constrast to the complicated regular expression | Note that the regular expressions are only for inflecting English words.
| patterns used by other frameworks. We think you'll enjoy the speed and | To inflect a non-English string, simply add its singular and plural
| simplicity of this solution. | form to the array of "irregular" word forms.
|
| When adding a word to the array, the key should be the singular form,
| while the array value should be the plural form. We've included an
| example to get you started!
| |
*/ */
'inflection' => array( 'plural' => array(
'/(quiz)$/i' => "$1zes",
'/^(ox)$/i' => "$1en",
'/([m|l])ouse$/i' => "$1ice",
'/(matr|vert|ind)ix|ex$/i' => "$1ices",
'/(x|ch|ss|sh)$/i' => "$1es",
'/([^aeiouy]|qu)y$/i' => "$1ies",
'/(hive)$/i' => "$1s",
'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
'/(shea|lea|loa|thie)f$/i' => "$1ves",
'/sis$/i' => "ses",
'/([ti])um$/i' => "$1a",
'/(tomat|potat|ech|her|vet)o$/i' => "$1oes",
'/(bu)s$/i' => "$1ses",
'/(alias)$/i' => "$1es",
'/(octop)us$/i' => "$1i",
'/(ax|test)is$/i' => "$1es",
'/(us)$/i' => "$1es",
'/s$/i' => "s",
'/$/' => "s"
),
'user' => 'users', 'singular' => array(
'person' => 'people', '/(quiz)zes$/i' => "$1",
'comment' => 'comments', '/(matr)ices$/i' => "$1ix",
'/(vert|ind)ices$/i' => "$1ex",
'/^(ox)en$/i' => "$1",
'/(alias)es$/i' => "$1",
'/(octop|vir)i$/i' => "$1us",
'/(cris|ax|test)es$/i' => "$1is",
'/(shoe)s$/i' => "$1",
'/(o)es$/i' => "$1",
'/(bus)es$/i' => "$1",
'/([m|l])ice$/i' => "$1ouse",
'/(x|ch|ss|sh)es$/i' => "$1",
'/(m)ovies$/i' => "$1ovie",
'/(s)eries$/i' => "$1eries",
'/([^aeiouy]|qu)ies$/i' => "$1y",
'/([lr])ves$/i' => "$1f",
'/(tive)s$/i' => "$1",
'/(hive)s$/i' => "$1",
'/(li|wi|kni)ves$/i' => "$1fe",
'/(shea|loa|lea|thie)ves$/i' => "$1f",
'/(^analy)ses$/i' => "$1sis",
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
'/([ti])a$/i' => "$1um",
'/(n)ews$/i' => "$1ews",
'/(h|bl)ouses$/i' => "$1ouse",
'/(corpse)s$/i' => "$1",
'/(us)es$/i' => "$1",
'/(us|ss)$/i' => "$1",
'/s$/i' => "",
),
'irregular' => array(
'child' => 'children',
'foot' => 'feet',
'goose' => 'geese',
'man' => 'men',
'move' => 'moves',
'person' => 'people',
'sex' => 'sexes',
'tooth' => 'teeth',
),
'uncountable' => array(
'audio',
'equipment',
'deer',
'fish',
'gold',
'information',
'money',
'rice',
'police',
'series',
'sheep',
'species',
), ),
/* /*
......
<?php namespace Laravel;
class Pluralizer {
/**
* The "strings" configuration array.
*
* @var array
*/
protected $config;
/**
* The cached copies of the plural inflections.
*/
protected $plural = array();
/**
* The cached copies of the singular inflections.
*
* @var array
*/
protected $singular = array();
/**
* Create a new pluralizer instance.
*
* @return void
*/
public function __construct($config)
{
$this->config = $config;
}
/**
* Get the singular form of the given word.
*
* @param string $value
* @return string
*/
public function singular($value)
{
// First we'll check the cache of inflected values. We cache each word that
// is inflected so we don't have to spin through the regular expressions
// each time we need to inflect a given value for the developer.
if (isset($this->singular[$value]))
{
return $this->singular[$value];
}
// English words may be automatically inflected using regular expressions.
// If the word is english, we'll just pass off the word to the automatic
// inflection method and return the result, which is cached.
$irregular = $this->config['irregular'];
$result = $this->auto($value, $this->config['singular'], $irregular);
return $this->singular[$value] = $result ?: $value;
}
/**
* Get the plural form of the given word.
*
* @param string $value
* @param int $count
* @return string
*/
public function plural($value, $count = 2)
{
if ((int) $count == 1) return $value;
// First we'll check the cache of inflected values. We cache each word that
// is inflected so we don't have to spin through the regular expressions
// each time we need to inflect a given value for the developer.
if (isset($this->plural[$value]))
{
return $this->plural[$value];
}
// English words may be automatically inflected using regular expressions.
// If the word is english, we'll just pass off the word to the automatic
// inflection method and return the result, which is cached.
$irregular = array_flip($this->config['irregular']);
$result = $this->auto($value, $this->config['plural'], $irregular);
return $this->plural[$value] = $result;
}
/**
* Perform auto inflection on an English word.
*
* @param string $value
* @param array $source
* @param array $irregular
* @return string
*/
protected function auto($value, $source, $irregular)
{
// If the word hasn't been cached, we'll check the list of words that
// that are "uncountable". This should be a quick look up since we
// can just hit the array directly for the value.
if (in_array(strtolower($value), $this->config['uncountable']))
{
return $value;
}
// Next we will check the "irregular" patterns, which contains words
// like "children" and "teeth" which can not be inflected using the
// typically used regular expression matching approach.
foreach ($irregular as $irregular => $pattern)
{
if (preg_match($pattern = '/'.$pattern.'$/i', $value))
{
return preg_replace($pattern, $irregular, $value);
}
}
// Finally we'll spin through the array of regular expressions and
// and look for matches for the word. If we find a match we will
// cache and return the inflected value for quick look up.
foreach ($source as $pattern => $inflected)
{
if (preg_match($pattern, $value))
{
return preg_replace($pattern, $inflected, $value);
}
}
}
}
\ No newline at end of file
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
class Str { class Str {
/**
* The pluralizer instance.
*
* @var Pluralizer
*/
public static $pluralizer;
/** /**
* Get the default string encoding for the application. * Get the default string encoding for the application.
* *
...@@ -154,25 +161,17 @@ class Str { ...@@ -154,25 +161,17 @@ class Str {
/** /**
* Get the singular form of the given word. * Get the singular form of the given word.
* *
* The word should be defined in the "strings" configuration file.
*
* @param string $value * @param string $value
* @return string * @return string
*/ */
public static function singular($value) public static function singular($value)
{ {
$inflection = Config::get('strings.inflection'); return static::pluralizer()->singular($value);
$singular = array_get(array_flip($inflection), strtolower($value), $value);
return (ctype_upper($value[0])) ? static::title($singular) : $singular;
} }
/** /**
* Get the plural form of the given word. * Get the plural form of the given word.
* *
* The word should be defined in the "strings" configuration file.
*
* <code> * <code>
* // Returns the plural form of "child" * // Returns the plural form of "child"
* $plural = Str::plural('child', 10); * $plural = Str::plural('child', 10);
...@@ -187,11 +186,19 @@ class Str { ...@@ -187,11 +186,19 @@ class Str {
*/ */
public static function plural($value, $count = 2) public static function plural($value, $count = 2)
{ {
if ((int) $count == 1) return $value; return static::pluralizer()->plural($value, $count);
}
$plural = array_get(Config::get('strings.inflection'), strtolower($value), $value); /**
* Get the pluralizer instance.
*
* @return Pluralizer
*/
protected static function pluralizer()
{
$config = Config::get('strings');
return (ctype_upper($value[0])) ? static::title($plural) : $plural; return static::$pluralizer ?: static::$pluralizer = new Pluralizer($config);
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment