Пример #1
0
 public function offsetSet($offset, $menu)
 {
     if ($menu instanceof Entity && !$this->active && $offset === NULL) {
         $this->active = $menu;
         return;
     } elseif ($menu instanceof Ytnuk\Translation\Entity) {
         $entity = new Entity();
         $entity->title = $menu;
         $menu = $entity;
     } elseif (is_string($menu)) {
         $this->repository->attach($entity = new Entity());
         $entity->title = new Ytnuk\Translation\Entity();
         $translate = new Ytnuk\Translation\Translate\Entity();
         $translate->value = $this->translator->translate($menu);
         $entity->title->translates->add($translate);
         $this->repository->detach($entity);
         $menu = $entity;
     }
     if ($menu instanceof Entity) {
         if ($offset === NULL) {
             $this->append[] = $menu;
         } else {
             $this->append[$offset] = $menu;
         }
     } else {
         parent::offsetSet($offset, $menu);
     }
 }
Пример #2
0
 public function setConfirm($confirm)
 {
     if ($this->translator) {
         $confirm = $this->translator->translate($confirm);
     }
     $this->confirm = $confirm;
     return $this;
 }
Пример #3
0
 /**
  * @param  string                   $pageUrl
  * @throws InvalidVideoUrlException
  * @return string
  */
 public function getVideoSrc($pageUrl)
 {
     $key = 'watch?v=';
     if (!Strings::contains($pageUrl, $key)) {
         throw new InvalidVideoUrlException($this->translator->translate('locale.error.invalid_youtube_video_url'));
     }
     return str_replace($key, 'embed/', $pageUrl);
 }
Пример #4
0
 /**
  * Get data header
  * @return array
  */
 public function getHeader()
 {
     $header = [];
     foreach ($this->columns as $column) {
         $header[] = $this->translator->translate($column->getName());
     }
     return $header;
 }
Пример #5
0
 /**
  * @return Form
  */
 public function create()
 {
     $form = new Form();
     $form->setTranslator($this->translator->domain('tags.tagForm'));
     $form->addText('name', 'name.label', null, Tag::LENGTH_NAME)->setRequired('name.messages.required');
     $form->addText('color', 'color.label', null, 7)->setRequired('color.messages.required')->setDefaultValue('#')->addRule(Form::PATTERN, 'color.messages.wrongPattern', '^#([0-f]{3}|[0-f]{6})$');
     $form->addSubmit('save', 'save.caption');
     return $form;
 }
Пример #6
0
 /**
  * @Actions login
  */
 protected function createComponentLoginForm()
 {
     $form = new Form();
     $form->setTranslator($this->translator->domain('users.login.form'));
     $form->addText('email', 'email.label')->setAttribute('placeholder', 'email.placeholder')->setAttribute('title', $this->translator->translate('users.login.form.email.title'))->setRequired('email.messages.required')->addRule(Form::EMAIL, 'email.messages.wrongFormat');
     $form->addPassword('password', 'password.label')->setAttribute('placeholder', 'password.placeholder')->setAttribute('title', $this->translator->translate('users.login.form.password.title'))->setRequired('password.messages.required');
     $form->addSubmit('login', 'login.caption');
     $form->onSuccess[] = [$this, 'processLogin'];
     return $form;
 }
Пример #7
0
 /**
  * @param bool $ingoreHidden
  * @return string
  */
 public function getName($ingoreHidden = FALSE)
 {
     $title = $this->name;
     if (!$ingoreHidden and $this->hideTitle) {
         $title = "";
     }
     if ($this->translator instanceof Nette\Localization\ITranslator and !$ingoreHidden) {
         $title = $this->translator->translate($title);
     }
     return $title;
 }
Пример #8
0
 protected function createComponentForm()
 {
     $form = new Form();
     $form->setTranslator($this->translator->domain('images.filterForm'));
     $form->addText('name', 'name.label', 30);
     $form->addSelect('extension', $this->translator->translate('images.filterForm.extension.label'), ['png' => 'PNG', 'jpg' => 'JPG'])->setPrompt($this->translator->translate('images.filterForm.extension.prompt'))->setTranslator(null);
     $form->addText('maxWidth', 'maxWidth.label')->addCondition(Form::FILLED)->addRule(Form::INTEGER, 'maxWidth.messages.integerType')->addRule(Form::MIN, 'maxWidth.messages.minValue', 1);
     $form->addText('maxHeight', 'maxHeight.label')->addCondition(Form::FILLED)->addRule(Form::INTEGER, 'maxHeight.messages.integerType')->addRule(Form::MIN, 'maxHeight.messages.integerType', 1);
     $form->addSubmit('filter', 'filter.caption')->onClick[] = [$this, 'processFilter'];
     $form->addSubmit('reset', 'reset.caption')->onClick[] = [$this, 'resetFilter'];
     return $form;
 }
