| <?php |
| |
| /** |
| * This file is part of the Carbon package. |
| * |
| * (c) Brian Nesbitt <brian@nesbot.com> |
| * |
| * For the full copyright and license information, please view the LICENSE |
| * file that was distributed with this source code. |
| */ |
| namespace Carbon\Traits; |
| |
| use Carbon\CarbonInterface; |
| use Carbon\Exceptions\InvalidTypeException; |
| use Carbon\Exceptions\NotLocaleAwareException; |
| use Carbon\Language; |
| use Carbon\Translator; |
| use Closure; |
| use Symfony\Component\Translation\TranslatorBagInterface; |
| use Symfony\Component\Translation\TranslatorInterface; |
| use Symfony\Contracts\Translation\LocaleAwareInterface; |
| use Symfony\Contracts\Translation\TranslatorInterface as ContractsTranslatorInterface; |
| |
| if (!interface_exists('Symfony\\Component\\Translation\\TranslatorInterface')) { |
| class_alias( |
| 'Symfony\\Contracts\\Translation\\TranslatorInterface', |
| 'Symfony\\Component\\Translation\\TranslatorInterface' |
| ); |
| } |
| |
| /** |
| * Trait Localization. |
| * |
| * Embed default and locale translators and translation base methods. |
| */ |
| trait Localization |
| { |
| /** |
| * Default translator. |
| * |
| * @var \Symfony\Component\Translation\TranslatorInterface |
| */ |
| protected static $translator; |
| |
| /** |
| * Specific translator of the current instance. |
| * |
| * @var \Symfony\Component\Translation\TranslatorInterface |
| */ |
| protected $localTranslator; |
| |
| /** |
| * Options for diffForHumans(). |
| * |
| * @var int |
| */ |
| protected static $humanDiffOptions = CarbonInterface::NO_ZERO_DIFF; |
| |
| /** |
| * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. |
| * You should rather use the ->settings() method. |
| * @see settings |
| * |
| * @param int $humanDiffOptions |
| */ |
| public static function setHumanDiffOptions($humanDiffOptions) |
| { |
| static::$humanDiffOptions = $humanDiffOptions; |
| } |
| |
| /** |
| * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. |
| * You should rather use the ->settings() method. |
| * @see settings |
| * |
| * @param int $humanDiffOption |
| */ |
| public static function enableHumanDiffOption($humanDiffOption) |
| { |
| static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption; |
| } |
| |
| /** |
| * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. |
| * You should rather use the ->settings() method. |
| * @see settings |
| * |
| * @param int $humanDiffOption |
| */ |
| public static function disableHumanDiffOption($humanDiffOption) |
| { |
| static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption; |
| } |
| |
| /** |
| * Return default humanDiff() options (merged flags as integer). |
| * |
| * @return int |
| */ |
| public static function getHumanDiffOptions() |
| { |
| return static::$humanDiffOptions; |
| } |
| |
| /** |
| * Get the default translator instance in use. |
| * |
| * @return \Symfony\Component\Translation\TranslatorInterface |
| */ |
| public static function getTranslator() |
| { |
| return static::translator(); |
| } |
| |
| /** |
| * Set the default translator instance to use. |
| * |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator |
| * |
| * @return void |
| */ |
| public static function setTranslator(TranslatorInterface $translator) |
| { |
| static::$translator = $translator; |
| } |
| |
| /** |
| * Return true if the current instance has its own translator. |
| * |
| * @return bool |
| */ |
| public function hasLocalTranslator() |
| { |
| return isset($this->localTranslator); |
| } |
| |
| /** |
| * Get the translator of the current instance or the default if none set. |
| * |
| * @return \Symfony\Component\Translation\TranslatorInterface |
| */ |
| public function getLocalTranslator() |
| { |
| return $this->localTranslator ?: static::translator(); |
| } |
| |
| /** |
| * Set the translator for the current instance. |
| * |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator |
| * |
| * @return $this |
| */ |
| public function setLocalTranslator(TranslatorInterface $translator) |
| { |
| $this->localTranslator = $translator; |
| |
| return $this; |
| } |
| |
| /** |
| * Returns raw translation message for a given key. |
| * |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use |
| * @param string $key key to find |
| * @param string|null $locale current locale used if null |
| * @param string|null $default default value if translation returns the key |
| * |
| * @return string |
| */ |
| public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) |
| { |
| if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) { |
| throw new InvalidTypeException( |
| 'Translator does not implement '.TranslatorInterface::class.' and '.TranslatorBagInterface::class.'. '. |
| (\is_object($translator) ? \get_class($translator) : \gettype($translator)).' has been given.' |
| ); |
| } |
| |
| if (!$locale && $translator instanceof LocaleAwareInterface) { |
| $locale = $translator->getLocale(); |
| } |
| |
| $result = $translator->getCatalogue($locale)->get($key); |
| |
| return $result === $key ? $default : $result; |
| } |
| |
| /** |
| * Returns raw translation message for a given key. |
| * |
| * @param string $key key to find |
| * @param string|null $locale current locale used if null |
| * @param string|null $default default value if translation returns the key |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use |
| * |
| * @return string |
| */ |
| public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null) |
| { |
| return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default); |
| } |
| |
| /** |
| * Translate using translation string or callback available. |
| * |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator |
| * @param string $key |
| * @param array $parameters |
| * @param null $number |
| * |
| * @return string |
| */ |
| public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string |
| { |
| $message = static::getTranslationMessageWith($translator, $key, null, $key); |
| if ($message instanceof Closure) { |
| return (string) $message(...array_values($parameters)); |
| } |
| |
| if ($number !== null) { |
| $parameters['%count%'] = $number; |
| } |
| if (isset($parameters['%count%'])) { |
| $parameters[':count'] = $parameters['%count%']; |
| } |
| |
| // @codeCoverageIgnoreStart |
| $choice = $translator instanceof ContractsTranslatorInterface |
| ? $translator->trans($key, $parameters) |
| : $translator->transChoice($key, $number, $parameters); |
| // @codeCoverageIgnoreEnd |
| |
| return (string) $choice; |
| } |
| |
| /** |
| * Translate using translation string or callback available. |
| * |
| * @param string $key |
| * @param array $parameters |
| * @param string|int|float|null $number |
| * @param \Symfony\Component\Translation\TranslatorInterface $translator |
| * |
| * @return string |
| */ |
| public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string |
| { |
| $translation = static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number); |
| |
| if ($number !== null && $altNumbers) { |
| return str_replace($number, $this->translateNumber($number), $translation); |
| } |
| |
| return $translation; |
| } |
| |
| /** |
| * Returns the alternative number for a given integer if available in the current locale. |
| * |
| * @param int $number |
| * |
| * @return string |
| */ |
| public function translateNumber(int $number): string |
| { |
| $translateKey = "alt_numbers.$number"; |
| $symbol = $this->translate($translateKey); |
| |
| if ($symbol !== $translateKey) { |
| return $symbol; |
| } |
| |
| if ($number > 99 && $this->translate('alt_numbers.99') !== 'alt_numbers.99') { |
| $start = ''; |
| foreach ([10000, 1000, 100] as $exp) { |
| $key = "alt_numbers_pow.$exp"; |
| if ($number >= $exp && $number < $exp * 10 && ($pow = $this->translate($key)) !== $key) { |
| $unit = floor($number / $exp); |
| $number -= $unit * $exp; |
| $start .= ($unit > 1 ? $this->translate("alt_numbers.$unit") : '').$pow; |
| } |
| } |
| $result = ''; |
| while ($number) { |
| $chunk = $number % 100; |
| $result = $this->translate("alt_numbers.$chunk").$result; |
| $number = floor($number / 100); |
| } |
| |
| return "$start$result"; |
| } |
| |
| if ($number > 9 && $this->translate('alt_numbers.9') !== 'alt_numbers.9') { |
| $result = ''; |
| while ($number) { |
| $chunk = $number % 10; |
| $result = $this->translate("alt_numbers.$chunk").$result; |
| $number = floor($number / 10); |
| } |
| |
| return $result; |
| } |
| |
| return (string) $number; |
| } |
| |
| /** |
| * Translate a time string from a locale to an other. |
| * |
| * @param string $timeString date/time/duration string to translate (may also contain English) |
| * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default) |
| * @param string|null $to output locale of the result returned (`"en"` by default) |
| * @param int $mode specify what to translate with options: |
| * - CarbonInterface::TRANSLATE_ALL (default) |
| * - CarbonInterface::TRANSLATE_MONTHS |
| * - CarbonInterface::TRANSLATE_DAYS |
| * - CarbonInterface::TRANSLATE_UNITS |
| * - CarbonInterface::TRANSLATE_MERIDIEM |
| * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS |
| * |
| * @return string |
| */ |
| public static function translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) |
| { |
| // Fallback source and destination locales |
| $from = $from ?: static::getLocale(); |
| $to = $to ?: 'en'; |
| |
| if ($from === $to) { |
| return $timeString; |
| } |
| |
| // Standardize apostrophe |
| $timeString = strtr($timeString, ['’' => "'"]); |
| |
| $fromTranslations = []; |
| $toTranslations = []; |
| |
| foreach (['from', 'to'] as $key) { |
| $language = $$key; |
| $translator = Translator::get($language); |
| $translations = $translator->getMessages(); |
| |
| if (!isset($translations[$language])) { |
| return $timeString; |
| } |
| |
| $translationKey = $key.'Translations'; |
| $messages = $translations[$language]; |
| $months = $messages['months'] ?? []; |
| $weekdays = $messages['weekdays'] ?? []; |
| $meridiem = $messages['meridiem'] ?? ['AM', 'PM']; |
| |
| if ($key === 'from') { |
| foreach (['months', 'weekdays'] as $variable) { |
| $list = $messages[$variable.'_standalone'] ?? null; |
| |
| if ($list) { |
| foreach ($$variable as $index => &$name) { |
| $name .= '|'.$messages[$variable.'_standalone'][$index]; |
| } |
| } |
| } |
| } |
| |
| $$translationKey = array_merge( |
| $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($months, 12, $timeString) : [], |
| $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($messages['months_short'] ?? [], 12, $timeString) : [], |
| $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($weekdays, 7, $timeString) : [], |
| $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($messages['weekdays_short'] ?? [], 7, $timeString) : [], |
| $mode & CarbonInterface::TRANSLATE_DIFF ? static::translateWordsByKeys([ |
| 'diff_now', |
| 'diff_today', |
| 'diff_yesterday', |
| 'diff_tomorrow', |
| 'diff_before_yesterday', |
| 'diff_after_tomorrow', |
| ], $messages, $key) : [], |
| $mode & CarbonInterface::TRANSLATE_UNITS ? static::translateWordsByKeys([ |
| 'year', |
| 'month', |
| 'week', |
| 'day', |
| 'hour', |
| 'minute', |
| 'second', |
| ], $messages, $key) : [], |
| $mode & CarbonInterface::TRANSLATE_MERIDIEM ? array_map(function ($hour) use ($meridiem) { |
| if (\is_array($meridiem)) { |
| return $meridiem[$hour < 12 ? 0 : 1]; |
| } |
| |
| return $meridiem($hour, 0, false); |
| }, range(0, 23)) : [] |
| ); |
| } |
| |
| return substr(preg_replace_callback('/(?<=[\d\s+.\/,_-])('.implode('|', $fromTranslations).')(?=[\d\s+.\/,_-])/iu', function ($match) use ($fromTranslations, $toTranslations) { |
| [$chunk] = $match; |
| |
| foreach ($fromTranslations as $index => $word) { |
| if (preg_match("/^$word\$/iu", $chunk)) { |
| return $toTranslations[$index] ?? ''; |
| } |
| } |
| |
| return $chunk; // @codeCoverageIgnore |
| }, " $timeString "), 1, -1); |
| } |
| |
| /** |
| * Translate a time string from the current locale (`$date->locale()`) to an other. |
| * |
| * @param string $timeString time string to translate |
| * @param string|null $to output locale of the result returned ("en" by default) |
| * |
| * @return string |
| */ |
| public function translateTimeStringTo($timeString, $to = null) |
| { |
| return static::translateTimeString($timeString, $this->getTranslatorLocale(), $to); |
| } |
| |
| /** |
| * Get/set the locale for the current instance. |
| * |
| * @param string|null $locale |
| * @param string ...$fallbackLocales |
| * |
| * @return $this|string |
| */ |
| public function locale(string $locale = null, ...$fallbackLocales) |
| { |
| if ($locale === null) { |
| return $this->getTranslatorLocale(); |
| } |
| |
| if (!$this->localTranslator || $this->getTranslatorLocale($this->localTranslator) !== $locale) { |
| $translator = Translator::get($locale); |
| |
| if (!empty($fallbackLocales)) { |
| $translator->setFallbackLocales($fallbackLocales); |
| |
| foreach ($fallbackLocales as $fallbackLocale) { |
| $messages = Translator::get($fallbackLocale)->getMessages(); |
| |
| if (isset($messages[$fallbackLocale])) { |
| $translator->setMessages($fallbackLocale, $messages[$fallbackLocale]); |
| } |
| } |
| } |
| |
| $this->setLocalTranslator($translator); |
| } |
| |
| return $this; |
| } |
| |
| /** |
| * Get the current translator locale. |
| * |
| * @return string |
| */ |
| public static function getLocale() |
| { |
| return static::getLocaleAwareTranslator()->getLocale(); |
| } |
| |
| /** |
| * Set the current translator locale and indicate if the source locale file exists. |
| * Pass 'auto' as locale to use closest language from the current LC_TIME locale. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function setLocale($locale) |
| { |
| return static::getLocaleAwareTranslator()->setLocale($locale) !== false; |
| } |
| |
| /** |
| * Set the fallback locale. |
| * |
| * @see https://symfony.com/doc/current/components/translation.html#fallback-locales |
| * |
| * @param string $locale |
| */ |
| public static function setFallbackLocale($locale) |
| { |
| $translator = static::getTranslator(); |
| |
| if (method_exists($translator, 'setFallbackLocales')) { |
| $translator->setFallbackLocales([$locale]); |
| |
| if ($translator instanceof Translator) { |
| $preferredLocale = $translator->getLocale(); |
| $translator->setMessages($preferredLocale, array_replace_recursive( |
| $translator->getMessages()[$locale] ?? [], |
| Translator::get($locale)->getMessages()[$locale] ?? [], |
| $translator->getMessages($preferredLocale) |
| )); |
| } |
| } |
| } |
| |
| /** |
| * Get the fallback locale. |
| * |
| * @see https://symfony.com/doc/current/components/translation.html#fallback-locales |
| * |
| * @return string|null |
| */ |
| public static function getFallbackLocale() |
| { |
| $translator = static::getTranslator(); |
| |
| if (method_exists($translator, 'getFallbackLocales')) { |
| return $translator->getFallbackLocales()[0] ?? null; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Set the current locale to the given, execute the passed function, reset the locale to previous one, |
| * then return the result of the closure (or null if the closure was void). |
| * |
| * @param string $locale locale ex. en |
| * @param callable $func |
| * |
| * @return mixed |
| */ |
| public static function executeWithLocale($locale, $func) |
| { |
| $currentLocale = static::getLocale(); |
| $result = $func(static::setLocale($locale) ? static::getLocale() : false, static::translator()); |
| static::setLocale($currentLocale); |
| |
| return $result; |
| } |
| |
| /** |
| * Returns true if the given locale is internally supported and has short-units support. |
| * Support is considered enabled if either year, day or hour has a short variant translated. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function localeHasShortUnits($locale) |
| { |
| return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { |
| return $newLocale && |
| ( |
| ($y = static::translateWith($translator, 'y')) !== 'y' && |
| $y !== static::translateWith($translator, 'year') |
| ) || ( |
| ($y = static::translateWith($translator, 'd')) !== 'd' && |
| $y !== static::translateWith($translator, 'day') |
| ) || ( |
| ($y = static::translateWith($translator, 'h')) !== 'h' && |
| $y !== static::translateWith($translator, 'hour') |
| ); |
| }); |
| } |
| |
| /** |
| * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). |
| * Support is considered enabled if the 4 sentences are translated in the given locale. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function localeHasDiffSyntax($locale) |
| { |
| return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { |
| if (!$newLocale) { |
| return false; |
| } |
| |
| foreach (['ago', 'from_now', 'before', 'after'] as $key) { |
| if ($translator instanceof TranslatorBagInterface && $translator->getCatalogue($newLocale)->get($key) instanceof Closure) { |
| continue; |
| } |
| |
| if ($translator->trans($key) === $key) { |
| return false; |
| } |
| } |
| |
| return true; |
| }); |
| } |
| |
| /** |
| * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). |
| * Support is considered enabled if the 3 words are translated in the given locale. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function localeHasDiffOneDayWords($locale) |
| { |
| return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { |
| return $newLocale && |
| $translator->trans('diff_now') !== 'diff_now' && |
| $translator->trans('diff_yesterday') !== 'diff_yesterday' && |
| $translator->trans('diff_tomorrow') !== 'diff_tomorrow'; |
| }); |
| } |
| |
| /** |
| * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). |
| * Support is considered enabled if the 2 words are translated in the given locale. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function localeHasDiffTwoDayWords($locale) |
| { |
| return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { |
| return $newLocale && |
| $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' && |
| $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow'; |
| }); |
| } |
| |
| /** |
| * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). |
| * Support is considered enabled if the 4 sentences are translated in the given locale. |
| * |
| * @param string $locale locale ex. en |
| * |
| * @return bool |
| */ |
| public static function localeHasPeriodSyntax($locale) |
| { |
| return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { |
| return $newLocale && |
| $translator->trans('period_recurrences') !== 'period_recurrences' && |
| $translator->trans('period_interval') !== 'period_interval' && |
| $translator->trans('period_start_date') !== 'period_start_date' && |
| $translator->trans('period_end_date') !== 'period_end_date'; |
| }); |
| } |
| |
| /** |
| * Returns the list of internally available locales and already loaded custom locales. |
| * (It will ignore custom translator dynamic loading.) |
| * |
| * @return array |
| */ |
| public static function getAvailableLocales() |
| { |
| $translator = static::getLocaleAwareTranslator(); |
| |
| return $translator instanceof Translator |
| ? $translator->getAvailableLocales() |
| : [$translator->getLocale()]; |
| } |
| |
| /** |
| * Returns list of Language object for each available locale. This object allow you to get the ISO name, native |
| * name, region and variant of the locale. |
| * |
| * @return Language[] |
| */ |
| public static function getAvailableLocalesInfo() |
| { |
| $languages = []; |
| foreach (static::getAvailableLocales() as $id) { |
| $languages[$id] = new Language($id); |
| } |
| |
| return $languages; |
| } |
| |
| /** |
| * Initialize the default translator instance if necessary. |
| * |
| * @return \Symfony\Component\Translation\TranslatorInterface |
| */ |
| protected static function translator() |
| { |
| if (static::$translator === null) { |
| static::$translator = Translator::get(); |
| } |
| |
| return static::$translator; |
| } |
| |
| /** |
| * Get the locale of a given translator. |
| * |
| * If null or omitted, current local translator is used. |
| * If no local translator is in use, current global translator is used. |
| * |
| * @param null $translator |
| * |
| * @return string|null |
| */ |
| protected function getTranslatorLocale($translator = null): ?string |
| { |
| if (\func_num_args() === 0) { |
| $translator = $this->getLocalTranslator(); |
| } |
| |
| $translator = static::getLocaleAwareTranslator($translator); |
| |
| return $translator ? $translator->getLocale() : null; |
| } |
| |
| /** |
| * Throw an error if passed object is not LocaleAwareInterface. |
| * |
| * @param LocaleAwareInterface|null $translator |
| * |
| * @return LocaleAwareInterface|null |
| */ |
| protected static function getLocaleAwareTranslator($translator = null) |
| { |
| if (\func_num_args() === 0) { |
| $translator = static::translator(); |
| } |
| |
| if ($translator && !($translator instanceof LocaleAwareInterface || method_exists($translator, 'getLocale'))) { |
| throw new NotLocaleAwareException($translator); |
| } |
| |
| return $translator; |
| } |
| |
| /** |
| * Return the word cleaned from its translation codes. |
| * |
| * @param string $word |
| * |
| * @return string |
| */ |
| private static function cleanWordFromTranslationString($word) |
| { |
| $word = str_replace([':count', '%count', ':time'], '', $word); |
| $word = strtr($word, ['’' => "'"]); |
| $word = preg_replace('/({\d+(,(\d+|Inf))?}|[\[\]]\d+(,(\d+|Inf))?[\[\]])/', '', $word); |
| |
| return trim($word); |
| } |
| |
| /** |
| * Translate a list of words. |
| * |
| * @param string[] $keys keys to translate. |
| * @param string[] $messages messages bag handling translations. |
| * @param string $key 'to' (to get the translation) or 'from' (to get the detection RegExp pattern). |
| * |
| * @return string[] |
| */ |
| private static function translateWordsByKeys($keys, $messages, $key): array |
| { |
| return array_map(function ($wordKey) use ($messages, $key) { |
| $message = $key === 'from' && isset($messages[$wordKey.'_regexp']) |
| ? $messages[$wordKey.'_regexp'] |
| : ($messages[$wordKey] ?? null); |
| |
| if (!$message) { |
| return '>>DO NOT REPLACE<<'; |
| } |
| |
| $parts = explode('|', $message); |
| |
| return $key === 'to' |
| ? static::cleanWordFromTranslationString(end($parts)) |
| : '(?:'.implode('|', array_map([static::class, 'cleanWordFromTranslationString'], $parts)).')'; |
| }, $keys); |
| } |
| |
| /** |
| * Get an array of translations based on the current date. |
| * |
| * @param callable $translation |
| * @param int $length |
| * @param string $timeString |
| * |
| * @return string[] |
| */ |
| private static function getTranslationArray($translation, $length, $timeString): array |
| { |
| $filler = '>>DO NOT REPLACE<<'; |
| |
| if (\is_array($translation)) { |
| return array_pad($translation, $length, $filler); |
| } |
| |
| $list = []; |
| $date = static::now(); |
| |
| for ($i = 0; $i < $length; $i++) { |
| $list[] = $translation($date, $timeString, $i) ?? $filler; |
| } |
| |
| return $list; |
| } |
| } |