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