Пример #9
0
 protected function createComponentForm()
 {
     $form = new Form();
     $form->setTranslator($this->translator->domain('admin.localization'));
     $form->addSelect('locale', null)->setItems($this->locales)->setDefaultValue($this->locale)->setTranslator(null);
     if (isset($this->locale) and array_key_exists($this->locale, $this->locales)) {
         $form['locale']->setValue($this->locale);
     }
     $form->addSubmit('change', 'form.change.caption');
     $form->onSuccess[] = [$this, 'processLocale'];
     return $form;
 }
Пример #10
0
 /**
  * @param string $destination
  * @param string $text
  * @param array $args
  * @return Item
  */
 public function addItem($destination, $text, $args = array())
 {
     if ($this->translator != NULL) {
         $text = $this->translator->translate($text);
     }
     $item = new Item();
     $item->setDestination($destination);
     $item->setText($text);
     $item->setArguments($args);
     $this->items[] = $item;
     return $item;
 }
Пример #11
0
 public function translate($message, $count = NULL, $parameters = array(), $domain = NULL, $locale = NULL)
 {
     if ($message instanceof Phrase) {
         return $this->translator->translate(new Phrase($this->prefix . '.' . $message->message, $message->count, $message->parameters, $message->domain, $message->locale));
     }
     if (is_array($count)) {
         $locale = $domain ?: NULL;
         $domain = $parameters ?: NULL;
         $parameters = $count ?: array();
         $count = NULL;
     }
     return $this->translator->translate($this->prefix . '.' . $message, $count, (array) $parameters, $domain, $locale);
 }
Пример #12
0
 /**
  * @throws Nette\Security\AuthenticationException
  * @return Nette\Security\Identity
  */
 public function authenticate(array $credentials)
 {
     list($email, $password) = $credentials;
     $user = $this->userRepository->getByEmail($email);
     if (!$user) {
         throw new Nette\Security\AuthenticationException($this->translator->translate('locale.sign.incorrect_email'), self::IDENTITY_NOT_FOUND);
     } elseif (!$user->isAuthenticated) {
         throw new Nette\Security\AuthenticationException($this->translator->translate('locale.sign.authentication_waiting'), self::NOT_APPROVED);
     } elseif (!Passwords::verify($password . $user->salt, $user->password)) {
         throw new Nette\Security\AuthenticationException($this->translator->translate('locale.sign.incorrect_password'), self::INVALID_CREDENTIAL);
     } elseif (Passwords::needsRehash($user->password)) {
         $this->userRepository->updatePassword($user, $user->password);
     }
     return $this->updateIdentity($user);
 }
Пример #13
0
 /**
  * @param array $values
  * @param string $gridName
  * @throws NoRowSelectedException
  */
 public function actionFormSubmitted($values, $gridName)
 {
     try {
         $rows = array();
         foreach ($values as $name => $value) {
             if (\Nette\Utils\Strings::startsWith($name, "row")) {
                 $vals = explode("_", $name);
                 if ((bool) $value) {
                     $rows[] = $vals[1];
                 }
             }
         }
         $subGrid = $gridName == $this->name ? FALSE : TRUE;
         if (!count($rows)) {
             throw new NoRowSelectedException($this->translator->translate('No row selected'));
         }
         if ($subGrid) {
             call_user_func($this[$gridName]['actions']->components[$values['action_name']]->getCallback(), $rows);
         } else {
             call_user_func($this['actions']->components[$values['action_name']]->getCallback(), $rows);
         }
         if (!$this->presenter->isAjax()) {
             $this->redirect("this");
         }
     } catch (NoRowSelectedException $e) {
         if ($subGrid) {
             $this[$gridName]->flashMessage($e->getMessage(), "grid-error");
         } else {
             $this->flashMessage($e->getMessage(), "grid-error");
         }
         if (!$this->presenter->isAjax()) {
             $this->redirect("this");
         }
     }
 }
Пример #14
0
 public function setPathToDictionary($pathToDictionary)
 {
     $this->pathToDictionary = $pathToDictionary;
     if ($this->translator instanceof BasicTranslator) {
         $this->translator->setPathToDictionary($pathToDictionary);
     }
 }
