Chris@0: t(). Otherwise Chris@0: * create a new \Drupal\Core\StringTranslation\TranslatableMarkup object Chris@0: * directly. Chris@0: * Chris@0: * Calling the trait's t() method or instantiating a new TranslatableMarkup Chris@0: * object serves two purposes: Chris@0: * - At run-time it translates user-visible text into the appropriate Chris@0: * language. Chris@0: * - Static analyzers detect calls to t() and new TranslatableMarkup, and add Chris@0: * the first argument (the string to be translated) to the database of Chris@0: * strings that need translation. These strings are expected to be in Chris@0: * English, so the first argument should always be in English. Chris@0: * To allow the site to be localized, it is important that all human-readable Chris@0: * text that will be displayed on the site or sent to a user is made available Chris@0: * in one of the ways supported by the Chris@0: * @link https://www.drupal.org/node/322729 Localization API @endlink. Chris@0: * See the @link https://www.drupal.org/node/322729 Localization API @endlink Chris@0: * pages for more information, including recommendations on how to break up or Chris@0: * not break up strings for translation. Chris@0: * Chris@0: * @section sec_translating_vars Translating Variables Chris@0: * $string should always be an English literal string. Chris@0: * Chris@0: * $string should never contain a variable, such as: Chris@0: * @code Chris@0: * new TranslatableMarkup($text) Chris@0: * @endcode Chris@0: * There are several reasons for this: Chris@0: * - Using a variable for $string that is user input is a security risk. Chris@0: * - Using a variable for $string that has even guaranteed safe text (for Chris@0: * example, user interface text provided literally in code), will not be Chris@0: * picked up by the localization static text processor. (The parameter could Chris@0: * be a variable if the entire string in $text has been passed into t() or Chris@0: * new TranslatableMarkup() elsewhere as the first argument, but that Chris@0: * strategy is not recommended.) Chris@0: * Chris@0: * It is especially important never to call new TranslatableMarkup($user_text) Chris@0: * or t($user_text) where $user_text is some text that a user entered -- doing Chris@0: * that can lead to cross-site scripting and other security problems. However, Chris@0: * you can use variable substitution in your string, to put variable text such Chris@0: * as user names or link URLs into translated text. Variable substitution Chris@0: * looks like this: Chris@0: * @code Chris@0: * new TranslatableMarkup("@name's blog", array('@name' => $account->getDisplayName())); Chris@0: * @endcode Chris@0: * Basically, you can put placeholders like @name into your string, and the Chris@0: * method will substitute the sanitized values at translation time. (See the Chris@0: * Localization API pages referenced above and the documentation of Chris@0: * \Drupal\Component\Render\FormattableMarkup::placeholderFormat() Chris@0: * for details about how to safely and correctly define variables in your Chris@0: * string.) Translators can then rearrange the string as necessary for the Chris@0: * language (e.g., in Spanish, it might be "blog de @name"). Chris@0: * Chris@0: * @param string $string Chris@0: * A string containing the English text to translate. Chris@0: * @param array $arguments Chris@0: * (optional) An associative array of replacements to make after Chris@0: * translation. Based on the first character of the key, the value is Chris@0: * escaped and/or themed. See Chris@0: * \Drupal\Component\Render\FormattableMarkup::placeholderFormat() for Chris@0: * details. Chris@0: * @param array $options Chris@0: * (optional) An associative array of additional options, with the following Chris@0: * elements: Chris@0: * - 'langcode' (defaults to the current language): A language code, to Chris@0: * translate to a language other than what is used to display the page. Chris@0: * - 'context' (defaults to the empty context): The context the source Chris@0: * string belongs to. Chris@0: * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation Chris@0: * (optional) The string translation service. Chris@0: * Chris@0: * @throws \InvalidArgumentException Chris@0: * Exception thrown when $string is not a string. Chris@0: * Chris@0: * @see \Drupal\Component\Render\FormattableMarkup::placeholderFormat() Chris@0: * @see \Drupal\Core\StringTranslation\StringTranslationTrait::t() Chris@0: * Chris@0: * @ingroup sanitization Chris@0: */ Chris@0: public function __construct($string, array $arguments = [], array $options = [], TranslationInterface $string_translation = NULL) { Chris@0: if (!is_string($string)) { Chris@0: $message = $string instanceof TranslatableMarkup ? '$string ("' . $string->getUntranslatedString() . '") must be a string.' : '$string ("' . (string) $string . '") must be a string.'; Chris@0: throw new \InvalidArgumentException($message); Chris@0: } Chris@14: parent::__construct($string, $arguments); Chris@0: $this->options = $options; Chris@0: $this->stringTranslation = $string_translation; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the untranslated string value stored in this translated string. Chris@0: * Chris@0: * @return string Chris@0: * The string stored in this wrapper. Chris@0: */ Chris@0: public function getUntranslatedString() { Chris@0: return $this->string; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets a specific option from this translated string. Chris@0: * Chris@0: * @param string $name Chris@0: * Option name. Chris@0: * Chris@0: * @return mixed Chris@0: * The value of this option or empty string of option is not set. Chris@0: */ Chris@0: public function getOption($name) { Chris@0: return isset($this->options[$name]) ? $this->options[$name] : ''; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets all options from this translated string. Chris@0: * Chris@0: * @return mixed[] Chris@0: * The array of options. Chris@0: */ Chris@0: public function getOptions() { Chris@0: return $this->options; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets all arguments from this translated string. Chris@0: * Chris@0: * @return mixed[] Chris@0: * The array of arguments. Chris@0: */ Chris@0: public function getArguments() { Chris@0: return $this->arguments; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Renders the object as a string. Chris@0: * Chris@0: * @return string Chris@0: * The translated string. Chris@0: */ Chris@0: public function render() { Chris@0: if (!isset($this->translatedMarkup)) { Chris@0: $this->translatedMarkup = $this->getStringTranslation()->translateString($this); Chris@0: } Chris@0: Chris@0: // Handle any replacements. Chris@0: if ($args = $this->getArguments()) { Chris@0: return $this->placeholderFormat($this->translatedMarkup, $args); Chris@0: } Chris@0: return $this->translatedMarkup; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Magic __sleep() method to avoid serializing the string translator. Chris@0: */ Chris@0: public function __sleep() { Chris@0: return ['string', 'arguments', 'options']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the string translation service. Chris@0: * Chris@0: * @return \Drupal\Core\StringTranslation\TranslationInterface Chris@0: * The string translation service. Chris@0: */ Chris@0: protected function getStringTranslation() { Chris@0: if (!$this->stringTranslation) { Chris@0: $this->stringTranslation = \Drupal::service('string_translation'); Chris@0: } Chris@0: Chris@0: return $this->stringTranslation; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns the string length. Chris@0: * Chris@0: * @return int Chris@0: * The length of the string. Chris@0: */ Chris@0: public function count() { Chris@17: return mb_strlen($this->render()); Chris@0: } Chris@0: Chris@0: }