comparison core/lib/Drupal/Component/Gettext/PoStreamReader.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 1fec387a4317
children
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
1 <?php 1 <?php
2 2
3 namespace Drupal\Component\Gettext; 3 namespace Drupal\Component\Gettext;
4 4
5 use Drupal\Component\Utility\SafeMarkup; 5 use Drupal\Component\Render\FormattableMarkup;
6 6
7 /** 7 /**
8 * Implements Gettext PO stream reader. 8 * Implements Gettext PO stream reader.
9 * 9 *
10 * The PO file format parsing is implemented according to the documentation at 10 * The PO file format parsing is implemented according to the documentation at
15 /** 15 /**
16 * Source line number of the stream being parsed. 16 * Source line number of the stream being parsed.
17 * 17 *
18 * @var int 18 * @var int
19 */ 19 */
20 private $_line_number = 0; 20 protected $lineNumber = 0;
21 21
22 /** 22 /**
23 * Parser context for the stream reader state machine. 23 * Parser context for the stream reader state machine.
24 * 24 *
25 * Possible contexts are: 25 * Possible contexts are:
30 * - 'MSGSTR' (msgstr or msgstr[]) 30 * - 'MSGSTR' (msgstr or msgstr[])
31 * - 'MSGSTR_ARR' (msgstr_arg) 31 * - 'MSGSTR_ARR' (msgstr_arg)
32 * 32 *
33 * @var string 33 * @var string
34 */ 34 */
35 private $_context = 'COMMENT'; 35 protected $context = 'COMMENT';
36 36
37 /** 37 /**
38 * Current entry being read. Incomplete. 38 * Current entry being read. Incomplete.
39 * 39 *
40 * @var array 40 * @var array
41 */ 41 */
42 private $_current_item = []; 42 protected $currentItem = [];
43 43
44 /** 44 /**
45 * Current plural index for plural translations. 45 * Current plural index for plural translations.
46 * 46 *
47 * @var int 47 * @var int
48 */ 48 */
49 private $_current_plural_index = 0; 49 protected $currentPluralIndex = 0;
50 50
51 /** 51 /**
52 * URI of the PO stream that is being read. 52 * URI of the PO stream that is being read.
53 * 53 *
54 * @var string 54 * @var string
55 */ 55 */
56 private $_uri = ''; 56 protected $uri = '';
57 57
58 /** 58 /**
59 * Language code for the PO stream being read. 59 * Language code for the PO stream being read.
60 * 60 *
61 * @var string 61 * @var string
62 */ 62 */
63 private $_langcode = NULL; 63 protected $langcode = NULL;
64 64
65 /** 65 /**
66 * File handle of the current PO stream. 66 * File handle of the current PO stream.
67 * 67 *
68 * @var resource 68 * @var resource
69 */ 69 */
70 private $_fd; 70 protected $fd;
71 71
72 /** 72 /**
73 * The PO stream header. 73 * The PO stream header.
74 * 74 *
75 * @var \Drupal\Component\Gettext\PoHeader 75 * @var \Drupal\Component\Gettext\PoHeader
76 */ 76 */
77 private $_header; 77 protected $header;
78 78
79 /** 79 /**
80 * Object wrapper for the last read source/translation pair. 80 * Object wrapper for the last read source/translation pair.
81 * 81 *
82 * @var \Drupal\Component\Gettext\PoItem 82 * @var \Drupal\Component\Gettext\PoItem
83 */ 83 */
84 private $_last_item; 84 protected $lastItem;
85 85
86 /** 86 /**
87 * Indicator of whether the stream reading is finished. 87 * Indicator of whether the stream reading is finished.
88 * 88 *
89 * @var bool 89 * @var bool
90 */ 90 */
91 private $_finished; 91 protected $finished;
92 92
93 /** 93 /**
94 * Array of translated error strings recorded on reading this stream so far. 94 * Array of translated error strings recorded on reading this stream so far.
95 * 95 *
96 * @var array 96 * @var array
97 */ 97 */
98 private $_errors; 98 protected $errors;
99 99
100 /** 100 /**
101 * {@inheritdoc} 101 * {@inheritdoc}
102 */ 102 */
103 public function getLangcode() { 103 public function getLangcode() {
104 return $this->_langcode; 104 return $this->langcode;
105 } 105 }
106 106
107 /** 107 /**
108 * {@inheritdoc} 108 * {@inheritdoc}
109 */ 109 */
110 public function setLangcode($langcode) { 110 public function setLangcode($langcode) {
111 $this->_langcode = $langcode; 111 $this->langcode = $langcode;
112 } 112 }
113 113
114 /** 114 /**
115 * {@inheritdoc} 115 * {@inheritdoc}
116 */ 116 */
117 public function getHeader() { 117 public function getHeader() {
118 return $this->_header; 118 return $this->header;
119 } 119 }
120 120
121 /** 121 /**
122 * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader(). 122 * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader().
123 * 123 *
128 128
129 /** 129 /**
130 * {@inheritdoc} 130 * {@inheritdoc}
131 */ 131 */
132 public function getURI() { 132 public function getURI() {
133 return $this->_uri; 133 return $this->uri;
134 } 134 }
135 135
136 /** 136 /**
137 * {@inheritdoc} 137 * {@inheritdoc}
138 */ 138 */
139 public function setURI($uri) { 139 public function setURI($uri) {
140 $this->_uri = $uri; 140 $this->uri = $uri;
141 } 141 }
142 142
143 /** 143 /**
144 * Implements Drupal\Component\Gettext\PoStreamInterface::open(). 144 * Implements Drupal\Component\Gettext\PoStreamInterface::open().
145 * 145 *
148 * 148 *
149 * @throws \Exception 149 * @throws \Exception
150 * If the URI is not yet set. 150 * If the URI is not yet set.
151 */ 151 */
152 public function open() { 152 public function open() {
153 if (!empty($this->_uri)) { 153 if (!empty($this->uri)) {
154 $this->_fd = fopen($this->_uri, 'rb'); 154 $this->fd = fopen($this->uri, 'rb');
155 $this->readHeader(); 155 $this->readHeader();
156 } 156 }
157 else { 157 else {
158 throw new \Exception('Cannot open stream without URI set.'); 158 throw new \Exception('Cannot open stream without URI set.');
159 } 159 }
164 * 164 *
165 * @throws \Exception 165 * @throws \Exception
166 * If the stream is not open. 166 * If the stream is not open.
167 */ 167 */
168 public function close() { 168 public function close() {
169 if ($this->_fd) { 169 if ($this->fd) {
170 fclose($this->_fd); 170 fclose($this->fd);
171 } 171 }
172 else { 172 else {
173 throw new \Exception('Cannot close stream that is not open.'); 173 throw new \Exception('Cannot close stream that is not open.');
174 } 174 }
175 } 175 }
177 /** 177 /**
178 * {@inheritdoc} 178 * {@inheritdoc}
179 */ 179 */
180 public function readItem() { 180 public function readItem() {
181 // Clear out the last item. 181 // Clear out the last item.
182 $this->_last_item = NULL; 182 $this->lastItem = NULL;
183 183
184 // Read until finished with the stream or a complete item was identified. 184 // Read until finished with the stream or a complete item was identified.
185 while (!$this->_finished && is_null($this->_last_item)) { 185 while (!$this->finished && is_null($this->lastItem)) {
186 $this->readLine(); 186 $this->readLine();
187 } 187 }
188 188
189 return $this->_last_item; 189 return $this->lastItem;
190 } 190 }
191 191
192 /** 192 /**
193 * Sets the seek position for the current PO stream. 193 * Sets the seek position for the current PO stream.
194 * 194 *
195 * @param int $seek 195 * @param int $seek
196 * The new seek position to set. 196 * The new seek position to set.
197 */ 197 */
198 public function setSeek($seek) { 198 public function setSeek($seek) {
199 fseek($this->_fd, $seek); 199 fseek($this->fd, $seek);
200 } 200 }
201 201
202 /** 202 /**
203 * Gets the pointer position of the current PO stream. 203 * Gets the pointer position of the current PO stream.
204 */ 204 */
205 public function getSeek() { 205 public function getSeek() {
206 return ftell($this->_fd); 206 return ftell($this->fd);
207 } 207 }
208 208
209 /** 209 /**
210 * Read the header from the PO stream. 210 * Read the header from the PO stream.
211 * 211 *
219 if (!$item) { 219 if (!$item) {
220 return; 220 return;
221 } 221 }
222 $header = new PoHeader(); 222 $header = new PoHeader();
223 $header->setFromString(trim($item->getTranslation())); 223 $header->setFromString(trim($item->getTranslation()));
224 $this->_header = $header; 224 $this->header = $header;
225 } 225 }
226 226
227 /** 227 /**
228 * Reads a line from the PO stream and stores data internally. 228 * Reads a line from the PO stream and stores data internally.
229 * 229 *
230 * Expands $this->_current_item based on new data for the current item. If 230 * Expands $this->current_item based on new data for the current item. If
231 * this line ends the current item, it is saved with setItemFromArray() with 231 * this line ends the current item, it is saved with setItemFromArray() with
232 * data from $this->_current_item. 232 * data from $this->current_item.
233 * 233 *
234 * An internal state machine is maintained in this reader using 234 * An internal state machine is maintained in this reader using
235 * $this->_context as the reading state. PO items are in between COMMENT 235 * $this->context as the reading state. PO items are in between COMMENT
236 * states (when items have at least one line or comment in between them) or 236 * states (when items have at least one line or comment in between them) or
237 * indicated by MSGSTR or MSGSTR_ARR followed immediately by an MSGID or 237 * indicated by MSGSTR or MSGSTR_ARR followed immediately by an MSGID or
238 * MSGCTXT (when items closely follow each other). 238 * MSGCTXT (when items closely follow each other).
239 * 239 *
240 * @return 240 * @return
243 * for later presentation. 243 * for later presentation.
244 */ 244 */
245 private function readLine() { 245 private function readLine() {
246 // Read a line and set the stream finished indicator if it was not 246 // Read a line and set the stream finished indicator if it was not
247 // possible anymore. 247 // possible anymore.
248 $line = fgets($this->_fd); 248 $line = fgets($this->fd);
249 $this->_finished = ($line === FALSE); 249 $this->finished = ($line === FALSE);
250 250
251 if (!$this->_finished) { 251 if (!$this->finished) {
252 252
253 if ($this->_line_number == 0) { 253 if ($this->lineNumber == 0) {
254 // The first line might come with a UTF-8 BOM, which should be removed. 254 // The first line might come with a UTF-8 BOM, which should be removed.
255 $line = str_replace("\xEF\xBB\xBF", '', $line); 255 $line = str_replace("\xEF\xBB\xBF", '', $line);
256 // Current plurality for 'msgstr[]'. 256 // Current plurality for 'msgstr[]'.
257 $this->_current_plural_index = 0; 257 $this->currentPluralIndex = 0;
258 } 258 }
259 259
260 // Track the line number for error reporting. 260 // Track the line number for error reporting.
261 $this->_line_number++; 261 $this->lineNumber++;
262 262
263 // Initialize common values for error logging. 263 // Initialize common values for error logging.
264 $log_vars = [ 264 $log_vars = [
265 '%uri' => $this->getURI(), 265 '%uri' => $this->getURI(),
266 '%line' => $this->_line_number, 266 '%line' => $this->lineNumber,
267 ]; 267 ];
268 268
269 // Trim away the linefeed. \\n might appear at the end of the string if 269 // Trim away the linefeed. \\n might appear at the end of the string if
270 // another line continuing the same string follows. We can remove that. 270 // another line continuing the same string follows. We can remove that.
271 $line = trim(strtr($line, ["\\\n" => ""])); 271 $line = trim(strtr($line, ["\\\n" => ""]));
272 272
273 if (!strncmp('#', $line, 1)) { 273 if (!strncmp('#', $line, 1)) {
274 // Lines starting with '#' are comments. 274 // Lines starting with '#' are comments.
275 275
276 if ($this->_context == 'COMMENT') { 276 if ($this->context == 'COMMENT') {
277 // Already in comment context, add to current comment. 277 // Already in comment context, add to current comment.
278 $this->_current_item['#'][] = substr($line, 1); 278 $this->currentItem['#'][] = substr($line, 1);
279 } 279 }
280 elseif (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) { 280 elseif (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
281 // We are currently in string context, save current item. 281 // We are currently in string context, save current item.
282 $this->setItemFromArray($this->_current_item); 282 $this->setItemFromArray($this->currentItem);
283 283
284 // Start a new entry for the comment. 284 // Start a new entry for the comment.
285 $this->_current_item = []; 285 $this->currentItem = [];
286 $this->_current_item['#'][] = substr($line, 1); 286 $this->currentItem['#'][] = substr($line, 1);
287 287
288 $this->_context = 'COMMENT'; 288 $this->context = 'COMMENT';
289 return; 289 return;
290 } 290 }
291 else { 291 else {
292 // A comment following any other context is a syntax error. 292 // A comment following any other context is a syntax error.
293 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr" was expected but not found on line %line.', $log_vars); 293 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr" was expected but not found on line %line.', $log_vars);
294 return FALSE; 294 return FALSE;
295 } 295 }
296 return; 296 return;
297 } 297 }
298 elseif (!strncmp('msgid_plural', $line, 12)) { 298 elseif (!strncmp('msgid_plural', $line, 12)) {
299 // A plural form for the current source string. 299 // A plural form for the current source string.
300 300
301 if ($this->_context != 'MSGID') { 301 if ($this->context != 'MSGID') {
302 // A plural form can only be added to an msgid directly. 302 // A plural form can only be added to an msgid directly.
303 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgid_plural" was expected but not found on line %line.', $log_vars); 303 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgid_plural" was expected but not found on line %line.', $log_vars);
304 return FALSE; 304 return FALSE;
305 } 305 }
306 306
307 // Remove 'msgid_plural' and trim away whitespace. 307 // Remove 'msgid_plural' and trim away whitespace.
308 $line = trim(substr($line, 12)); 308 $line = trim(substr($line, 12));
309 309
310 // Only the plural source string is left, parse it. 310 // Only the plural source string is left, parse it.
311 $quoted = $this->parseQuoted($line); 311 $quoted = $this->parseQuoted($line);
312 if ($quoted === FALSE) { 312 if ($quoted === FALSE) {
313 // The plural form must be wrapped in quotes. 313 // The plural form must be wrapped in quotes.
314 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains a syntax error on line %line.', $log_vars); 314 $this->errors[] = new FormattableMarkup('The translation stream %uri contains a syntax error on line %line.', $log_vars);
315 return FALSE; 315 return FALSE;
316 } 316 }
317 317
318 // Append the plural source to the current entry. 318 // Append the plural source to the current entry.
319 if (is_string($this->_current_item['msgid'])) { 319 if (is_string($this->currentItem['msgid'])) {
320 // The first value was stored as string. Now we know the context is 320 // The first value was stored as string. Now we know the context is
321 // plural, it is converted to array. 321 // plural, it is converted to array.
322 $this->_current_item['msgid'] = [$this->_current_item['msgid']]; 322 $this->currentItem['msgid'] = [$this->currentItem['msgid']];
323 } 323 }
324 $this->_current_item['msgid'][] = $quoted; 324 $this->currentItem['msgid'][] = $quoted;
325 325
326 $this->_context = 'MSGID_PLURAL'; 326 $this->context = 'MSGID_PLURAL';
327 return; 327 return;
328 } 328 }
329 elseif (!strncmp('msgid', $line, 5)) { 329 elseif (!strncmp('msgid', $line, 5)) {
330 // Starting a new message. 330 // Starting a new message.
331 331
332 if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) { 332 if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
333 // We are currently in string context, save current item. 333 // We are currently in string context, save current item.
334 $this->setItemFromArray($this->_current_item); 334 $this->setItemFromArray($this->currentItem);
335 335
336 // Start a new context for the msgid. 336 // Start a new context for the msgid.
337 $this->_current_item = []; 337 $this->currentItem = [];
338 } 338 }
339 elseif ($this->_context == 'MSGID') { 339 elseif ($this->context == 'MSGID') {
340 // We are currently already in the context, meaning we passed an id with no data. 340 // We are currently already in the context, meaning we passed an id with no data.
341 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgid" is unexpected on line %line.', $log_vars); 341 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgid" is unexpected on line %line.', $log_vars);
342 return FALSE; 342 return FALSE;
343 } 343 }
344 344
345 // Remove 'msgid' and trim away whitespace. 345 // Remove 'msgid' and trim away whitespace.
346 $line = trim(substr($line, 5)); 346 $line = trim(substr($line, 5));
347 347
348 // Only the message id string is left, parse it. 348 // Only the message id string is left, parse it.
349 $quoted = $this->parseQuoted($line); 349 $quoted = $this->parseQuoted($line);
350 if ($quoted === FALSE) { 350 if ($quoted === FALSE) {
351 // The message id must be wrapped in quotes. 351 // The message id must be wrapped in quotes.
352 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgid" on line %line.', $log_vars, $log_vars); 352 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgid" on line %line.', $log_vars, $log_vars);
353 return FALSE; 353 return FALSE;
354 } 354 }
355 355
356 $this->_current_item['msgid'] = $quoted; 356 $this->currentItem['msgid'] = $quoted;
357 $this->_context = 'MSGID'; 357 $this->context = 'MSGID';
358 return; 358 return;
359 } 359 }
360 elseif (!strncmp('msgctxt', $line, 7)) { 360 elseif (!strncmp('msgctxt', $line, 7)) {
361 // Starting a new context. 361 // Starting a new context.
362 362
363 if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) { 363 if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
364 // We are currently in string context, save current item. 364 // We are currently in string context, save current item.
365 $this->setItemFromArray($this->_current_item); 365 $this->setItemFromArray($this->currentItem);
366 $this->_current_item = []; 366 $this->currentItem = [];
367 } 367 }
368 elseif (!empty($this->_current_item['msgctxt'])) { 368 elseif (!empty($this->currentItem['msgctxt'])) {
369 // A context cannot apply to another context. 369 // A context cannot apply to another context.
370 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgctxt" is unexpected on line %line.', $log_vars); 370 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgctxt" is unexpected on line %line.', $log_vars);
371 return FALSE; 371 return FALSE;
372 } 372 }
373 373
374 // Remove 'msgctxt' and trim away whitespaces. 374 // Remove 'msgctxt' and trim away whitespaces.
375 $line = trim(substr($line, 7)); 375 $line = trim(substr($line, 7));
376 376
377 // Only the msgctxt string is left, parse it. 377 // Only the msgctxt string is left, parse it.
378 $quoted = $this->parseQuoted($line); 378 $quoted = $this->parseQuoted($line);
379 if ($quoted === FALSE) { 379 if ($quoted === FALSE) {
380 // The context string must be quoted. 380 // The context string must be quoted.
381 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgctxt" on line %line.', $log_vars); 381 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgctxt" on line %line.', $log_vars);
382 return FALSE; 382 return FALSE;
383 } 383 }
384 384
385 $this->_current_item['msgctxt'] = $quoted; 385 $this->currentItem['msgctxt'] = $quoted;
386 386
387 $this->_context = 'MSGCTXT'; 387 $this->context = 'MSGCTXT';
388 return; 388 return;
389 } 389 }
390 elseif (!strncmp('msgstr[', $line, 7)) { 390 elseif (!strncmp('msgstr[', $line, 7)) {
391 // A message string for a specific plurality. 391 // A message string for a specific plurality.
392 392
393 if (($this->_context != 'MSGID') && 393 if (($this->context != 'MSGID') &&
394 ($this->_context != 'MSGCTXT') && 394 ($this->context != 'MSGCTXT') &&
395 ($this->_context != 'MSGID_PLURAL') && 395 ($this->context != 'MSGID_PLURAL') &&
396 ($this->_context != 'MSGSTR_ARR')) { 396 ($this->context != 'MSGSTR_ARR')) {
397 // Plural message strings must come after msgid, msgxtxt, 397 // Plural message strings must come after msgid, msgctxt,
398 // msgid_plural, or other msgstr[] entries. 398 // msgid_plural, or other msgstr[] entries.
399 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars); 399 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
400 return FALSE; 400 return FALSE;
401 } 401 }
402 402
403 // Ensure the plurality is terminated. 403 // Ensure the plurality is terminated.
404 if (strpos($line, ']') === FALSE) { 404 if (strpos($line, ']') === FALSE) {
405 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars); 405 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
406 return FALSE; 406 return FALSE;
407 } 407 }
408 408
409 // Extract the plurality. 409 // Extract the plurality.
410 $frombracket = strstr($line, '['); 410 $frombracket = strstr($line, '[');
411 $this->_current_plural_index = substr($frombracket, 1, strpos($frombracket, ']') - 1); 411 $this->currentPluralIndex = substr($frombracket, 1, strpos($frombracket, ']') - 1);
412 412
413 // Skip to the next whitespace and trim away any further whitespace, 413 // Skip to the next whitespace and trim away any further whitespace,
414 // bringing $line to the message text only. 414 // bringing $line to the message text only.
415 $line = trim(strstr($line, " ")); 415 $line = trim(strstr($line, " "));
416 416
417 $quoted = $this->parseQuoted($line); 417 $quoted = $this->parseQuoted($line);
418 if ($quoted === FALSE) { 418 if ($quoted === FALSE) {
419 // The string must be quoted. 419 // The string must be quoted.
420 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars); 420 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
421 return FALSE; 421 return FALSE;
422 } 422 }
423 if (!isset($this->_current_item['msgstr']) || !is_array($this->_current_item['msgstr'])) { 423 if (!isset($this->currentItem['msgstr']) || !is_array($this->currentItem['msgstr'])) {
424 $this->_current_item['msgstr'] = []; 424 $this->currentItem['msgstr'] = [];
425 } 425 }
426 426
427 $this->_current_item['msgstr'][$this->_current_plural_index] = $quoted; 427 $this->currentItem['msgstr'][$this->currentPluralIndex] = $quoted;
428 428
429 $this->_context = 'MSGSTR_ARR'; 429 $this->context = 'MSGSTR_ARR';
430 return; 430 return;
431 } 431 }
432 elseif (!strncmp("msgstr", $line, 6)) { 432 elseif (!strncmp("msgstr", $line, 6)) {
433 // A string pair for an msgid (with optional context). 433 // A string pair for an msgid (with optional context).
434 434
435 if (($this->_context != 'MSGID') && ($this->_context != 'MSGCTXT')) { 435 if (($this->context != 'MSGID') && ($this->context != 'MSGCTXT')) {
436 // Strings are only valid within an id or context scope. 436 // Strings are only valid within an id or context scope.
437 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr" is unexpected on line %line.', $log_vars); 437 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr" is unexpected on line %line.', $log_vars);
438 return FALSE; 438 return FALSE;
439 } 439 }
440 440
441 // Remove 'msgstr' and trim away away whitespaces. 441 // Remove 'msgstr' and trim away away whitespaces.
442 $line = trim(substr($line, 6)); 442 $line = trim(substr($line, 6));
443 443
444 // Only the msgstr string is left, parse it. 444 // Only the msgstr string is left, parse it.
445 $quoted = $this->parseQuoted($line); 445 $quoted = $this->parseQuoted($line);
446 if ($quoted === FALSE) { 446 if ($quoted === FALSE) {
447 // The string must be quoted. 447 // The string must be quoted.
448 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr" on line %line.', $log_vars); 448 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr" on line %line.', $log_vars);
449 return FALSE; 449 return FALSE;
450 } 450 }
451 451
452 $this->_current_item['msgstr'] = $quoted; 452 $this->currentItem['msgstr'] = $quoted;
453 453
454 $this->_context = 'MSGSTR'; 454 $this->context = 'MSGSTR';
455 return; 455 return;
456 } 456 }
457 elseif ($line != '') { 457 elseif ($line != '') {
458 // Anything that is not a token may be a continuation of a previous token. 458 // Anything that is not a token may be a continuation of a previous token.
459 459
460 $quoted = $this->parseQuoted($line); 460 $quoted = $this->parseQuoted($line);
461 if ($quoted === FALSE) { 461 if ($quoted === FALSE) {
462 // This string must be quoted. 462 // This string must be quoted.
463 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: string continuation expected on line %line.', $log_vars); 463 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: string continuation expected on line %line.', $log_vars);
464 return FALSE; 464 return FALSE;
465 } 465 }
466 466
467 // Append the string to the current item. 467 // Append the string to the current item.
468 if (($this->_context == 'MSGID') || ($this->_context == 'MSGID_PLURAL')) { 468 if (($this->context == 'MSGID') || ($this->context == 'MSGID_PLURAL')) {
469 if (is_array($this->_current_item['msgid'])) { 469 if (is_array($this->currentItem['msgid'])) {
470 // Add string to last array element for plural sources. 470 // Add string to last array element for plural sources.
471 $last_index = count($this->_current_item['msgid']) - 1; 471 $last_index = count($this->currentItem['msgid']) - 1;
472 $this->_current_item['msgid'][$last_index] .= $quoted; 472 $this->currentItem['msgid'][$last_index] .= $quoted;
473 } 473 }
474 else { 474 else {
475 // Singular source, just append the string. 475 // Singular source, just append the string.
476 $this->_current_item['msgid'] .= $quoted; 476 $this->currentItem['msgid'] .= $quoted;
477 } 477 }
478 } 478 }
479 elseif ($this->_context == 'MSGCTXT') { 479 elseif ($this->context == 'MSGCTXT') {
480 // Multiline context name. 480 // Multiline context name.
481 $this->_current_item['msgctxt'] .= $quoted; 481 $this->currentItem['msgctxt'] .= $quoted;
482 } 482 }
483 elseif ($this->_context == 'MSGSTR') { 483 elseif ($this->context == 'MSGSTR') {
484 // Multiline translation string. 484 // Multiline translation string.
485 $this->_current_item['msgstr'] .= $quoted; 485 $this->currentItem['msgstr'] .= $quoted;
486 } 486 }
487 elseif ($this->_context == 'MSGSTR_ARR') { 487 elseif ($this->context == 'MSGSTR_ARR') {
488 // Multiline plural translation string. 488 // Multiline plural translation string.
489 $this->_current_item['msgstr'][$this->_current_plural_index] .= $quoted; 489 $this->currentItem['msgstr'][$this->currentPluralIndex] .= $quoted;
490 } 490 }
491 else { 491 else {
492 // No valid context to append to. 492 // No valid context to append to.
493 $this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: unexpected string on line %line.', $log_vars); 493 $this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: unexpected string on line %line.', $log_vars);
494 return FALSE; 494 return FALSE;
495 } 495 }
496 return; 496 return;
497 } 497 }
498 } 498 }
499 499
500 // Empty line read or EOF of PO stream, close out the last entry. 500 // Empty line read or EOF of PO stream, close out the last entry.
501 if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) { 501 if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
502 $this->setItemFromArray($this->_current_item); 502 $this->setItemFromArray($this->currentItem);
503 $this->_current_item = []; 503 $this->currentItem = [];
504 } 504 }
505 elseif ($this->_context != 'COMMENT') { 505 elseif ($this->context != 'COMMENT') {
506 $this->_errors[] = SafeMarkup::format('The translation stream %uri ended unexpectedly at line %line.', $log_vars); 506 $this->errors[] = new FormattableMarkup('The translation stream %uri ended unexpectedly at line %line.', $log_vars);
507 return FALSE; 507 return FALSE;
508 } 508 }
509 509
510 return; 510 return;
511 } 511 }
531 $item->setContext(isset($value['msgctxt']) ? $value['msgctxt'] : ''); 531 $item->setContext(isset($value['msgctxt']) ? $value['msgctxt'] : '');
532 $item->setSource($value['msgid']); 532 $item->setSource($value['msgid']);
533 $item->setTranslation($value['msgstr']); 533 $item->setTranslation($value['msgstr']);
534 $item->setPlural($plural); 534 $item->setPlural($plural);
535 $item->setComment($comments); 535 $item->setComment($comments);
536 $item->setLangcode($this->_langcode); 536 $item->setLangcode($this->langcode);
537 537
538 $this->_last_item = $item; 538 $this->lastItem = $item;
539 539
540 $this->_context = 'COMMENT'; 540 $this->context = 'COMMENT';
541 } 541 }
542 542
543 /** 543 /**
544 * Parses a string in quotes. 544 * Parses a string in quotes.
545 * 545 *