Пример #15
0
 /**
  * @param  string $s
  * @param  int $count
  * @return string
  */
 public function translate($s, $count = NULL)
 {
     if ($this->translator === NULL) {
         return sprintf($s, $count);
     }
     return $this->translator->translate($s, $count);
 }
Пример #16
0
 /**
  * Sets translate adapter.
  * @return self
  */
 public function setTranslator(Nette\Localization\ITranslator $translator = NULL)
 {
     $this->latte->addFilter('translate', $translator === NULL ? NULL : function (Latte\Runtime\FilterInfo $fi, ...$args) use($translator) {
         return $translator->translate(...$args);
     });
     return $this;
 }
Пример #17
0
 /**
  * @param  ArrayHash $values
  * @param  Entities\TagEntity $tag
  * @param  string $type
  * @param  Entities\WikiEntity $e
  * @throws PossibleUniqueKeyDuplicationException
  * @return Entities\WikiEntity
  */
 public function update(ArrayHash $values, Entities\TagEntity $tag, $type, Entities\WikiEntity $e)
 {
     $e->setValues($values);
     if ($e->tag->id !== $tag->id && $this->getByTagAndNameAndType($tag, $values->name, $type)) {
         throw new PossibleUniqueKeyDuplicationException($this->translator->translate('locale.duplicity.article_tag_and_name'));
     }
     $e->slug = $e->slug ?: Slugger::slugify($e->name);
     if ($e->tag->id !== $tag->id && $this->getByTagAndSlugAndType($tag, $e->slug, $type)) {
         throw new PossibleUniqueKeyDuplicationException($this->translator->translate('locale.duplicity.article_tag_and_slug'));
     }
     $e->text = $this->htmlPurifier->purify($values->text);
     $e->tag = $tag;
     $e->type = $type;
     $this->persistAndFlush($this->em, $e);
     return $e;
 }
Пример #18
0
 /**
  * @return void
  */
 protected function startup()
 {
     parent::startup();
     // Language
     $this->checkLanguage();
     // Setup translator
     $this->translator->setLang($this->lang);
 }
Пример #19
0
 private function outputTranslations()
 {
     $script = Html::el('script', array('type' => 'text/javascript'));
     $contents = "\nvar translations = typeof translations == 'undefined' ? {} : translations;\n";
     foreach (array_unique($this->translations) as $message) {
         $contents .= 'translations[' . json_encode($message) . '] = ' . json_encode(NULL !== $this->translator ? $this->translator->translate($message) : $message) . ";\n";
     }
     $script->setText($contents);
     return $script;
 }
 public function translate($message, $count = NULL, $parameters = array(), $domain = NULL, $locale = NULL)
 {
     $translationString = $message instanceof Phrase ? $message->message : $message;
     $prefix = $this->prefix . '.';
     if (Strings::startsWith($message, '//')) {
         $prefix = NULL;
         $translationString = Strings::substring($translationString, 2);
     }
     if ($message instanceof Phrase) {
         return $this->translator->translate(new Phrase($prefix . $translationString, $message->count, $message->parameters, $message->domain, $message->locale));
     }
     if (is_array($count)) {
         $locale = $domain ?: NULL;
         $domain = $parameters ?: NULL;
         $parameters = $count ?: array();
         $count = NULL;
     }
     return $this->translator->translate($prefix . $translationString, $count, (array) $parameters, $domain, $locale);
 }
Пример #21
0
 public function update(ArrayHash $values, Entities\TagEntity $tag, Entities\UserEntity $user, Entities\ArticleEntity $e)
 {
     if ($e->tag->id !== $tag->id) {
         $this->menuCache->deleteSection(MenuCache::SECTION_ARTICLES);
     }
     $e->setValues($values);
     if ($e->tag->id !== $tag->id && $this->getByTagAndName($tag, $values->name)) {
         throw new PossibleUniqueKeyDuplicationException($this->translator->translate('locale.duplicity.article_tag_and_name'));
     }
     $e->slug = $e->slug ?: Slugger::slugify($e->name);
     if ($e->tag->id !== $tag->id && $this->getByTagAndSlug($tag, $e->slug)) {
         throw new PossibleUniqueKeyDuplicationException($this->translator->translate('locale.duplicity.article_tag_and_slug'));
     }
     $e->text = $this->htmlPurifier->purify($values->text);
     $e->tag = $tag;
     $e->user = $user;
     $this->persistAndFlush($this->em, $e);
     return $e;
 }
