diff --git a/src/Carbon/CarbonInterval.php b/src/Carbon/CarbonInterval.php index aab960eb3..dcfcaa721 100644 --- a/src/Carbon/CarbonInterval.php +++ b/src/Carbon/CarbonInterval.php @@ -41,6 +41,7 @@ use ReflectionException; use ReturnTypeWillChange; use RuntimeException; +use Symfony\Contracts\Translation\TranslatorInterface; use Throwable; /** @@ -1705,7 +1706,9 @@ protected function getForHumansParameters($syntax = null, $short = false, $parts ':optional-space' => $optionalSpace, ]; - return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip]; + $translator ??= isset($locale) ? Translator::get($locale) : null; + + return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip, $translator]; } protected static function getRoundingMethodFromOptions(int $options): ?string @@ -1822,7 +1825,9 @@ public function getValuesSequence(): array * ` - if $join is missing, a space will be used as glue * - 'minimumUnit' entry determines the smallest unit of time to display can be long or * ` short form of the units, e.g. 'hour' or 'h' (default value: s) - * if int passed, it add modifiers: + * - 'locale' language in which the diff should be output (has no effect if 'translator' key is set) + * - 'translator' a custom translator to use to translator the output. + * if int passed, it adds modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier @@ -1838,7 +1843,8 @@ public function getValuesSequence(): array */ public function forHumans($syntax = null, $short = false, $parts = self::NO_LIMIT, $options = null): string { - [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip] = $this + /* @var TranslatorInterface|null $translator */ + [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip, $translator] = $this ->getForHumansParameters($syntax, $short, $parts, $options); $interval = []; @@ -1852,8 +1858,7 @@ public function forHumans($syntax = null, $short = false, $parts = self::NO_LIMI $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before'); $declensionMode = null; - /** @var Translator $translator */ - $translator = $this->getLocalTranslator(); + $translator ??= $this->getLocalTranslator(); $handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) { if (!$absolute) { diff --git a/src/Carbon/Traits/Difference.php b/src/Carbon/Traits/Difference.php index 735fe8f5f..310607eb4 100644 --- a/src/Carbon/Traits/Difference.php +++ b/src/Carbon/Traits/Difference.php @@ -499,7 +499,9 @@ public function secondsUntilEndOfDay(): float * - 'other' entry (see above) * - 'minimumUnit' entry determines the smallest unit of time to display can be long or * ` short form of the units, e.g. 'hour' or 'h' (default value: s) - * if int passed, it add modifiers: + * - 'locale' language in which the diff should be output (has no effect if 'translator' key is set) + * - 'translator' a custom translator to use to translator the output. + * if int passed, it adds modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier diff --git a/src/Carbon/Traits/IntervalRounding.php b/src/Carbon/Traits/IntervalRounding.php index 24cac6943..e27c7bab7 100644 --- a/src/Carbon/Traits/IntervalRounding.php +++ b/src/Carbon/Traits/IntervalRounding.php @@ -42,7 +42,7 @@ protected function roundWith(DateInterval|string|float|int $precision, callable| $unit = 'second'; if ($precision instanceof DateInterval) { - $precision = (string) CarbonInterval::instance($precision)->locale(''); + $precision = CarbonInterval::instance($precision)->forHumans(['locale' => 'en']); } if (\is_string($precision) && preg_match('/^\s*(?\d+)?\s*(?\w+)(?\W.*)?$/', $precision, $match)) { diff --git a/tests/Carbon/LocalizationTest.php b/tests/Carbon/LocalizationTest.php index bce5fec51..0c2229241 100644 --- a/tests/Carbon/LocalizationTest.php +++ b/tests/Carbon/LocalizationTest.php @@ -14,6 +14,7 @@ namespace Tests\Carbon; use Carbon\Carbon; +use Carbon\CarbonInterface; use Carbon\CarbonInterval; use Carbon\Language; use Carbon\Translator; @@ -462,14 +463,44 @@ public function testAddCustomTranslation() // en_Boring inherit en because it starts with "en", see symfony-translation behavior $this->assertSame('3 boring days 4 hours', $diff); + Carbon::setLocale('en'); + + $diff = Carbon::parse('2018-01-01') + ->diffForHumans('2018-01-04 04:00', [ + 'syntax' => CarbonInterface::DIFF_ABSOLUTE, + 'parts' => 2, + 'locale' => 'de', + ]); + + $this->assertSame('3 Tage 4 Stunden', $diff); + $translator->resetMessages(); $this->assertSame([], $translator->getMessages()); - Carbon::setLocale('en'); $this->assertSame('en', Carbon::getLocale()); } + public function testLocaleOption() + { + $translator = Translator::get('en_Boring'); + $translator->setTranslations([ + 'day' => ':count boring day|:count boring days', + ]); + + $diff = Carbon::parse('2018-01-01') + ->diffForHumans('2018-01-04 04:00', [ + 'syntax' => CarbonInterface::DIFF_ABSOLUTE, + 'parts' => 2, + 'locale' => 'en_Boring', + ]); + + $translator->setLocale('en'); + $translator->resetMessages(); + + $this->assertSame('3 boring days 4 hours', $diff); + } + public function testCustomWeekStart() { Carbon::setLocale('ru');