changed Inflector from static to class + added multilang support

This commit is contained in:
Andy Miller
2015-07-24 10:26:54 -06:00
parent bd08d787f2
commit 16f779c8f5
8 changed files with 147 additions and 131 deletions

58
system/languages/en.yaml Normal file
View File

@@ -0,0 +1,58 @@
INFLECTOR_PLURALS:
'/(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)ies$/i': '\1y'
'/([^aeiouy]|qu)y$/i': '\1ies'
'/(hive)$/i': '\1s'
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
'/sis$/i': 'ses'
'/([ti])um$/i': '\1a'
'/(buffal|tomat)o$/i': '\1oes'
'/(bu)s$/i': '\1ses'
'/(alias|status)/i': '\1es'
'/(octop|vir)us$/i': '\1i'
'/(ax|test)is$/i': '\1es'
'/s$/i': 's'
'/$/': 's'
INFLECTOR_SINGULAR:
'/(quiz)zes$/i': '\1'
'/(matr)ices$/i': '\1ix'
'/(vert|ind)ices$/i': '\1ex'
'/^(ox)en/i': '\1'
'/(alias|status)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'
'/([^f])ves$/i': '\1fe'
'/(^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'
'/s$/i': ''
INFLECTOR_UNCOUNTABLE: ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep']
INFLECTOR_IRREGULAR:
'person': 'people'
'man': 'men'
'child': 'children'
'sex': 'sexes'
'move': 'moves'
INFLECTOR_ORDINALS:
'default': 'th'
'first': 'st'
'second': 'nd'
'third': 'rd'

View File