Пример #22
0
 /**
  * Creates template and registers helpers and latte filter
  * @param  UI\Presenter $presenter
  * @param  string		$file	Filepath to file
  * @param  string|NULL	$lang	Lang code (length=2)
  * @param  string		$class	Name of template class
  * @throws InvalidArgumentException
  * @return Nette\Templating\IFileTemplate
  */
 public function createTemplate(UI\Presenter $presenter, $file = NULL, $lang = NULL, $class = NULL)
 {
     $this->translator->setLangTo($lang);
     $latte = $this->latteFactory->create();
     $template = $class ? new $class($latte) : new Nette\Bridges\ApplicationLatte\Template($latte);
     $template->getLatte()->addFilter(NULL, 'Nette\\Templating\\Helpers::loader');
     $template->getLatte()->addFilter(NULL, '\\Helpers::loader');
     array_unshift($latte->onCompile, function ($latte) {
         $latte->getParser()->shortNoEscape = TRUE;
         $latte->getCompiler()->addMacro('cache', new CacheMacro($latte->getCompiler()));
         Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
         FormMacros::install($latte->getCompiler());
     });
     $latte->addFilter('url', 'rawurlencode');
     // back compatiblity
     foreach (array('normalize', 'toAscii', 'webalize', 'padLeft', 'padRight', 'reverse') as $name) {
         $latte->addFilter($name, 'Nette\\Utils\\Strings::' . $name);
     }
     $template->setTranslator($this->translator);
     if (!is_null($file)) {
         $template->setFile($this->appDir . $file);
     }
     // default parameters
     $template->control = $template->_control = $presenter;
     $template->presenter = $template->_presenter = $presenter;
     if ($presenter instanceof UI\Presenter) {
         $template->user = $presenter->getUser();
         $template->netteHttpResponse = $this->httpResponse;
         $template->netteCacheStorage = $this->netteCacheStorage;
         $template->baseUri = $template->baseUrl = rtrim($this->httpRequest->getUrl()->getBaseUrl(), '/');
         $template->basePath = preg_replace('#https?://[^/]+#A', '', $template->baseUrl);
         // flash message
         if ($presenter->hasFlashSession()) {
             $id = $presenter->getParameterId('flash');
             $template->flashes = $presenter->getFlashSession()->{$id};
         }
     }
     if (!isset($template->flashes) || !is_array($template->flashes)) {
         $template->flashes = array();
     }
     return $template;
 }
 /**
  * Formulář pro vytvoření nového formátu
  * @return Form
  */
 protected function createComponentNewFormatForm()
 {
     $form = new Form();
     $form->addHidden('datasource');
     $form->addHidden('column');
     $metaAttribute = $form->addHidden('metaAttribute');
     $form->addText('metaAttributeName', 'Meta-attribute:')->setAttribute('readonly', 'readonly')->setAttribute('class', 'normalWidth');
     $formatName = $form->addText('formatName', 'Format name:')->setRequired()->setAttribute('class', 'normalWidth');
     $formatName->addRule(Form::MIN_LENGTH, 'Min length of format name is %s characters!', 3);
     $formatName->addRule(function (TextInput $control) use($metaAttribute) {
         try {
             $format = $this->metaAttributesFacade->findFormatByName($metaAttribute->value, $control->value);
             ///XXX
             if ($format instanceof Format) {
                 return false;
             }
         } catch (\Exception $e) {
             /*chybu ignorujeme (nenalezený metaatribut je OK)*/
         }
         return true;
     }, 'Format with this name already exists!');
     $form->addCheckbox('formatShared', 'Create shared (standard) format');
     $form->addSelect('formatType', 'Values range:', array('interval' => 'Continuous values (interval)', 'values' => 'Distinct values (enumeration)'))->setAttribute('class', 'normalWidth')->setDefaultValue('values');
     $submit = $form->addSubmit('create', 'Create format');
     $submit->setValidationScope(array($formatName));
     $submit->onClick[] = function (SubmitButton $button) {
         $values = $button->form->values;
         try {
             $datasourceColumn = $this->datasourcesFacade->findDatasourceColumn($values->datasource, $values->column);
             $metaAttribute = $this->metaAttributesFacade->findMetaAttribute($values->metaAttribute);
             $datasource = $this->datasourcesFacade->findDatasource($values->datasource);
             $this->databasesFacade->openDatabase($datasource->getDbConnection());
             $datasourceColumnValuesStatistic = $this->databasesFacade->getColumnValuesStatistic($datasource->dbTable, $datasourceColumn->name);
             $format = $this->metaAttributesFacade->createFormatFromDatasourceColumn($metaAttribute, $values->formatName, $datasourceColumn, $datasourceColumnValuesStatistic, @$values->formatType, @$values->formatShared);
             $datasourceColumn->format = $format;
             $this->datasourcesFacade->saveDatasourceColumn($datasourceColumn);
         } catch (\Exception $e) {
             $this->flashMessage($this->translator->translate('Format creation failed.'));
         }
         $this->redirect('Close');
     };
     $storno = $form->addSubmit('storno', 'Storno');
     $storno->setValidationScope(array());
     $storno->onClick[] = function (SubmitButton $button) {
         $values = $button->form->values;
         $this->redirect('SelectFormat', array('datasource' => $values->datasource, 'column' => $values->column, 'metaAttribute' => $values->metaAttribute));
     };
     $form->onError[] = function (Form $form) {
         $values = $form->values;
         $this->handleNewFormat($values->datasource, $values->column, $values->metaAttribute);
     };
     return $form;
 }
