diff --git a/system/languages/en.yaml b/system/languages/en.yaml
new file mode 100644
index 000000000..7ee1ca42b
--- /dev/null
+++ b/system/languages/en.yaml
@@ -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'
+
+
diff --git a/system/src/Grav/Common/GPM/GPM.php b/system/src/Grav/Common/GPM/GPM.php
index a6eefce5a..049f0ec8c 100644
--- a/system/src/Grav/Common/GPM/GPM.php
+++ b/system/src/Grav/Common/GPM/GPM.php
@@ -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]);
diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php
index c145192e4..2bcb9e9cd 100644
--- a/system/src/Grav/Common/Grav.php
+++ b/system/src/Grav/Common/Grav.php
@@ -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;
diff --git a/system/src/Grav/Common/Inflector.php b/system/src/Grav/Common/Inflector.php
index d707448c4..2c89f7313 100644
--- a/system/src/Grav/Common/Inflector.php
+++ b/system/src/Grav/Common/Inflector.php
@@ -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();
diff --git a/system/src/Grav/Common/Language/Language.php b/system/src/Grav/Common/Language/Language.php
index 9069c2a10..6c890b1bc 100644
--- a/system/src/Grav/Common/Language/Language.php
+++ b/system/src/Grav/Common/Language/Language.php
@@ -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 '' . $lookup . '';
+ if ($html_out) {
+ return '' . $lookup . '';
+ } 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 '' . $key . '[' . $index . ']';
+ if ($html_out) {
+ return '' . $key . '[' . $index . ']';
+ } 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);
}
diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php
index 77a2afa2e..dd5fb74a0 100644
--- a/system/src/Grav/Common/Plugins.php
+++ b/system/src/Grav/Common/Plugins.php
@@ -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;
diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php
index b27a32c87..516a9d2fb 100644
--- a/system/src/Grav/Common/Themes.php
+++ b/system/src/Grav/Common/Themes.php
@@ -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;
diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php
index f2cba017f..1e8ef609c 100644
--- a/system/src/Grav/Common/Twig/TwigExtension.php
+++ b/system/src/Grav/Common/Twig/TwigExtension.php
@@ -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;