@@ -349,6 +349,8 @@ class GPM extends Iterator
public function findPackages($searches = [])
{
$packages = ['total' => 0, 'not_found' => []];
$inflector = $this->grav['inflector'];
foreach ($searches as $search) {
$repository = '';
@@ -380,7 +382,7 @@ class GPM extends Iterator
}
$not_found = new \stdClass();
$not_found->name = Inflector::camelize($search);
$not_found->name = $inflector->camelize($search);
$not_found->slug = $search;
$not_found->package_type = $type;
$not_found->install_path = str_replace('%name%', $search, $this->install_paths[$type]);

View File

@@ -159,6 +159,8 @@ class Grav extends Container
$container->register(new StreamsServiceProvider);
$container->register(new ConfigServiceProvider);
$container['inflector'] = new Inflector();
$container['debugger']->stopTimer('_init');
return $container;

View File

@@ -4,6 +4,7 @@ namespace Grav\Common;
/**
* This file was originally part of the Akelos Framework
*/
use Grav\Common\Language\Language;
/**
* Inflector for pluralize and singularize English nouns.
@@ -20,65 +21,55 @@ namespace Grav\Common;
class Inflector
{
use GravTrait;
protected $plural;
protected $singular;
protected $uncountable;
protected $irregular;
protected $ordinals;
public function init()
{
if (empty($this->plural)) {
$language = self::getGrav()['language'];
$this->plural = $language->translate('INFLECTOR_PLURALS', null, true);
$this->singular = $language->translate('INFLECTOR_SINGULAR', null, true);
$this->uncountable = $language->translate('INFLECTOR_UNCOUNTABLE', null, true);
$this->irregular = $language->translate('INFLECTOR_IRREGULAR', null, true);
$this->ordinals = $language->translate('INFLECTOR_ORDINALS', null, true);
}
}
/**
* Pluralizes English nouns.
*
* @access static public
* @static
* @param string $word English noun to pluralize
* @return string Plural noun
*/
public static function pluralize($word, $count = 2)
public function pluralize($word, $count = 2)
{
$this->init();
if ($count == 1) {
return $word;
}
$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)ies$/i' => '\1y',
'/([^aeiouy]|qu)y$/i' => '\1ies',
'/(hive)$/i' => '\1s',
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
'/sis$/i' => 'ses',
'/([ti])um$/i' => '\1a',
'/(buffal|tomat)o$/i' => '\1oes',
'/(bu)s$/i' => '\1ses',
'/(alias|status)/i'=> '\1es',
'/(octop|vir)us$/i'=> '\1i',
'/(ax|test)is$/i'=> '\1es',
'/s$/i'=> 's',
'/$/'=> 's');
$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
$irregular = array(
'person' => 'people',
'man' => 'men',
'child' => 'children',
'sex' => 'sexes',
'move' => 'moves');
$lowercased_word = strtolower($word);
foreach ($uncountable as $_uncountable) {
foreach ($this->uncountable as $_uncountable) {
if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($irregular as $_plural => $_singular) {
foreach ($this->irregular as $_plural => $_singular) {
if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
return preg_replace('/('.$_plural.')$/i', substr($arr[0], 0, 1).substr($_singular, 1), $word);
}
}
foreach ($plural as $rule => $replacement) {
foreach ($this->plural as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
}
@@ -94,62 +85,26 @@ class Inflector
* @param int $count
* @return string Singular noun.
*/
public static function singularize($word, $count = 1)
public function singularize($word, $count = 1)
{
if ($count != 1) {
return $word;
}
$singular = array (
'/(quiz)zes$/i' => '\1',
'/(matr)ices$/i' => '\1ix',
'/(vert|ind)ices$/i' => '\1ex',
'/^(ox)en/i' => '\1',
'/(alias|status)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',
'/([^f])ves$/i' => '\1fe',
'/(^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',
'/s$/i' => '',
);
$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
$irregular = array(
'person' => 'people',
'man' => 'men',
'child' => 'children',
'sex' => 'sexes',
'move' => 'moves');
$lowercased_word = strtolower($word);
foreach ($uncountable as $_uncountable) {
foreach ($this->uncountable as $_uncountable) {
if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($irregular as $_plural => $_singular) {
foreach ($this->irregular as $_plural => $_singular) {
if (preg_match('/('.$_singular.')$/i', $word, $arr)) {
return preg_replace('/('.$_singular.')$/i', substr($arr[0], 0, 1).substr($_plural, 1), $word);
}
}
foreach ($singular as $rule => $replacement) {
foreach ($this->singular as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
}
@@ -162,24 +117,22 @@ class Inflector
* Converts an underscored or CamelCase word into a English
* sentence.
*
* The titleize static public function converts text like "WelcomePage",
* The titleize public function converts text like "WelcomePage",
* "welcome_page" or "welcome page" to this "Welcome
* Page".
* If second parameter is set to 'first' it will only
* capitalize the first character of the title.
*
* @access static public
* @static
* @param string $word Word to format as tile
* @param string $uppercase If set to 'first' it will only uppercase the
* first character. Otherwise it will uppercase all
* the words in the title.
* @return string Text formatted as title
*/
public static function titleize($word, $uppercase = '')
public function titleize($word, $uppercase = '')
{
$uppercase = $uppercase == 'first' ? 'ucfirst' : 'ucwords';
return $uppercase(static::humanize(static::underscorize($word)));
return $uppercase($this->humanize($this->underscorize($word)));
}
/**
@@ -189,13 +142,11 @@ class Inflector
* will remove non alphanumeric character from the word, so
* "who's online" will be converted to "WhoSOnline"
*
* @access static public
* @static
* @see variablize
* @param string $word Word to convert to camel case
* @return string UpperCamelCasedWord
*/
public static function camelize($word)
public function camelize($word)
{
return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
}
@@ -208,12 +159,10 @@ class Inflector
*
* This can be really useful for creating friendly URLs.
*
* @access static public
* @static
* @param string $word Word to underscore
* @return string Underscored word
*/
public static function underscorize($word)
public function underscorize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
@@ -229,12 +178,10 @@ class Inflector
*
* This can be really useful for creating friendly URLs.
*
* @access static public
* @static
* @param string $word Word to hyphenate
* @return string hyphenized word
*/
public static function hyphenize($word)
public function hyphenize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1-\2', $regex1);
@@ -252,14 +199,12 @@ class Inflector
* If you need to uppercase all the words you just have to
* pass 'all' as a second parameter.
*
* @access static public
* @static
* @param string $word String to "humanize"
* @param string $uppercase If set to 'all' it will uppercase all the words
* instead of just the first one.
* @return string Human-readable word
*/
public static function humanize($word, $uppercase = '')
public function humanize($word, $uppercase = '')
{
$uppercase = $uppercase == 'all' ? 'ucwords' : 'ucfirst';
return $uppercase(str_replace('_', ' ', preg_replace('/_id$/', '', $word)));
@@ -272,15 +217,13 @@ class Inflector
* will remove non alphanumeric character from the word, so
* "who's online" will be converted to "whoSOnline"
*
* @access static public
* @static
* @see camelize
* @param string $word Word to lowerCamelCase
* @return string Returns a lowerCamelCasedWord
*/
public static function variablize($word)
public function variablize($word)
{
$word = static::camelize($word);
$word = $this->camelize($word);
return strtolower($word[0]).substr($word, 1);
}
@@ -290,15 +233,13 @@ class Inflector
*
* Converts "Person" to "people"
*
* @access static public
* @static
* @see classify
* @param string $class_name Class name for getting related table_name.
* @return string plural_table_name
*/
public static function tableize($class_name)
public function tableize($class_name)
{
return static::pluralize(static::underscore($class_name));
return $this->pluralize($this->underscore($class_name));
}
/**
@@ -307,15 +248,13 @@ class Inflector
*
* Converts "people" to "Person"
*
* @access static public
* @static
* @see tableize
* @param string $table_name Table name for getting related ClassName.
* @return string SingularClassName
*/
public static function classify($table_name)
public function classify($table_name)
{
return static::camelize(static::singularize($table_name));
return $this->camelize($this->singularize($table_name));
}
/**
@@ -323,34 +262,32 @@ class Inflector
*
* This method converts 13 to 13th, 2 to 2nd ...
*
* @access static public
* @static
* @param integer $number Number to get its ordinal value
* @return string Ordinal representation of given string.
*/
public static function ordinalize($number)
public function ordinalize($number)
{
if (in_array(($number % 100), range(11, 13))) {
return $number.'th';
return $number.$this->ordinals['default'];
} else {
switch (($number % 10)) {
case 1:
return $number.'st';
return $number.$this->ordinals['first'];
break;
case 2:
return $number.'nd';
return $number.$this->ordinals['second'];
break;
case 3:
return $number.'rd';
return $number.$this->ordinals['third'];
break;
default:
return $number.'th';
return $number.$this->ordinals['default'];
break;
}
}
}
public static function monthize($days)
public function monthize($days)
{
$now = new \DateTime();
$end = new \DateTime();

View File

@@ -276,13 +276,15 @@ class Language
/**
* Translate a key and possibly arguments into a string using current lang and fallbacks
*
* @param $args first argument is the lookup key value
* other arguments can be passed and replaced in the translation with sprintf syntax
* @param $args first argument is the lookup key value
* other arguments can be passed and replaced in the translation with sprintf syntax
* @param Array $languages
* @param bool $array_support
* @param bool $html_out
*
* @return string
*/
public function translate($args, Array $languages = null)
public function translate($args, Array $languages = null, $array_support = false, $html_out = false)
{
if (is_array($args)) {
$lookup = array_shift($args);
@@ -306,7 +308,7 @@ class Language
}
foreach ((array)$languages as $lang) {
$translation = $this->getTranslation($lang, $lookup);
$translation = $this->getTranslation($lang, $lookup, $array_support);
if ($translation) {
if (count($args) >= 1) {
@@ -318,7 +320,11 @@ class Language
}
}
return '<span class="untranslated">' . $lookup . '</span>';
if ($html_out) {
return '<span class="untranslated">' . $lookup . '</span>';
} else {
return $lookup;
}
}
/**
@@ -327,10 +333,11 @@ class Language
* @param $key
* @param $index
* @param null $languages
* @param bool $html_out
*
* @return string
*/
public function translateArray($key, $index, $languages = null)
public function translateArray($key, $index, $languages = null, $html_out = false)
{
if ($this->config->get('system.languages.translations', true)) {
if ($this->enabled() && $key) {
@@ -353,21 +360,26 @@ class Language
}
}
return '<span class="untranslated">' . $key . '[' . $index . ']</span>';
if ($html_out) {
return '<span class="untranslated">' . $key . '[' . $index . ']</span>';
} else {
return $key . '[' . $index . ']';
}
}
/**
* Lookup the translation text for a given lang and key
*
* @param $lang lang code
* @param $key key to lookup with
* @param $lang lang code
* @param $key key to lookup with
* @param bool $array_support
*
* @return string
*/
public function getTranslation($lang, $key)
public function getTranslation($lang, $key, $array_support = false)
{
$translation = $this->config->getLanguages()->get($lang . '.' . $key, null);
if (is_array($translation)) {
if (!$array_support && is_array($translation)) {
return (string)array_shift($translation);
}

View File

@@ -32,6 +32,8 @@ class Plugins extends Iterator
$config = self::getGrav()['config'];
$plugins = (array) $config->get('plugins');
$inflector = self::getGrav()['inflector'];
/** @var EventDispatcher $events */
$events = self::getGrav()['events'];
@@ -52,7 +54,7 @@ class Plugins extends Iterator
$pluginClassFormat = [
'Grav\\Plugin\\'.ucfirst($plugin).'Plugin',
'Grav\\Plugin\\'.Inflector::camelize($plugin).'Plugin'
'Grav\\Plugin\\'.$inflector->camelize($plugin).'Plugin'
];
$pluginClassName = false;

View File

@@ -141,15 +141,16 @@ class Themes extends Iterator
$locator = $grav['locator'];
$file = $locator('theme://theme.php') ?: $locator("theme://{$name}.php");
$inflector = $grav['inflector'];
if ($file) {
// Local variables available in the file: $grav, $config, $name, $file
$class = include $file;
if (!is_object($class)) {
$themeClassFormat = [
'Grav\\Theme\\'.ucfirst($name),
'Grav\\Theme\\'.Inflector::camelize($name)
'Grav\\Theme\\'.$inflector->camelize($name)
];
$themeClassName = false;

View File

@@ -194,16 +194,18 @@ class TwigExtension extends \Twig_Extension
// TODO: check this and fix the docblock if needed.
$action = $action.'ize';
$inflector = $this->grav['inflector'];
if (in_array(
$action,
['titleize','camelize','underscorize','hyphenize', 'humanize','ordinalize','monthize']
)) {
return Inflector::$action($data);
return $inflector->$action($data);
} elseif (in_array($action, ['pluralize','singularize'])) {
if ($count) {
return Inflector::$action($data, $count);
return $inflector->$action($data, $count);
} else {
return Inflector::$action($data);
return $inflector->$action($data);
}
} else {
return $data;