Пример #24
0
 /**
  * @param  Entities\UserEntity             $e
  * @param  string                          $token
  * @throws UserNotFoundException
  * @throws ActivationLimitExpiredException
  */
 public function checkForTokenExpiration(Entities\UserEntity $e, $token)
 {
     if ($e->token !== $token) {
         throw new UserNotFoundException($this->translator->translate('locale.sign.incorrect_token'));
     }
     $current = new DateTime();
     $created = $e->tokenCreatedAt;
     $currentTimestamp = $current->getTimestamp();
     $createdTimestamp = $created->getTimestamp();
     $diff = $currentTimestamp - $createdTimestamp;
     if ($diff >= Authenticator::ACTIVATION_LIMIT_TIMESTAMP) {
         throw new ActivationLimitExpiredException($this->translator->translate('locale.sign.authentication_expired'));
     }
 }
Пример #25
0
 /**
  * Get assambled form
  * @param  Nette\Forms\Container $group_action_container
  * @param Form $form
  * @param Nette\Localization\ITranslator $translator
  * @return void
  */
 public function addToFormContainer($group_action_container, $form, $translator = NULL)
 {
     /**
      * First foreach for filling "main" select
      */
     foreach ($this->group_actions as $id => $action) {
         $main_options[$id] = $action->getTitle();
     }
     $group_action_container->addSelect('group_action', '', $main_options)->setPrompt($translator ? $translator->translate('Choose') : 'Choose');
     /**
      * Second for creating select for each "sub"-action
      */
     foreach ($this->group_actions as $id => $action) {
         if ($action->hasOptions()) {
             $group_action_container->addSelect($id, '', $action->getOptions())->setAttribute('id', static::ID_ATTRIBUTE_PREFIX . $id);
         }
     }
     foreach ($this->group_actions as $id => $action) {
         $group_action_container['group_action']->addCondition(Form::EQUAL, $id)->toggle(static::ID_ATTRIBUTE_PREFIX . $id);
     }
     $group_action_container['group_action']->addCondition(Form::FILLED)->toggle('group_action_submit');
     $group_action_container->addSubmit('submit', $translator ? $translator->translate('Do') : 'Do')->setAttribute('id', 'group_action_submit');
     $form->onSubmit[] = [$this, 'submitted'];
 }
Пример #26
0
 public function authenticate(array $credentials)
 {
     if ($this->checkConnection->invoke()) {
         $data = $this->getData();
         try {
             /** @var $user \CmsModule\Pages\Users\UserEntity */
             $user = $this->userRepository->createQueryBuilder('a')->join('a.socialLogins', 's')->where('s.type = :type AND s.uniqueKey = :key')->setParameter('type', $this->getType())->setParameter('key', $data['id'])->getQuery()->getSingleResult();
         } catch (\Doctrine\ORM\NoResultException $e) {
         }
         if (!isset($user) || !$user) {
             throw new AuthenticationException($this->translator->translate('User does not exist.'), self::INVALID_CREDENTIAL);
         }
         return new Identity($user->email, $user->getRoles());
     }
 }
