annotate core/lib/Drupal/Core/StringTranslation/PluralTranslatableMarkup.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\StringTranslation;
Chris@0 4
Chris@18 5 use Drupal\Component\Gettext\PoItem;
Chris@18 6
Chris@0 7 /**
Chris@0 8 * A class to hold plural translatable markup.
Chris@0 9 */
Chris@0 10 class PluralTranslatableMarkup extends TranslatableMarkup {
Chris@0 11
Chris@0 12 /**
Chris@0 13 * The delimiter used to split plural strings.
Chris@0 14 *
Chris@0 15 * This is the ETX (End of text) character and is used as a minimal means to
Chris@0 16 * separate singular and plural variants in source and translation text. It
Chris@0 17 * was found to be the most compatible delimiter for the supported databases.
Chris@18 18 *
Chris@18 19 * @deprecated in Drupal 8.7.x, will be removed before Drupal 9.0.0.
Chris@18 20 * Use Drupal\Component\Gettext\PoItem::DELIMITER instead.
Chris@0 21 */
Chris@18 22 const DELIMITER = PoItem::DELIMITER;
Chris@0 23
Chris@0 24 /**
Chris@0 25 * The item count to display.
Chris@0 26 *
Chris@0 27 * @var int
Chris@0 28 */
Chris@0 29 protected $count;
Chris@0 30
Chris@0 31 /**
Chris@0 32 * The already translated string.
Chris@0 33 *
Chris@0 34 * @var string
Chris@0 35 */
Chris@0 36 protected $translatedString;
Chris@0 37
Chris@0 38 /**
Chris@0 39 * Constructs a new PluralTranslatableMarkup object.
Chris@0 40 *
Chris@0 41 * Parses values passed into this class through the format_plural() function
Chris@0 42 * in Drupal and handles an optional context for the string.
Chris@0 43 *
Chris@0 44 * @param int $count
Chris@0 45 * The item count to display.
Chris@0 46 * @param string $singular
Chris@0 47 * The string for the singular case. Make sure it is clear this is singular,
Chris@0 48 * to ease translation (e.g. use "1 new comment" instead of "1 new"). Do not
Chris@0 49 * use @count in the singular string.
Chris@0 50 * @param string $plural
Chris@0 51 * The string for the plural case. Make sure it is clear this is plural, to
Chris@0 52 * ease translation. Use @count in place of the item count, as in
Chris@0 53 * "@count new comments".
Chris@0 54 * @param array $args
Chris@0 55 * (optional) An array with placeholder replacements, keyed by placeholder.
Chris@0 56 * See \Drupal\Component\Render\FormattableMarkup::placeholderFormat() for
Chris@0 57 * additional information about placeholders. Note that you do not need to
Chris@0 58 * include @count in this array; this replacement is done automatically
Chris@0 59 * for the plural cases.
Chris@0 60 * @param array $options
Chris@0 61 * (optional) An associative array of additional options. See t() for
Chris@0 62 * allowed keys.
Chris@0 63 * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
Chris@0 64 * (optional) The string translation service.
Chris@0 65 *
Chris@0 66 * @see \Drupal\Component\Render\FormattableMarkup::placeholderFormat()
Chris@0 67 */
Chris@0 68 public function __construct($count, $singular, $plural, array $args = [], array $options = [], TranslationInterface $string_translation = NULL) {
Chris@0 69 $this->count = $count;
Chris@18 70 $translatable_string = implode(PoItem::DELIMITER, [$singular, $plural]);
Chris@0 71 parent::__construct($translatable_string, $args, $options, $string_translation);
Chris@0 72 }
Chris@0 73
Chris@0 74 /**
Chris@0 75 * Constructs a new class instance from already translated markup.
Chris@0 76 *
Chris@0 77 * This method ensures that the string is pluralized correctly. As opposed
Chris@0 78 * to the __construct() method, this method is designed to be invoked with
Chris@0 79 * a string already translated (such as with configuration translation).
Chris@0 80 *
Chris@0 81 * @param int $count
Chris@0 82 * The item count to display.
Chris@0 83 * @param string $translated_string
Chris@0 84 * The already translated string.
Chris@0 85 * @param array $args
Chris@0 86 * An associative array of replacements to make after translation. Instances
Chris@0 87 * of any key in this array are replaced with the corresponding value.
Chris@0 88 * Based on the first character of the key, the value is escaped and/or
Chris@17 89 * themed. See \Drupal\Component\Render\FormattableMarkup. Note that you
Chris@0 90 * do not need to include @count in this array; this replacement is done
Chris@0 91 * automatically for the plural cases.
Chris@0 92 * @param array $options
Chris@0 93 * An associative array of additional options. See t() for allowed keys.
Chris@0 94 *
Chris@0 95 * @return \Drupal\Core\StringTranslation\PluralTranslatableMarkup
Chris@0 96 * A PluralTranslatableMarkup object.
Chris@0 97 */
Chris@0 98 public static function createFromTranslatedString($count, $translated_string, array $args = [], array $options = []) {
Chris@0 99 $plural = new static($count, '', '', $args, $options);
Chris@0 100 $plural->translatedString = $translated_string;
Chris@0 101 return $plural;
Chris@0 102 }
Chris@0 103
Chris@0 104 /**
Chris@0 105 * Renders the object as a string.
Chris@0 106 *
Chris@0 107 * @return string
Chris@0 108 * The translated string.
Chris@0 109 */
Chris@0 110 public function render() {
Chris@0 111 if (!$this->translatedString) {
Chris@0 112 $this->translatedString = $this->getStringTranslation()->translateString($this);
Chris@0 113 }
Chris@0 114 if ($this->translatedString === '') {
Chris@0 115 return '';
Chris@0 116 }
Chris@0 117
Chris@0 118 $arguments = $this->getArguments();
Chris@0 119 $arguments['@count'] = $this->count;
Chris@18 120 $translated_array = explode(PoItem::DELIMITER, $this->translatedString);
Chris@0 121
Chris@0 122 if ($this->count == 1) {
Chris@0 123 return $this->placeholderFormat($translated_array[0], $arguments);
Chris@0 124 }
Chris@0 125
Chris@0 126 $index = $this->getPluralIndex();
Chris@0 127 if ($index == 0) {
Chris@0 128 // Singular form.
Chris@0 129 $return = $translated_array[0];
Chris@0 130 }
Chris@0 131 else {
Chris@0 132 if (isset($translated_array[$index])) {
Chris@0 133 // N-th plural form.
Chris@0 134 $return = $translated_array[$index];
Chris@0 135 }
Chris@0 136 else {
Chris@0 137 // If the index cannot be computed or there's no translation, use the
Chris@0 138 // second plural form as a fallback (which allows for most flexibility
Chris@0 139 // with the replaceable @count value).
Chris@0 140 $return = $translated_array[1];
Chris@0 141 }
Chris@0 142 }
Chris@0 143
Chris@0 144 return $this->placeholderFormat($return, $arguments);
Chris@0 145 }
Chris@0 146
Chris@0 147 /**
Chris@0 148 * Gets the plural index through the gettext formula.
Chris@0 149 *
Chris@0 150 * @return int
Chris@0 151 */
Chris@0 152 protected function getPluralIndex() {
Chris@0 153 // We have to test both if the function and the service exist since in
Chris@0 154 // certain situations it is possible that locale code might be loaded but
Chris@0 155 // the service does not exist. For example, where the parent test site has
Chris@0 156 // locale installed but the child site does not.
Chris@0 157 // @todo Refactor in https://www.drupal.org/node/2660338 so this code does
Chris@0 158 // not depend on knowing that the Locale module exists.
Chris@0 159 if (function_exists('locale_get_plural') && \Drupal::hasService('locale.plural.formula')) {
Chris@0 160 return locale_get_plural($this->count, $this->getOption('langcode'));
Chris@0 161 }
Chris@0 162 return -1;
Chris@0 163 }
Chris@0 164
Chris@0 165 /**
Chris@0 166 * {@inheritdoc}
Chris@0 167 */
Chris@0 168 public function __sleep() {
Chris@0 169 return array_merge(parent::__sleep(), ['count']);
Chris@0 170 }
Chris@0 171
Chris@0 172 }