diff --git a/composer.json b/composer.json index 5a1c0b4cb583..1f345cfddad7 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,6 @@ "symfony/http-kernel": "3.2.*", "symfony/process": "3.2.*", "symfony/routing": "3.2.*", - "symfony/translation": "3.2.*", "symfony/var-dumper": "3.2.*", "vlucas/phpdotenv": "~2.2" }, diff --git a/src/Illuminate/Contracts/Translation/Translator.php b/src/Illuminate/Contracts/Translation/Translator.php new file mode 100644 index 000000000000..9a8cf4b560f8 --- /dev/null +++ b/src/Illuminate/Contracts/Translation/Translator.php @@ -0,0 +1,42 @@ + ['Illuminate\Contracts\Filesystem\Filesystem'], 'filesystem.cloud' => ['Illuminate\Contracts\Filesystem\Cloud'], 'hash' => ['Illuminate\Contracts\Hashing\Hasher'], - 'translator' => ['Illuminate\Translation\Translator', 'Symfony\Component\Translation\TranslatorInterface'], + 'translator' => ['Illuminate\Translation\Translator', 'Illuminate\Contracts\Translation\Translator'], 'log' => ['Illuminate\Log\Writer', 'Illuminate\Contracts\Logging\Log', 'Psr\Log\LoggerInterface'], 'mailer' => ['Illuminate\Mail\Mailer', 'Illuminate\Contracts\Mail\Mailer', 'Illuminate\Contracts\Mail\MailQueue'], 'auth.password' => ['Illuminate\Auth\Passwords\PasswordBrokerManager', 'Illuminate\Contracts\Auth\PasswordBrokerFactory'], diff --git a/src/Illuminate/Foundation/helpers.php b/src/Illuminate/Foundation/helpers.php index 10240934ed23..651b8de4d157 100644 --- a/src/Illuminate/Foundation/helpers.php +++ b/src/Illuminate/Foundation/helpers.php @@ -762,18 +762,17 @@ function storage_path($path = '') * Translate the given message. * * @param string $id - * @param array $parameters - * @param string $domain + * @param array $replace * @param string $locale - * @return \Symfony\Component\Translation\TranslatorInterface|string + * @return \Illuminate\Contracts\Translation\Translator|string */ - function trans($id = null, $parameters = [], $domain = 'messages', $locale = null) + function trans($id = null, $replace = [], $locale = null) { if (is_null($id)) { return app('translator'); } - return app('translator')->trans($id, $parameters, $domain, $locale); + return app('translator')->trans($id, $replace, $locale); } } @@ -783,14 +782,13 @@ function trans($id = null, $parameters = [], $domain = 'messages', $locale = nul * * @param string $id * @param int|array|\Countable $number - * @param array $parameters - * @param string $domain + * @param array $replace * @param string $locale * @return string */ - function trans_choice($id, $number, array $parameters = [], $domain = 'messages', $locale = null) + function trans_choice($id, $number, array $replace = [], $locale = null) { - return app('translator')->transChoice($id, $number, $parameters, $domain, $locale); + return app('translator')->transChoice($id, $number, $replace, $locale); } } diff --git a/src/Illuminate/Translation/MessageSelector.php b/src/Illuminate/Translation/MessageSelector.php new file mode 100755 index 000000000000..4fec5d524950 --- /dev/null +++ b/src/Illuminate/Translation/MessageSelector.php @@ -0,0 +1,93 @@ +extract($parts, $number)) !== null) { + return trim($value); + } + + $parts = $this->stripConditions($parts); + + return count($parts) == 1 || $number == 1 + ? $parts[0] : $parts[1]; + } + + /** + * Extract a translation string using inline conditions. + * + * @param array $parts + * @param int $number + * @return mixed + */ + private function extract($parts, $number) + { + foreach ($parts as $part) { + if (($line = $this->extractFromString($part, $number)) !== null) { + return $line; + } + } + } + + /** + * Get the translation string if the condition matches. + * + * @param string $part + * @param int $number + * @return mixed + */ + private function extractFromString($part, $number) + { + preg_match('/^[\{\[]([^\[\]\{\}]*)[\}\]](.*)/s', $part, $matches); + + if (count($matches) != 3) { + return; + } + + $condition = $matches[1]; + + $value = $matches[2]; + + if (Str::contains($condition, ',')) { + list($from, $to) = explode(',', $condition, 2); + + if ($to == '*' && $number >= $from) { + return $value; + } elseif ($from == '*' && $number <= $to) { + return $value; + } elseif ($number >= $from && $number <= $to) { + return $value; + } + } + + return $condition == $number ? $value : null; + } + + /** + * Strip the inline condition. + * + * @param array $parts + * @return array + */ + private function stripConditions($parts) + { + return Collection::make($parts)->map(function ($part) { + return preg_replace('/^[\{\[]([^\[\]\{\}]*)[\}\]]/', '', $part); + })->toArray(); + } +} diff --git a/src/Illuminate/Translation/Translator.php b/src/Illuminate/Translation/Translator.php index 6793e15bed94..2e83718c57c6 100755 --- a/src/Illuminate/Translation/Translator.php +++ b/src/Illuminate/Translation/Translator.php @@ -7,10 +7,9 @@ use Illuminate\Support\Collection; use Illuminate\Support\Traits\Macroable; use Illuminate\Support\NamespacedItemResolver; -use Symfony\Component\Translation\MessageSelector; -use Symfony\Component\Translation\TranslatorInterface; +use Illuminate\Contracts\Translation\Translator as TranslatorContract; -class Translator extends NamespacedItemResolver implements TranslatorInterface +class Translator extends NamespacedItemResolver implements TranslatorContract { use Macroable; @@ -45,7 +44,7 @@ class Translator extends NamespacedItemResolver implements TranslatorInterface /** * The message selector. * - * @var \Symfony\Component\Translation\MessageSelector + * @var \Illuminate\Translation\MessageSelector */ protected $selector; @@ -225,30 +224,28 @@ public function choice($key, $number, array $replace = [], $locale = null) /** * Get the translation for a given key. * - * @param string $id - * @param array $parameters - * @param string $domain + * @param string $key + * @param array $replace * @param string $locale * @return string|array|null */ - public function trans($id, array $parameters = [], $domain = 'messages', $locale = null) + public function trans($key, array $replace = [], $locale = null) { - return $this->get($id, $parameters, $locale); + return $this->get($key, $replace, $locale); } /** * Get a translation according to an integer value. * - * @param string $id + * @param string $key * @param int|array|\Countable $number - * @param array $parameters - * @param string $domain + * @param array $replace * @param string $locale * @return string */ - public function transChoice($id, $number, array $parameters = [], $domain = 'messages', $locale = null) + public function transChoice($key, $number, array $replace = [], $locale = null) { - return $this->choice($id, $number, $parameters, $locale); + return $this->choice($key, $number, $replace, $locale); } /** @@ -329,7 +326,7 @@ protected function parseLocale($locale) /** * Get the message selector instance. * - * @return \Symfony\Component\Translation\MessageSelector + * @return \Illuminate\Translation\MessageSelector */ public function getSelector() { @@ -343,7 +340,7 @@ public function getSelector() /** * Set the message selector instance. * - * @param \Symfony\Component\Translation\MessageSelector $selector + * @param \Illuminate\Translation\MessageSelector $selector * @return void */ public function setSelector(MessageSelector $selector) diff --git a/src/Illuminate/Translation/composer.json b/src/Illuminate/Translation/composer.json index 209914c43e17..29bcaf10e270 100755 --- a/src/Illuminate/Translation/composer.json +++ b/src/Illuminate/Translation/composer.json @@ -16,8 +16,7 @@ "require": { "php": ">=5.6.4", "illuminate/filesystem": "5.4.*", - "illuminate/support": "5.4.*", - "symfony/translation": "3.2.*" + "illuminate/support": "5.4.*" }, "autoload": { "psr-4": { diff --git a/src/Illuminate/Validation/Factory.php b/src/Illuminate/Validation/Factory.php index 1b61f73a3a80..734d81504ea0 100755 --- a/src/Illuminate/Validation/Factory.php +++ b/src/Illuminate/Validation/Factory.php @@ -5,7 +5,7 @@ use Closure; use Illuminate\Support\Str; use Illuminate\Contracts\Container\Container; -use Symfony\Component\Translation\TranslatorInterface; +use Illuminate\Contracts\Translation\Translator; use Illuminate\Contracts\Validation\Factory as FactoryContract; class Factory implements FactoryContract @@ -13,7 +13,7 @@ class Factory implements FactoryContract /** * The Translator implementation. * - * @var \Symfony\Component\Translation\TranslatorInterface + * @var \Illuminate\Contracts\Translation\Translator */ protected $translator; @@ -69,11 +69,11 @@ class Factory implements FactoryContract /** * Create a new Validator factory instance. * - * @param \Symfony\Component\Translation\TranslatorInterface $translator + * @param \Illuminate\Contracts\Translation\Translator $translator * @param \Illuminate\Contracts\Container\Container $container * @return void */ - public function __construct(TranslatorInterface $translator, Container $container = null) + public function __construct(Translator $translator, Container $container = null) { $this->container = $container; $this->translator = $translator; @@ -227,7 +227,7 @@ public function resolver(Closure $resolver) /** * Get the Translator implementation. * - * @return \Symfony\Component\Translation\TranslatorInterface + * @return \Illuminate\Contracts\Translation\Translator */ public function getTranslator() { diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 821503762aa4..692c62e91e40 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -17,7 +17,7 @@ use Illuminate\Support\MessageBag; use Illuminate\Contracts\Container\Container; use Symfony\Component\HttpFoundation\File\File; -use Symfony\Component\Translation\TranslatorInterface; +use Illuminate\Contracts\Translation\Translator; use Symfony\Component\HttpFoundation\File\UploadedFile; use Illuminate\Contracts\Validation\Validator as ValidatorContract; @@ -26,7 +26,7 @@ class Validator implements ValidatorContract /** * The Translator implementation. * - * @var \Symfony\Component\Translation\TranslatorInterface + * @var \Illuminate\Contracts\Translation\Translator */ protected $translator; @@ -190,14 +190,14 @@ class Validator implements ValidatorContract /** * Create a new Validator instance. * - * @param \Symfony\Component\Translation\TranslatorInterface $translator + * @param \Illuminate\Contracts\Translation\Translator $translator * @param array $data * @param array $rules * @param array $messages * @param array $customAttributes * @return void */ - public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = []) + public function __construct(Translator $translator, array $data, array $rules, array $messages = [], array $customAttributes = []) { $this->initialRules = $rules; $this->translator = $translator; @@ -3126,7 +3126,7 @@ public function setPresenceVerifier(PresenceVerifierInterface $presenceVerifier) /** * Get the Translator implementation. * - * @return \Symfony\Component\Translation\TranslatorInterface + * @return \Illuminate\Contracts\Translation\Translator */ public function getTranslator() { @@ -3136,10 +3136,10 @@ public function getTranslator() /** * Set the Translator implementation. * - * @param \Symfony\Component\Translation\TranslatorInterface $translator + * @param \Illuminate\Contracts\Translation\Translator $translator * @return void */ - public function setTranslator(TranslatorInterface $translator) + public function setTranslator(Translator $translator) { $this->translator = $translator; } diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index 2d6f90716c96..a3526b6f3204 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -18,8 +18,7 @@ "illuminate/container": "5.4.*", "illuminate/contracts": "5.4.*", "illuminate/support": "5.4.*", - "symfony/http-foundation": "3.2.*", - "symfony/translation": "3.2.*" + "symfony/http-foundation": "3.2.*" }, "autoload": { "psr-4": { diff --git a/tests/Translation/TranslationMessageSelectorTest.php b/tests/Translation/TranslationMessageSelectorTest.php new file mode 100755 index 000000000000..073009c6252c --- /dev/null +++ b/tests/Translation/TranslationMessageSelectorTest.php @@ -0,0 +1,66 @@ +assertEquals($expected, $selector->choose($id, $number)); + } + + public function chooseTestData() + { + return [ + ['first', 'first', 1], + ['first', 'first', 10], + ['first', 'first|second', 1], + ['second', 'first|second', 10], + ['second', 'first|second', 0], + + ['first', '{0} first|{1}second', 0], + ['first', '{1}first|{2}second', 1], + ['second', '{1}first|{2}second', 2], + ['first', '{2}first|{1}second', 2], + ['second', '{9}first|{10}second', 0], + ['first', '{9}first|{10}second', 1], + ['', '{0}|{1}second', 0], + ['', '{0}first|{1}', 1], + ['first', '{1.3}first|{2.3}second', 1.3], + ['second', '{1.3}first|{2.3}second', 2.3], + ['first + line', '{1}first + line|{2}second', 1], + ["first \n + line", "{1}first \n + line|{2}second", 1], + + ['first', '{0} first|[1,9]second', 0], + ['second', '{0}first|[1,9]second', 1], + ['second', '{0}first|[1,9]second', 10], + ['first', '{0}first|[2,9]second', 1], + ['second', '[4,*]first|[1,3]second', 1], + ['first', '[4,*]first|[1,3]second', 100], + ['second', '[1,5]first|[6,10]second', 7], + ['first', '[*,4]first|[5,*]second', 1], + ['second', '[5,*]first|[*,4]second', 1], + ['second', '[5,*]first|[*,4]second', 0], + + ['first', '{0}first|[1,3]second|[4,*]third', 0], + ['second', '{0}first|[1,3]second|[4,*]third', 1], + ['third', '{0}first|[1,3]second|[4,*]third', 9], + + ['first', 'first|second|third', 1], + ['second', 'first|second|third', 9], + ['second', 'first|second|third', 0], + + ['first', '{0} first | { 1 } second', 0], + ['first', '[4,*]first | [1,3]second', 100], + ]; + } +} diff --git a/tests/Translation/TranslationTranslatorTest.php b/tests/Translation/TranslationTranslatorTest.php index 607ae48ed2a3..9296990e3c9e 100755 --- a/tests/Translation/TranslationTranslatorTest.php +++ b/tests/Translation/TranslationTranslatorTest.php @@ -74,7 +74,7 @@ public function testChoiceMethodProperlyLoadsAndRetrievesItem() { $t = $this->getMockBuilder('Illuminate\Translation\Translator')->setMethods(['get'])->setConstructorArgs([$this->getLoader(), 'en'])->getMock(); $t->expects($this->once())->method('get')->with($this->equalTo('foo'), $this->equalTo(['replace']), $this->equalTo('en'))->will($this->returnValue('line')); - $t->setSelector($selector = m::mock('Symfony\Component\Translation\MessageSelector')); + $t->setSelector($selector = m::mock('Illuminate\Translation\MessageSelector')); $selector->shouldReceive('choose')->once()->with('line', 10, 'en')->andReturn('choiced'); $t->choice('foo', 10, ['replace']); @@ -84,7 +84,7 @@ public function testChoiceMethodProperlyCountsCollectionsAndLoadsAndRetrievesIte { $t = $this->getMockBuilder('Illuminate\Translation\Translator')->setMethods(['get'])->setConstructorArgs([$this->getLoader(), 'en'])->getMock(); $t->expects($this->exactly(2))->method('get')->with($this->equalTo('foo'), $this->equalTo(['replace']), $this->equalTo('en'))->will($this->returnValue('line')); - $t->setSelector($selector = m::mock('Symfony\Component\Translation\MessageSelector')); + $t->setSelector($selector = m::mock('Illuminate\Translation\MessageSelector')); $selector->shouldReceive('choose')->twice()->with('line', 3, 'en')->andReturn('choiced'); $values = ['foo', 'bar', 'baz']; diff --git a/tests/Validation/ValidationFactoryTest.php b/tests/Validation/ValidationFactoryTest.php index 3fe978f348cb..cb8eade1b65a 100755 --- a/tests/Validation/ValidationFactoryTest.php +++ b/tests/Validation/ValidationFactoryTest.php @@ -4,7 +4,7 @@ use Illuminate\Validation\Factory; use Illuminate\Validation\Validator; use Illuminate\Validation\PresenceVerifierInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Illuminate\Contracts\Translation\Translator as TranslatorInterface; class ValidationFactoryTest extends PHPUnit_Framework_TestCase { diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index a8c6a540ab14..46946908c6c6 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -3196,7 +3196,7 @@ public function testValidMethod() protected function getTranslator() { - return m::mock('Symfony\Component\Translation\TranslatorInterface'); + return m::mock('Illuminate\Contracts\Translation\Translator'); } public function getIlluminateArrayTranslator()