Пример #27
0
 public function processImageUpload(Form $form, $values)
 {
     if (!$this->authorizator->isAllowed($this->user, 'image', 'upload')) {
         $this->flashMessage('authorization.noPermission', FlashMessage::WARNING);
         return;
     }
     /** @var FileUpload $image */
     $image = $values->image;
     try {
         if ($image->isOk()) {
             $this->imageFacade->saveImage($image);
             $this->flashMessage('images.uploadForm.messages.success', FlashMessage::SUCCESS);
             $this->redirect('this');
         }
     } catch (NotImageUploadedException $iu) {
         $form->addError($this->translator->translate('images.uploadForm.messages.wrongFileType'));
     } catch (FileSizeException $fs) {
         $form->addError($this->translator->translate('images.uploadForm.messages.wrongFileSize', ['size' => $this->imageSize]));
     } catch (InvalidStateException $is) {
         $form->addError($this->translator->translate('images.uploadForm.messages.savingError'));
     } catch (DBALException $e) {
         $form->addError($this->translator->translate('images.uploadForm.messages.savingError'));
     }
 }
Пример #28
0
 /**
  * @param string $number
  * @param string $country
  * @param string|NULL $locale
  * @param string|NULL $userCountry
  *
  * @return string
  *
  * @throws Exceptions\NoValidCountryException
  * @throws Exceptions\NoValidPhoneException
  */
 public function getLocation($number, $country = 'AUTO', $locale = NULL, $userCountry = NULL)
 {
     if ($this->isValid((string) $number, $country)) {
         $country = strtoupper($country);
         if ($userCountry !== NULL) {
             // Check for valid user country
             $userCountry = $this->validateCountry($userCountry);
         }
         // Parse phone number
         $parsed = $this->phoneNumberUtil->parse((string) $number, $country);
         // Determine locale
         $locale = $locale === NULL && $this->translator && method_exists($this->translator, 'getLocale') ? $this->translator->getLocale() : 'en_US';
         // Get phone number location
         return $this->phoneNumberGeocoder->getDescriptionForNumber($parsed, $locale, $userCountry);
     } else {
         throw new Exceptions\NoValidPhoneException('Provided phone number "' . $number . '" is not valid phone number. Provide valid phone number.');
     }
 }
Пример #29
0
 public function actionDefault(Throwable $exception)
 {
     if ($exception instanceof Nette\Application\BadRequestException) {
         $code = $exception->getCode();
         if ($this->logger) {
             $this->logger->log($exception->getMessage());
         }
     } else {
         $code = Nette\Http\IResponse::S500_INTERNAL_SERVER_ERROR;
         if ($this->logger) {
             $this->logger->log($exception, Tracy\ILogger::EXCEPTION);
         }
     }
     if (ob_get_level() && ob_get_length()) {
         $this->setLayout(FALSE);
     }
     $view = $this->getView();
     $this->setView($this->code = $this->translator instanceof Symfony\Component\Translation\TranslatorBagInterface && $this->translator->getCatalogue()->has(implode('.', ['error.message', $code, 'title']), 'web') && $this->translator->getCatalogue()->has(implode('.', ['error.message', $code, 'description']), 'web') ? $code : 0);
     if (!count($this->formatTemplateFiles())) {
         $this->setView($view);
     }
 }
Пример #30
0
 /**
  * @param $date
  * @return string
  */
 public function relativeDate($date)
 {
     if (is_int($date)) {
         $date = Nette\Utils\DateTime::from($date);
     }
     $diff = $date->diff(new Nette\Utils\DateTime());
     if ($diff->y > 0) {
         return $this->translator->translate('latteHelpers.relativeDate.xYearsAgo', min(2, $diff->y), ['years' => $diff->y]);
     }
     if ($diff->m > 0) {
         return $this->translator->translate('latteHelpers.relativeDate.xMonthsAgo', min(2, $diff->m), ['months' => $diff->m]);
     }
     if ($diff->d > 0) {
         return $this->translator->translate('latteHelpers.relativeDate.xDaysAgo', min(2, $diff->d), ['days' => $diff->d]);
     }
     if ($diff->h > 0) {
         return $this->translator->translate('latteHelpers.relativeDate.xHoursAgo', min(2, $diff->h), ['hours' => $diff->h]);
     }
     if ($diff->i > 0) {
         return $this->translator->translate('latteHelpers.relativeDate.xMinutesAgo', min(2, $diff->i), ['minutes' => $diff->i]);
     }
     return $this->translator->translate('latteHelpers.relativeDate.fewSecondsAgo');
 }