/var/www/html_de/wp-content/plugins/loco-translate/lib/compiled/gettext.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
<?php
/**
 * Downgraded for PHP 7.2 compatibility. Do not edit.
 * @noinspection ALL
 */
interface LocoArrayInterface extends ArrayAccessIteratorCountableJsonSerializable { }
class 
LocoHeaders extends ArrayIterator implements LocoArrayInterface 
private 
/*array*/ $map = []; 
public function 
__construct(array $raw = [] ){ if( $raw ){ $keys array_keys$raw ); $this->map array_combinearray_map'strtolower'$keys ), $keys ); parent::__construct($raw); } } 
public function 
normalizestring $k ):?string $k strtolower($k); return array_key_exists($k,$this->map) ? $this->map[$k] : null; } 
public function 
add($key$val ):self $this->offsetSet$key$val ); return $this; } 
public function 
__toString():string $pairs = []; foreach( $this as $key => $val ){ $pairs[] = $key.': '.$val; } return implode("\n"$pairs ); } 
public function 
trimmedstring $prop ):string { return trim$this->__get($prop) ); } 
public function 
hasstring $key):bool { return array_key_existsstrtolower($key), $this->map ); } 
public function 
__getstring $key ){ return $this->offsetGet$key ); } 
public function 
__setstring $key/*mixed*/ $val ):void $this->offsetSet$key$val ); } 
#[
ReturnTypeWillChange]
public function 
offsetExists/*mixed*/ $key ):bool { return $this->has($key); } 
#[
ReturnTypeWillChange]
public function 
offsetGet/*mixed*/ $key ) { $k $this->normalize($key); if( is_null($k) ){ return ''; } return parent::offsetGet($k); } 
#[
ReturnTypeWillChange]
public function 
offsetSet/*mixed*/ $key/*mixed*/ $value ):void $k strtolower($key); if( isset($this->map[$k]) && $key !== $this->map[$k] ){ parent::offsetUnset$this->map[$k] ); } $this->map[$k] = $keyparent::offsetSet$key$value ); } 
#[
ReturnTypeWillChange]
public function 
offsetUnset/*mixed*/ $key ):void $k strtolower($key); if( isset($this->map[$k]) ){ parent::offsetUnset$this->map[$k] ); unset( $this->map[$k] ); } } 
#[
ReturnTypeWillChange]
public function 
jsonSerialize():array { return $this->getArrayCopy(); } }
function 
loco_normalize_charsetstring $cs ):string { if( preg_match('/^UTF-?(8|16-?(LE|BE)?)$/i',$cs,$r,PREG_UNMATCHED_AS_NULL) ){ return '8' === $r[1] ? 'UTF-8' 'UTF-16'.$r[2]; } try { return mb_preferred_mime_name($cs); } catch( ValueError $e ){ try { if( preg_match('/^csISO(\\w+)/i',$cs,$r) || preg_match('/^(\\w+)8$/',$cs,$r) ){ return mb_preferred_mime_name($r[1]); } throw $e; } catch( ValueError $e ){ throw new InvalidArgumentException('Unsupported character encoding: '.$cs ); } } }
class 
LocoPoHeaders extends LocoHeaders 
private 
/*string*/ $cs null
public function 
getCharset():string $cs $this->cs; if( is_null($cs) ){ $cs ''$raw $this->offsetGet('content-type'); if( $raw && preg_match('!\\bcharset[= ]+([-\\w]+)!',$raw,$r) ){ try { $cs loco_normalize_charset($r[1]); } catch( InvalidArgumentException $e ){ } catch( Throwable $e ){ trigger_error$e->getMessage(), E_USER_NOTICE ); } } $this->cs $cs; } return $cs; } 
public function 
setCharsetstring $to ):string $to loco_normalize_charset($to); $from $this->getCharset(); $this->cs $to$this['Content-Type'] = 'text/plain; charset='.$to; if( '' !== $from && $from !== $to ){ foreach( $this as $key => $val ){ $this[$key] = mb_convert_encoding($val,$to,$from); } } return $to; } 
public static function 
fromMsgstrstring $str ):LocoPoHeaders $headers = new LocoPoHeaders$key ''; foreach( preg_split('/[\\r\\n]+/',$str) as $line ){ $i strpos($line,':'); if( is_int($i) ){ $key trimsubstr($line,0,$i), " \t" ); $headers->offsetSet$keyltrimsubstr($line,++$i)," \t" ) ); } else if( '' !== $key ){ $headers->offsetSet$key$headers->offsetGet($key)."\n".$line ); } } $cs $headers->getCharset(); if( '' !== $cs && 'UTF-8' !== $cs && 'UTF-8' !== mb_detect_encoding($str,['UTF-8',$cs],true) ){ foreach( $headers as $key => $val ){ $headers[$key] = mb_convert_encoding($val,'UTF-8',[$cs]); } } return $headers; } 
public static function 
fromSourcestring $raw ):LocoPoHeaders $po = new LocoPoParser($raw); $po->parse(0); return $po->getHeader(); } }
function 
loco_convert_utf8string $strstring $encbool $strict ):string { if( '' === $enc || 'UTF-8' === $enc || 'US-ASCII' === $enc ){ if( false === preg_match('//u',$str) ){ if( $strict ){ $e = new Loco_error_ParseException$enc 'Invalid '.$enc.' encoding' 'Unknown character encoding' ); if( preg_match('/^(?:[\\x00-\\x7F]|[\\xC0-\\xDF][\\x80-\\xBF]|[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xFF][\\x80-\\xBF]{3})*/',$str,$r) && $str !== $r[0] ){ $e->setOffsetContextstrlen($r[0]), $str ); } throw $e; } $str loco_fix_utf8($str); } } else if( 'ISO-8859-1' === $enc ) { $str mb_convert_encoding$str'UTF-8''Windows-1252' ); } else { $str mb_convert_encoding$str'UTF-8'$enc ); } return $str; }
function 
loco_fix_utf8string $str ):string $fix ''; while( is_string($str) && '' !== $str ){ if( preg_match('/^(?:[\\x00-\\x7F]|[\\xC0-\\xDF][\\x80-\\xBF]|[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xFF][\\x80-\\xBF]{3})+/',$str,$r) ){ $fix .= $r[0]; $str substr($strstrlen($r[0]) ); } else { $fix.= mb_convert_encoding$str[0], 'UTF-8''Windows-1252' ); $str substr($str,1); } } return loco_convert_utf8($fix,'',true); }
abstract class 
LocoGettextParser 
private 
/*LocoPoHeaders*/ $head null
private 
/*string*/ $cs ''
abstract public function 
parseint $limit = -):array; 
protected function 
setHeaderLocoPoHeaders $head ):LocoPoHeaders $this->head $head$cs $head->getCharset(); if( '' !== $cs ){ if( '' === $this->cs ){ $this->setCharset($cs); } } return $head; } 
public function 
getHeader():?LocoPoHeaders { return $this->head; } 
protected function 
setCharsetstring $cs ):void $this->cs $cs; } 
protected function 
getCharset():?string { return $this->cs; } 
protected function 
strstring $str ):string { if( '' !== $str ){ $str loco_convert_utf8($str,$this->cs,false); } return $str; } 
protected function 
initMsgKeystring $key ):array { $r explode("\4",$key); $value = [ 'source' => array_pop($r), 'target' => '', ]; if( isset($r[0]) ){ $value['context'] = $r[0]; } return $value; } }
function 
loco_remove_bomstring $s, &$c ):string $bom substr($s,0,2); if( "\xFF\xFE" === $bom ){ $c 'UTF-16LE'; return substr($s,2); } if( "\xFE\xFF" === $bom ){ $c 'UTF-16BE'; return substr($s,2); } if( "\xEF\xBB" === $bom && "\xBF" === $s[2] ){ $c 'UTF-8'; return substr($s,3); } $c ''; return $s; }
function 
loco_parse_reference_idstring $refs, &$_id ):string { if( false === ( $n strpos($refs,'loco:') ) ){ $_id ''; return $refs; } $_id substr($refs$n+524 ); $refs substr_replace$refs''$n29 ); return trim$refs ); }
class 
LocoPoParser extends LocoGettextParser implements Iterator 
private 
/*array*/ $lines = []; 
private 
/*int*/ $i
private 
/*int*/ $k
private 
/*array*/ $m
public function 
__constructstring $src ){ if( '' !== $src ){ $src loco_remove_bom($src,$cs); if( $cs && 'UTF-8' !== $cs ){ $src mb_convert_encoding$src'UTF-8'$cs ); $cs 'UTF-8'; } if( 'UTF-8' === $cs ){ $this->setCharset('UTF-8'); } $this->lines preg_split('/(\\r\\n?|\\n)/'$src ); } } 
#[
ReturnTypeWillChange]
public function 
rewind():void $this->= -1$this->= -1$this->next(); } 
#[
ReturnTypeWillChange]
public function 
valid():bool { return is_int($this->i); } 
#[
ReturnTypeWillChange]
public function 
key():?int { return $this->k; } 
#[
ReturnTypeWillChange]
public function 
current():?array { return $this->m; } 
#[
ReturnTypeWillChange]
public function 
next():void $valid false$entry = [ '#' => [], 'id' => [null], 'str' => [null] ]; $i $this->i; while( array_key_exists(++$i,$this->lines) ){ $line $this->lines[$i]; try { if( '' === $line ){ if( $valid ){ break; } continue; } $c $line[0]; if( '#' === $c ){ if( $valid ){ $i--; break; } if( '#' === $line ){ continue; } $f $line[1]; $entry['#'][$f][] = trimsubstr$line1+strlen($f) ), " \n\r\t"); } else if( preg_match('/^msg(id(?:_plural)?|ctxt|str(?:\\[(\\d+)])?)[ \\t]*/'$line$r ) ){ if( isset($r[2]) ){ $key 'str'$idx = (int) $r[2]; } else { $key $r[1]; $idx 0; } if( $valid && 'str' !== $key && null !== $entry['str'][0] ){ $i--; break; } $snip strlen($r[0]); if( '"' !== substr($line,$snip,1) ){ throw new Exception('Expected " to follow msg'.$key); } $val ''$line substr($line,$snip); while( true ){ if( '"' === $line || ! substr($line,-1) === '"' ){ throw new Exception('Unterminated msg'.$key ); } $val .= substr$line1, -); $j $i 1; if( array_key_exists($j,$this->lines) && ( $line $this->lines[$j] ) && '"' === $line[0] ){ $i $j; } else { break; } } if( ! $valid ){ $valid true; } if( 'id_plural' === $key ){ $key 'id'$idx 1; } $entry[$key][$idx] = stripcslashes($val); } else if( preg_match('/^[ \\t]+$/',$line) ){ if( $valid ) { break; } } else if( '"' === $c ){ throw new Exception('String encountered without keyword'); } else { throw new Exception('Junk'); } } catch( Exception $e ){ } } if( $valid ){ ++$this->k$this->$i$this->$entry; } else { $this->null$this->null$this->null; } } 
public function 
parseint $limit = -):array { $this->rewind(); if( ! $this->valid() ){ throw new Loco_error_ParseException('Invalid PO file'); } $entry $this->current(); if( '' !== $entry['id'][0] || isset($entry['ctxt']) || is_null($entry['str'][0]) ){ $head $this->setHeader( new LocoPoHeaders ); } else { $head $this->setHeaderLocoPoHeaders::fromMsgstr($entry['str'][0]) ); } if( === $limit ){ return []; } $i = -1$assets = []; $lk $head['X-Loco-Lookup']; while( $this->valid() ){ $entry $this->current(); $msgid $entry['id'][0]; if( is_null($msgid) ){ $this->next(); continue; } if( ++$i === $limit ){ return $assets; } $asset = [ 'source' => $this->str$msgid ), 'target' => $this->str( (string) $entry['str'][0] ), 'context' => null, ]; $prev_entry null; if( isset($entry['ctxt']) ){ $asset['context'] = $this->str$entry['ctxt'][0] ); } $cmt $entry['#']; if( isset($cmt[' ']) ){ $asset['comment'] = $this->strimplode("\n"$cmt[' '] ) ); } if( isset($cmt['.']) ){ $asset['notes'] = $this->strimplode("\n"$cmt['.'] ) ); } if( isset($cmt[':']) ){ if( $refs implode' '$cmt[':'] ) ) { $refs $this->str($refs); if( $refs loco_parse_reference_id$refs$_id ) ){ $asset['refs'] = $refs; } if( $_id ){ $asset['_id'] = $_id; } } } if( isset($cmt[',']) ){ foreach( $cmt[','] as $flags ){ foreach( explode(',',$flags) as $flag ){ if( $flag trim($flag," \t") ){ if( preg_match('/^((?:no-)?\w+)-format/'$flag$r ) ){ $asset['format'] = $r[1]; } else if( 'fuzzy' === $flag ){ $asset['flag'] = 4; } } } } } if( isset($cmt['|']) ){ $p = new LocoPoParser(''); $p->lines $cmt['|']; $p->setCharset$this->getCharset() ); try { $prev_entry $p->parse(); } catch( Loco_error_ParseException $e ){ } if( $prev_entry ){ $msgid $prev_entry[0]['source']; if( $lk && 'text' !== $lk ){ $asset[$lk] = $asset['source']; $asset['source'] = $msgid; } else if( substr($msgid,0,5) === 'loco:' ){ $asset['_id'] = substr($msgid,5); } else { $asset['prev'] = $prev_entry$prev_entry null; } } } $assets[] = $asset; if( isset($entry['id'][1]) ){ $idx 0$pidx count($assets) - 1$num max2count($entry['str']) ); while( ++$idx $num ){ $plural = [ 'source' => '''target' => isset($entry['str'][$idx]) ? $this->str($entry['str'][$idx]) : '''plural' => $idx'parent' => $pidx, ]; if( === $idx ){ $plural['source'] = $this->str($entry['id'][1]); if( is_array($prev_entry) && isset($prev_entry[1]) ){ if( $lk && 'text' !== $lk ){ $plural[$lk] = $plural['source']; $plural['source'] = $prev_entry[1]['source']; } } } if( isset($asset['flag']) ){ $plural['flag'] = $asset['flag']; } $assets[] = $plural; } } $this->next(); } if( -=== $i ){ throw new Loco_error_ParseException('Invalid PO file'); } else if( === $i && '' === $assets[0]['source'] && '' === $assets[0]['target'] ){ throw new Loco_error_ParseException('Invalid PO file' ); } return $assets; } }
class 
LocoMoParser extends LocoGettextParser 
private 
/*string*/ $bin
private 
/*bool*/ $be null
private 
/*int*/ $n null
private 
/*int*/ $o null
private 
/*int*/ $t null
private 
/*int*/ $v null
public function 
__constructstring $bin ){ $this->bin $bin; } 
public function 
getAtint $idx ) { $offset $this->targetOffset(); $offset += ( $idx ); $len $this->integerAt$offset ); $idx $this->integerAt$offset ); $txt $this->bytes$idx$len ); if( false !== strpos($txt,"\0") ){ return explode"\0"$txt ); } return $txt; } 
public function 
parseint $limit = -):array { $i = -1$r = []; $sourceOffset $this->sourceOffset(); $targetOffset $this->targetOffset(); $soffset $sourceOffset$toffset $targetOffset; while( $soffset $targetOffset ){ $len $this->integerAt$soffset ); $idx $this->integerAt$soffset ); $src $this->bytes$idx$len ); $eot strpos$src"\x04" ); if( false === $eot ){ $context null; } else { $context $this->strsubstr($src0$eot ) ); $src substr$src$eot+); } $sources explode"\0"$src); $len $this->integerAt$toffset ); $idx $this->integerAt$toffset ); $targets explode"\0"$this->bytes$idx$len ) ); if( -=== $i && '' === $sources[0] && is_null($context) ){ $this->setHeaderLocoPoHeaders::fromMsgstr($targets[0]) ); } if( ++$i $limit && -!== $limit ){ break; } $r[$i] = [ 'source' => $this->str$sources[0] ), 'target' => $this->str$targets[0] ), 'context' => $context, ]; if( isset($sources[1]) ){ $p count($r) - 1$nforms max2count($targets) ); for( $n 1$n $nforms$n++ ){ $r[++$i] = [ 'source' => === $n && isset($sources[1]) ? $this->str($sources[1]) : '''target' => isset($targets[$n]) ? $this->str$targets[$n] ) : '''parent' => $p'plural' => $n, ]; } } $soffset += 8$toffset += 8; } return $r; } 
public function 
isBigendian():bool { if( is_null($this->be) ){ $str $this->words0); if( "\xDE\x12\x04\x95" === $str ){ $this->be false; } else if( "\x95\x04\x12\xDE" === $str ){ $this->be true; } else { throw new Loco_error_ParseException('Invalid MO format'); } } return $this->be; } 
public function 
version():int { if( is_null($this->v) ){ $this->$this->integerWord(1); } return $this->v; } 
#[
ReturnTypeWillChange]
public function 
count():int { if( is_null($this->n) ){ $this->$this->integerWord(2); } return $this->n; } 
public function 
sourceOffset():int { if( is_null($this->o) ){ $this->$this->integerWord(3); } return $this->o; } 
public function 
targetOffset():int { if( is_null($this->t) ){ $this->$this->integerWord(4); } return $this->t; } 
public function 
getHashTable():string $s $this->integerWord(5); $h $this->integerWord(6); return $this->bytes$h$s ); } 
private function 
bytesint $offsetint $length ):string $s substr$this->bin$offset$length ); if( strlen($s) !== $length ){ throw new Loco_error_ParseException('Failed to read '.$length.' bytes at ['.$offset.']' ); } return $s; } 
private function 
wordsint $offsetint $length ):string { return $this->bytes$offset 4$length ); } 
private function 
integerWordint $offset ):int { return $this->integerAt$offset ); } 
private function 
integerAtint $offset ):int $str $this->bytes$offset); $fmt $this->isBigendian() ? 'N' 'V'$arr unpack$fmt$str ); if( ! isset($arr[1]) || ! is_int($arr[1]) ){ throw new Loco_error_ParseException('Failed to read integer at byte '.$offset); } return $arr[1]; } }
class 
LocoJedParser extends LocoGettextParser 
private 
/*array*/ $ld
public function 
__construct( array $struct ){ $this->ld $struct; } 
public function 
parseint $limit = -): array { $values = []; foreach( $this->ld as $messages ){ if( ! is_array($messages) ){ throw new Loco_error_ParseException('Array expected'); } $msgid key($messages); if( '' === $msgid ){ $this->setHeader( new LocoJedHeaders($messages['']) ); unset($messages['']); } else { $this->setHeader( new LocoJedHeaders ); } $values[] = [ 'source' => '''target' => $this->getHeader(), ]; $i = -1; foreach( $messages as $key => $list ){ if( ++$i === $limit ){ break; } $value $this->initMsgKey($key); $index count($values); foreach( $list as $j => $msgstr ){ if( ! is_string($msgstr) ){ throw new Loco_error_ParseException('msgstr must be scalar'); } $value['target'] = $msgstr; if( $j ){ $value['plural'] = $j$value['parent'] = $index$value['source'] = ''; } $values[] = $value; } } } return $values; } }
class 
LocoJedHeaders extends LocoPoHeaders 
public function 
__construct( array $raw = [] ) { foreach( ['Language'=>'lang','plural_forms'=>'Plural-Forms'] as $canonical => $alias ){ if( array_key_exists($alias,$raw) && ! array_key_exists($canonical,$raw) ){ $raw[$canonical] = $raw[$alias]; } } parent::__construct($raw); } }
class 
LocoMoPhpParser extends LocoGettextParser 
private 
/*array*/ $msgs
public function 
__construct( array $struct ){ $this->msgs $struct['messages']; unset($struct['messages']); $this->setHeader( new LocoPoHeaders($struct) ); } 
public function 
parseint $limit = -): array { $values = [ [ 'source' => '''target' => $this->getHeader(), ] ]; $i = -1; foreach( $this->msgs as $key => $bin ){ if( ++$i === $limit ){ break; } $value $this->initMsgKey($key); $index count($values); foreach( explode("\0",$bin) as $i => $msgstr ){ $value['target'] = $msgstr; if( $i ){ $value['plural'] = $i$value['parent'] = $index$value['source'] = ''; } $values[] = $value; } } return $values; } }
abstract class 
LocoPo 
public static function 
pairstring $keystring $textint $width 79string $eol "\n"string $esc '\\n' ):string { if( '' === $text ){ return $key.' ""'; } $text addcslashes$text"\t\x0B\x0C\x07\x08\\\"" ); if( $esc ) { $text preg_replace('/\\r\\n?|\\n/'$esc.$eol$text, -1$nbr ); } else { $eol "\n"$text preg_replace_callback('/\\r\\n?|\\n/',[__CLASS__,'replace_br'], $text, -1$nbr ); } if( $nbr ){ } else if( $width && $width mb_strlen($text,'UTF-8') + strlen($key) + ){ } else { return $key.' "'.$text.'"'; } $lines = [ $key.' "' ]; if( $width ){ $width -= 2$a '/^.{0,'.($width-1).'}[-– .,:;?!)\\]}>]/u'$b '/^[^-– .,:;?!)\\]}>]+/u'; foreach( explode($eol,$text) as $unwrapped ){ $length mb_strlen$unwrapped'UTF-8' ); while( $length $width ){ if( preg_match$a$unwrapped$r ) ){ $line $r[0]; } else if( preg_match$b$unwrapped$r ) ){ $line $r[0]; } else { throw new Exception('Wrapping error'); } $lines[] = $line$trunc mb_strlen($line,'UTF-8'); $length -= $trunc$unwrapped = (string) substr$unwrappedstrlen($line) ); if( ( '' === $unwrapped && !== $length ) || ( === $length && '' !== $unwrapped ) ){ throw new Exception('Truncation error'); } } if( !== $length ){ $lines[] = $unwrapped; } } } else { foreach( explode($eol,$text) as $unwrapped ){ $lines[] = $unwrapped; } } return implode('"'.$eol.'"',$lines).'"'; } 
private static function 
replace_br( array $r ):string { return addcslashes($r[0],"\r\n")."\n"; } 
public static function 
refsstring $textint $width 76string $eol "\n" ):string $text preg_replace('/\\s+/u'' '$text ); if( $width ){ $text wordwrap$text$width$eol.'#: ' ); } return '#: '.$text; } 
public static function 
prefixstring $textstring $prefixstring $eol "\n" ):string { return $prefix implode($eol.$prefixself::split($text) ); } 
public static function 
splitstring $text ):array { $lines preg_split('/\\R/u'$text ); if( false === $lines ){ if( false === preg_match('//u',$text) ){ $text mb_convert_encoding$text'UTF-8''Windows-1252' ); } $lines preg_split('/\\r?\\n+/'$text ); } return $lines; } 
public static function 
trimstring $text ):string $lines = []; $deferred null; foreach( explode("\n",$text) as $line ){ if( '' === $line ){ continue; } if( preg_match('/^msg[a-z]+(?:\\[\\d+])? ""/',$line) ){ $deferred $line; continue; } if( $deferred && '"' === $line[0] ){ $lines[] = $deferred$deferred null; } $lines[] = $line; } return implode("\n",$lines); } }
class 
LocoPoIndex extends ArrayIterator 
public function 
compareLocoPoMessage $aLocoPoMessage $b ):int $h $a->getHash(); if( ! isset($this[$h]) ){ return 1; } $j $b->getHash(); if( ! isset($this[$j]) ){ return -1; } return $this[$h] > $this[$j] ? : -1; } }
class 
LocoPoMessage extends ArrayObject 
public function 
__construct( array $r ){ $r['key'] = $r['source']; parent::__construct($r); } 
public function 
__getstring $prop ) { return $this->offsetExists($prop) ? $this->offsetGet($prop) : null; } 
public function 
isFuzzy():bool { return === $this->__get('flag'); } 
public function 
getFormat():string $f $this->__get('format'); if( is_string($f) && '' !== $f ){ return $f; } return ''; } 
private function 
getPoFlags():array { $flags = []; foreach( array_merge( [$this], $this->__get('plurals')?:[] ) as $form ){ if( $form->isFuzzy() ){ $flags[0] = 'fuzzy'; } $f $form->getFormat(); if( '' !== $f ){ $flags[1] = $f.'-format'; } } return array_values($flags); } 
public function 
getHash():string $hash $this->getKey(); if( $this->offsetExists('plurals') ){ foreach( $this->offsetGet('plurals') as $p ){ $hash .= "\0".$p->getKey(); break; } } return $hash; } 
public function 
getKey():string $msgid = (string) $this['source']; $msgctxt = (string) $this->__get('context'); if( '' !== $msgctxt ){ if( '' === $msgid ){ $msgid '('.$msgctxt.')'; } $msgid $msgctxt."\4".$msgid; } return $msgid; } 
public function 
exportSerialstring $f 'target' ):array { $a = [ $this[$f] ]; if( $this->offsetExists('plurals') ){ $plurals $this->offsetGet('plurals'); if( is_array($plurals) ){ foreach( $plurals as $p ){ $a[] = $p[$f]; } } } return $a; } 
public function 
__toString(){ return $this->render7976 ); } 
public function 
renderint $widthint $ref_widthint $max_forms ):string $s = []; try { if( $text $this->__get('comment') ) { $s[] = LocoPo::prefix$text'# '); } if( $text $this->__get('notes') ) { $s[] = LocoPo::prefix$text'#. '); } if( $text $this->__get('refs') ){ $s[] = LocoPo::refs$text$ref_width ); } if( $texts $this->getPoFlags() ){ $s[] = '#, '.implode(', ',$texts); } $prev $this->__get('prev'); if( is_array($prev) && $prev ){ foreach( new LocoPoIterator($prev) as $p ){ $text $p->rendermax(0,$width-3), ); $s[] = LocoPo::prefixLocoPo::trim($text),'#| '); break; } } $text $this->__get('context'); if( is_string($text) && '' !== $text ){ $s[] = LocoPo::pair('msgctxt'$text$width ); } $s[] = LocoPo::pair'msgid'$this['source'], $width ); $target $this['target']; $plurals $this->__get('plurals'); if( is_array($plurals) ){ if( array_key_exists(0,$plurals) ){ $p $plurals[0]; $s[] = LocoPo::pair('msgid_plural'$p['source'], $width ); $s[] = LocoPo::pair('msgstr[0]'$target$width ); $i 0; while( array_key_exists($i,$plurals) ){ $p $plurals[$i]; if( ++$i === $max_forms ){ break; } $s[] = LocoPo::pair('msgstr['.$i.']'$p['target'], $width ); } } else if( isset($this['plural_key']) ){ $s[] = LocoPo::pair('msgid_plural'$this['plural_key'], $width ); $s[] = LocoPo::pair('msgstr[0]'$target$width ); } else { trigger_error('Missing plural_key in zero plural export'); $s[] = LocoPo::pair('msgstr'$target$width ); } } else { $s[] = LocoPo::pair('msgstr'$target$width ); } } catch( Exception $e ){ trigger_error$e->getMessage(), E_USER_WARNING ); } return implode("\n",$s)."\n"; } 
public function 
mergeLocoPoMessage $defbool $translate false ):void { if( $def->getHash() !== $this->getHash() ){ $prev = [ 'source' => '''target' => '' ]; $prev $this->diff('source',$def,$prev); $prev $this->diff('context',$def,$prev); $this['flag'] = 4$this['prev'] = [ $prev ]; $defPlural $def->getPlural(0); $ourPlural $this->getPlural(0); if( $defPlural && $ourPlural ) { $ourPlural->merge($defPlural); if( $ourPlural->offsetExists('prev') ) { $this['prev'][] = $ourPlural->prev[0]+['parent'=>0,'plural'=>1]; $ourPlural->offsetUnset('prev'); } } else if( $defPlural ){ $this['plurals'] = [ clone $defPlural ]; } else if( $ourPlural ){ $this['prev'][] = $ourPlural->exportBasic() + ['parent'=>0,'plural'=>1]; $this->offsetUnset('plurals'); } } foreach( ['notes','refs','format'] as $f ){ if( $def->offsetExists($f) ){ $this->offsetSet($f,$def->offsetGet($f)); } else if( $this->offsetExists($f) ){ $this->offsetUnset($f); } } if( $translate && '' === $this['target'] && '' !== $def['target'] ){ $this['target'] = $def['target']; if( $def->offsetExists('comment') ) { $this['comment'] = $def['comment']; } if( $this->offsetExists('plurals') ){ foreach( $this['plurals'] as $i => $ourPlural ){ if( '' === $ourPlural['target'] ){ $defPlural $def->getPlural($i); if( $defPlural ){ $ourPlural['target'] = $defPlural['target']; } } } } } } 
private function 
diffstring $keyLocoPoMessage $def, array $prev ):array { $old $this->__get($key); $new $def->__get($key); if( $new !== $old ){ $this->offsetSet($key,$new); if( is_string($old) && '' !== $old ){ $prev[$key] = $old; } } return $prev; } 
private function 
getPluralint $i ):?self { if( $this->offsetExists('plurals') ){ $plurals $this->offsetGet('plurals'); if( is_array($plurals) && array_key_exists($i,$plurals) ){ return $plurals[$i]; } } return null; } 
private function 
exportBasic():array { return [ 'source' => $this['source'], 'context' => $this->context'target' => '', ]; } 
public function 
export():array { $a $this->getArrayCopy(); unset($a['key']); if( array_key_exists('plurals',$a) ){ foreach( $a['plurals'] as $i => $p ){ if( $p instanceof ArrayObject ){ $a['plurals'][$i] = $p->getArrayCopy(); } } } return $a; } 
public function 
strip():self $this['target'] = ''$plurals $this->plurals; if( is_array($plurals) ){ foreach( $plurals as $p ){ $p->strip(); } } return $this; } 
public function 
translated():int $n 0; if( '' !== (string) $this['target'] ){ $n++; } if( $this->offsetExists('plurals') ){ foreach( $this->offsetGet('plurals') as $plural ) { if( '' !== (string) $plural['target']) { $n++; } } } return $n; } }
class 
LocoPoIterator implements IteratorCountable 
private 
/*array*/ $po
private 
/*LocoPoHeaders*/ $headers null
private 
/*int*/ $i
private 
/*int*/ $t
private 
/*int*/ $j
private 
/*int*/ $z 0
private 
/*int*/ $w 79
public function 
__constructiterable $po ){ if( is_array($po) ){ $this->po $po; } else if( $po instanceof Traversable ){ $this->po iterator_to_array($po,false); } else { throw new InvalidArgumentException('PO data must be array or iterator'); } $this->count$this->po ); if( === $this->){ throw new InvalidArgumentException('Empty PO data'); } $h $po[0]; if( '' !== $h['source'] || ( isset($h['context']) && '' !== $h['context'] ) || ( isset($po[1]['parent']) && === $po[1]['parent'] ) ){ $this->= -1; } } 
public function 
pushLocoPoMessage $p ):void $raw $p->export(); $plurals $p->plurals; unset($raw['plurals']); $i count($this->po); $this->po[$i] = $raw$this->t++; if( is_array($plurals) ) { $j 0; foreach( $plurals as $p ) { $raw $p->export(); $raw['parent'] = $i$raw['plural'] = ++$j$this->po[] = $raw$this->t++; } } } 
public function 
concatiterable $more ):self { foreach( $more as $message ){ $this->push($message); } return $this; } 
public function 
__clone() { if( $this->headers ){ $this->headers = new LocoPoHeaders$this->headers->getArrayCopy() ); } } 
#[
ReturnTypeWillChange]
public function 
count():int { return $this->- ( $this->); } 
public function 
wrapint $width ):self { if( $width ){ $this->max15$width ); } else { $this->0; } return $this; } 
#[
ReturnTypeWillChange]
public function 
rewind():void $this->$this->z$this->= -1$this->next(); } 
#[
ReturnTypeWillChange]
public function 
key():?int { return $this->j; } 
#[
ReturnTypeWillChange]
public function 
valid():bool { return is_int($this->i); } 
#[
ReturnTypeWillChange]
public function 
next():void $i $this->i; while( ++$i $this->){ if( array_key_exists('parent',$this->po[$i]) ){ continue; } $this->j++; $this->$i; return; } $this->null$this->null; } 
#[
ReturnTypeWillChange]
public function 
current():LocoPoMessage { return $this->item$this->); } 
private function 
itemint $i ):LocoPoMessage $po $this->po$parent = new LocoPoMessage$po[$i] ); $plurals = []; $nonseq $parent->offsetExists('child'); $j $nonseq $parent['child'] : $i+1; while( isset($po[$j]['parent']) && $i === $po[$j]['parent'] ){ $plurals[] = new LocoPoMessage($po[$j++]); } if( $plurals ){ $parent['plurals'] = $plurals; } return $parent; } 
public function 
exportEntryint $i ):LocoPoMessage { return $this->item$i + ( 1-$this->z) ); } 
public function 
getArrayCopy():array { $po $this->po; if( === $this->){ $po[0]['target'] = (string) $this->getHeaders(); } return $po; } 
public function 
clear():void { if( === $this->){ $this->po = [ $this->po[0] ]; $this->1; } else { $this->po = []; $this->0; } } 
public function 
getHeaders():LocoPoHeaders { if( is_null($this->headers) ){ $header $this->po[0]; if( === $this->){ $value $header['target']; if( is_string($value) ){ $this->headers LocoPoHeaders::fromMsgstr($value); } else if( $value instanceof LocoPoHeaders ){ $this->headers $value; } else if( is_array($value) ){ $this->headers = new LocoPoHeaders($value); } } else { $this->headers = new LocoPoHeaders; } } return $this->headers; } 
public function 
setHeadersLocoPoHeaders $head ):self $this->headers $head; if( === $this->){ $this->po[0]['target'] = null; } return $this; } 
public function 
initPo():self { if( === $this->){ unset( $this->po[0]['flag'] ); } return $this; } 
public function 
initPot():self { if( === $this->){ $this->po[0]['flag'] = 4; } return $this; } 
public function 
strip():self $po $this->po$i count($po); $z $this->z; while( --$i $z ){ $po[$i]['target'] = ''; } $this->po $po; return $this; } 
public function 
__toString():string { try { return $this->render(); } catch( Exception $e ){ trigger_error$e->getMessage(), E_USER_WARNING ); return ''; } } 
public function 
render( ?callable $sorter null ):string $width $this->w$ref_width max0$width ); $h $this->exportHeader(); $msg = new LocoPoMessage$h ); $s $msg->render$width$ref_width ); if( $sorter ){ $msgs = []; foreach( $this as $msg ){ $msgs[] = $msg; } usort$msgs$sorter ); } else { $msgs $this; } $h $this->getHeaders()->offsetGet('Plural-Forms'); if( is_string($h) && preg_match('/nplurals\\s*=\\s*(\\d)/',$h,$r) ){ $max_pl = (int) $r[1]; } else { $max_pl 0; } foreach( $msgs as $msg ){ $s .= "\n".$msg->render$width$ref_width$max_pl ); } return $s; } 
public function 
exportJed():array { $head $this->getHeaders(); $a = [ '' => [ 'domain' => $head['domain'], 'lang' => $head['language'], 'plural-forms' => $head['plural-forms'], ] ]; foreach( $this as $message ){ if( $message->translated() ){ $a$message->getKey() ] = $message->exportSerial(); } } return $a; } 
private function 
exportHeader():array { if( === $this->){ $h $this->po[0]; } else { $h = [ 'source' => '''target' => '' ]; } if( $this->headers ){ $h['target'] = (string) $this->headers; } return $h; } 
public function 
exportRefsstring $grep '' ):array { $a = []; if( '' === $grep ) { $grep '/(\\S+):\\d+/'; } else { $grep '/(\\S*'.$grep.'):\\d+/'; } $self get_class($this); $base = [ $this->exportHeader() ]; foreach( $this as $message ){ if( preg_match_all$grep, (string) $message->refs$r ) ){ foreach( $r[1] as $ref ) { if( array_key_exists($ref,$a) ){ $po $a[$ref]; } else { $po = new $self($base); $a[$ref] = $po; } $po->push($message); } } } return $a; } 
public function 
splitRefs( ?array $map null ):array { $a = []; $self get_class($this); $base = [ $this->exportHeader() ]; if( is_array($map) ){ $grep implode('|',array_keys($map)); } else { $grep '[a-z]+'; } foreach( $this as $message ){ $refs ltrim( (string) $message->refs ); if( '' !== $refs ){ if( preg_match_all('/\\S+\\.('.$grep.'):\\d+/'$refs$rPREG_SET_ORDER ) ){ $tmp = []; foreach( $r as $rr ) { list( $ref$ext ) = $rr$tmp[$ext][$ref] = true; } foreach( $tmp as $ext => $refs ){ if( is_array($map) ){ $ext $map[$ext]; } if( array_key_exists($ext,$a) ){ $po $a[$ext]; } else { $po = new $self($base); $a[$ext] = $po; } $message = clone $message$message['refs'] = implode(' ',array_keys($refs) ); $po->push($message); } } } } return $a; } 
public function 
getHashes():array { $a = []; foreach( $this as $msg ){ $a[] = $msg->getKey(); } sort$aSORT_STRING ); return $a; } 
public function 
equalSourceLocoPoIterator $that ):bool { return $this->getHashes() === $that->getHashes(); } 
public function 
equalLocoPoIterator $that ):bool { if( $this->!== $that->){ return false; } $i $this->z$fields = [ 'source''context''notes''refs''target''comment''flag''parent''plural' ]; while( ++$i $this->){ $a $this->po[$i]; $b $that->po[$i]; foreach( $fields as $f ){ $af $a[$f] ?? ''$bf $b[$f] ?? ''; if( $af !== $bf ){ return false; } } } return true; } 
public function 
sort( ?callable $func null ):self $order = []; foreach( $this as $msg ){ $order[] = $msg; } usort$order$func ?: [__CLASS__,'compare'] ); $this->clear(); foreach( $order as $p ){ $this->push($p); } return $this; } 
public static function 
compareLocoPoMessage $aLocoPoMessage $b ):int $h $a->getHash(); $j $b->getHash(); $n strcasecmp$h$j ); if( === $n ){ $n strcmp$h$j ); if( === $n ){ return 0; } } return $n : -1; } 
public function 
createSorter():array { $index = []; foreach( $this as $i => $msg ){ $index$msg->getHash() ] = $i; } $obj = new LocoPoIndex$index ); return [ $obj'compare' ]; } }
class 
LocoMoTable 
private 
/*int*/ $size 0
private 
/*string*/ $bin ''
private 
/*array*/ $map null
public function 
__construct/*mixed*/ $data '' ){ if( is_array($data) ){ $this->compile$data ); } else if( '' !== $data ){ $this->parse$data ); } } 
#[
ReturnTypeWillChange]
public function 
count():int { if( is_null($this->size) ){ if( $this->bin ){ $this->size = (int) ( strlen$this->bin ) / ); } else if( is_array($this->map) ){ $this->size count($this->map); } else { return 0; } if( ! self::is_prime($this->size) || $this->size ){ throw new Exception('Size expected to be prime number above 2, got '.$this->size); } } return $this->size; } 
public function 
bytes():int { return $this->count() * 4; } 
public function 
__toString():string { return $this->bin; } 
public function 
export():array { if( is_null($this->map) ){ $this->parse($this->bin); } return $this->map; } 
private function 
resetint $length ):int $this->size max3self::next_prime$length ) ); $this->bin ''$this->map = []; return $this->size; } 
public function 
compile( array $msgids ):void $hash_tab_size $this->resetcount($msgids) ); $packed array_fill0$hash_tab_size"\0\0\0\0" ); $j 0; foreach( $msgids as $msgid ){ $hash_val self::hashpjw$msgid ); $idx $hash_val $hash_tab_size; if( array_key_exists($idx$this->map) ){ $incr + ( $hash_val % ( $hash_tab_size ) ); do { $idx += $incr; if( $hash_val === $idx ){ throw new Exception('Unable to find empty slot in hash table'); } $idx %= $hash_tab_size; } while( array_key_exists($idx$this->map ) ); } $this->map[$idx] = $j$packed[$idx] = pack('V', ++$j ); } $this->bin implode('',$packed); } 
public function 
lookupstring $msgid, array $msgids ):int $hash_val self::hashpjw$msgid ); $idx $hash_val $this->size$incr + ( $hash_val % ( $this->size ) ); while( true ){ if( ! array_key_exists($idx$this->map) ){ break; } $j $this->map[$idx]; if( isset($msgids[$j]) && $msgid === $msgids[$j] ){ return $j; } $idx += $incr; if( $idx === $hash_val ){ break; } $idx %= $this->size; } return -1; } 
private function 
parsestring $bin ):void $this->bin $bin$this->size null$hash_tab_size $this->count(); $this->map = []; $idx = -1$byte 0; while( ++$idx $hash_tab_size ){ $word substr$this->bin$byte); if( "\0\0\0\0" !== $word ){ list(,$j) = unpack('V'$word ); $this->map[$idx] = $j 1; } $byte += 4; } } 
public static function 
hashpjwstring $str ):int $i = -1$hval 0$len strlen($str); while( ++$i $len ){ $ord ordsubstr($str,$i,1) ); $hval = ( $hval << ) + $ord$g $hval 0xf0000000; if( $g !== ){ $hval ^= $g >> 24$hval ^= $g; } } return $hval; } 
private static function 
next_primefloat $seed ):int $seed = (int) floor($seed); $seed |= 1; while ( ! self::is_prime($seed) ){ $seed += 2; } return $seed; } 
private static function 
is_primeint $num ):bool { if( === $num ){ return false; } if( === $num ){ return true; } if( $num == ) { return false; } for( $i 3$i <= ceil(sqrt($num)); $i $i 2) { if($num $i == ){ return false; } } return true; } }
class 
LocoMo 
private 
/*string*/ $bin
private 
/*Iterator*/ $msgs
private 
/*LocoPoHeaders*/ $head
private 
/*LocoMoTable*/ $hash null
private 
/*bool*/ $use_fuzzy false
private 
/*string*/ $cs null
public function 
__constructIterator $export, ?LocoPoHeaders $head null ){ if( $head ){ $this->head $head; } else { $this->head = new LocoPoHeaders$this->setHeader('Project-Id-Version','Loco'); } $this->msgs $export$this->bin ''; } 
public function 
setCharsetstring $cs ):void $cs $this->head->setCharset($cs); $this->cs 'UTF-8' === $cs null $cs; } 
public function 
enableHash():void $this->hash = new LocoMoTable; } 
public function 
useFuzzy():void $this->use_fuzzy true; } 
public function 
setHeaderstring $keystring $val ):self $this->head->add($key,$val); return $this; } 
private function 
strstring $s ):string { if( $cs $this->cs ){ $s mb_convert_encoding($s,$cs,['UTF-8']); } return $s; } 
public function 
compile():string $table = ['']; $sources = ['']; $targets = [ (string) $this->head ]; $fuzzy_flag 4$skip_fuzzy = ! $this->use_fuzzy; if( $this->head->has('Plural-Forms') && preg_match('/^nplurals=(\\d)/',$this->head->trimmed('Plural-Forms'), $r) ){ $nplurals = (int) $r[1]; $maxplural max0$nplurals-); } else { $maxplural 1; } $unique = []; foreach( $this->msgs as $r ){ if( $skip_fuzzy && isset($r['flag']) && $fuzzy_flag === $r['flag'] ){ continue; } $msgid $this->str$r['key'] ); if( isset($r['context']) ){ $msgctxt $this->str$r['context'] ); if( '' !== $msgctxt ){ if( '' === $msgid ){ $msgid '('.$msgctxt.')'; } $msgid $msgctxt."\x04".$msgid; } } if( '' === $msgid ){ continue; } if( array_key_exists($msgid,$unique) ){ continue; } $unique[$msgid] = true$msgstr $this->str$r['target'] ); if( '' === $msgstr ){ continue; } $table[] = $msgid; if( isset($r['plurals']) ){ if( $r['plurals'] ){ $i 0; foreach( $r['plurals'] as $i => $p ){ if( $i === ){ $msgid .= "\0".$this->str($p['key']); } $msgstr .= "\0".$this->str($p['target']); } while( $maxplural > ++$i ){ $msgstr .= "\0"; } } else if( isset($r['plural_key']) ){ $msgid .= "\0".$this->str($r['plural_key']); } } $sources[] = $msgid$targets[] = $msgstr; } asort$sourcesSORT_STRING ); $this->bin "\xDE\x12\x04\x95\x00\x00\x00\x00"$n count($sources); $this->writeInteger$n ); $offset 28$this->writeInteger$offset ); $offset += $n 8$this->writeInteger$offset ); if( $this->hash ){ sort$tableSORT_STRING ); $this->hash->compile$table ); $s $this->hash->count(); } else { $s 0; } $this->writeInteger$s ); $offset += $n 8$this->writeInteger$offset ); if( $s ){ $offset += $s 4; } $source ''; foreach( $sources as $str ){ $source .= $str."\0"$this->writeInteger$strlen strlen($str) ); $this->writeInteger$offset ); $offset += $strlen 1; } $target ''; foreach( array_keys($sources) as $i ){ $str $targets[$i]; $target .= $str."\0"$this->writeInteger$strlen strlen($str) ); $this->writeInteger$offset ); $offset += $strlen 1; } if( $this->hash ){ $this->bin .= $this->hash->__toString(); } $this->bin .= $source$this->bin .= $target; return $this->bin; } 
private function 
writeIntegerint $num ):void $this->bin .= pack'V'$num ); } }
interface 
LocoTokensInterface extends Iterator 
public function 
advance(); 
public function 
ignore( ...$symbols ):self; }
class 
LocoTokenizer implements LocoTokensInterface { const /*int*/T_LITERAL 0; const /*int*/T_UNKNOWN = -1
private 
/*string*/ $src
private 
/*int*/ $pos
private 
/*int*/ $line
private 
/*int*/ $col
private 
/*int*/ $max
private 
/*array*/ $rules = []; 
private 
/*array*/ $skip = []; 
private 
/*mixed*/ $tok
private 
/*int*/ $len
public function 
__constructstring $src '' ){ $this->init($src); } 
public function 
parsestring $src ):array { return iterator_to_array$this->generate($src) ); } 
public function 
generatestring $src ):Generator $this->init($src); while( $this->valid() ){ yield $this->current(); $this->next(); } } 
public function 
initstring $src ):self $this->src $src$this->rewind(); return $this; } 
public function 
definestring $grep/*mixed*/ $t ):self { if('^' !== $grep[1] ){ throw new InvalidArgumentException('Expression '.$grep.' isn\'t anchored'); } if( ! is_int($t) && ! is_callable($t) ){ throw new InvalidArgumentException('Non-integer token must be valid callback'); } $sniff $grep[2]; if( $sniff === preg_quote($sniff,$grep[0]) ){ $this->rules[$sniff][] = [ $grep$t ]; } else { $this->rules[''][] = [ $grep$t ]; } return $this; } 
public function 
ignore( ...$symbols ):LocoTokensInterface $this->skip += array_fill_keys$symbolstrue ); return $this; } 
public function 
allow( ...$symbols ):self $this->skip array_diff_key$this->skiparray_fill_keys($symbols,true) ); return $this; } 
#[
ReturnTypeWillChange]
public function 
current() { return $this->tok; } 
public function 
advance() { $tok $this->current(); $this->next(); return $tok; } 
#[
ReturnTypeWillChange]
public function 
next():void $tok null$offset $this->pos$column $this->col$line $this->line; while( $offset <= $this->max ){ $t null$s ''$text substr($this->src,$offset); foreach( [$text[0],''] as $k ){ if( isset($this->rules[$k]) ) { foreach( $this->rules[$k] as $rule) { if( preg_match($rule[0], $text$match ) ) { $s $match[0]; $t $rule[1]; if( ! is_int($t) ) { $t call_user_func$t$s$match ); } break 2; } } } } if( is_null($t) ){ $n preg_match('/^./u',$text,$match); if( false === $n ){ $s $text[0]; $match = [ mb_convert_encoding($s,'UTF-8','Windows-1252') ]; } $s = (string) $match[0]; $t self::T_UNKNOWN; } $length strlen($s); if( === $length ){ throw new Loco_error_ParseException('Failed to match anything'); } $offset += $length$lines preg_split('/\\r?\\n/',$s); $nlines count($lines); if( $nlines ){ $next_line $line + ( $nlines ); $next_column strlenend($lines) ); } else { $next_line $line$next_column $column $length; } if( array_key_exists($t,$this->skip) ){ $line $next_line$column $next_column; continue; } $tok self::T_LITERAL === $t $s : [ $t$s$line$column ]; $line $next_line$column $next_column$this->len++; break; } $this->tok $tok$this->pos $offset$this->col $column$this->line $line; } 
#[
ReturnTypeWillChange]
public function 
key():?int { return $this->len $this->len-null; } 
#[
ReturnTypeWillChange]
public function 
valid():bool { return null !== $this->tok; } 
#[
ReturnTypeWillChange]
public function 
rewind():void $this->len 0$this->pos 0$this->col 0$this->line 1$this->max strlen($this->src) - 1$this->next(); } }
function 
loco_utf8_chrint $u ){ if( $u 0x80 ){ if( $u ){ throw new RangeExceptionsprintf('%d is out of Unicode range'$u ) ); } return chr($u); } if( $u 0x800 ) { return chr( ($u>>6) & 0x1F 0xC0 ).chr$u 0x3F 0x80 ); } if( $u 0x10000 ) { return chr$u>>12 15 0xE0 ).chr$u>>0x3F 0x80 ).chr$u 0x3F 0x80 ); } if( $u 0x110000 ) { return chr$u>>18 0xF0 ).chr$u>>12 0x3F 0x80 ).chr$u>>0x3F 0x80 ).chr$u 0x3F 0x80 ); } throw new RangeExceptionsprintf('\\x%X is out of Unicode range'$u ) ); }
function 
loco_resolve_surrogatesstring $s ){ return preg_replace_callback('/\\xED([\\xA0-\\xAF])([\\x80-\\xBF])\\xED([\\xB0-\\xBF])([\\x80-\\xBF])/''_loco_resolve_surrogates'$s ); }
function 
_loco_resolve_surrogates( array $r ){ return loco_utf8_chr ( ( ( ( ( 832 | ( ord($r[1]) & 0x3F ) ) << ) | ( ord($r[2]) & 0x3F ) ) - 0xD800 ) * 0x400 + ( ( ( ( 832 | ( ord($r[3]) & 0x3F ) ) << ) | ( ord($r[4]) & 0x3F ) ) - 0xDC00 ) + 0x10000 ); }
class 
LocoEscapeParser 
private 
/*array*/ $map
private 
/*string*/ $grep
public function 
__construct( array $map = [] ){ $this->map $map$rules = ['\\\\']; if( $map ){ $rules[] = '['.implode(array_keys($map)).']'; } if( ! isset($map['U']) ) { $rules[] = 'U[0-9A-Fa-f]{5,8}'; } if( ! isset($map['u']) ) { $rules[] = 'u(?:\\{[0-9A-Fa-f]+\\}|[0-9A-Fa-f]{1,4})(?:\\\\u(?:\\{[0-9A-Fa-f]+\\}|[0-9A-Fa-f]{1,4}))*'; } $this->grep '/\\\\('.implode('|',$rules).')/'; } 
final public function 
unescapestring $s ):string { if( '' !== $s ) { return $this->stripSlashespreg_replace_callback($this->grep, [$this'unescapeMatch'], $s) ); } return ''; } 
final public function 
unescapeMatch( array $r ):string $s $r[0]; $c $s[1]; if( isset($this->map[$c]) ){ return $this->map[$c]; } if( 'u' === $c ){ $str ''$surrogates false; foreach( explode('\\u',$s) as $i => $h ){ if( '' !== $h ){ $h ltrimtrim($h,'{}'),'0'); $u intval($h,16); $str.= loco_utf8_chr($u); if( ! $surrogates ){ $surrogates $u >= 0xD800 && $u <= 0xDBFF; } } } if( $surrogates ){ $str loco_resolve_surrogates($str); } return $str; } if( 'U' === $c ){ return loco_utf8_chrintval(substr($s,2),16) ); } if( 'x' === $c ){ return chrintval(substr($s,2),16) ); } if( ctype_digit($c) ){ return chrintval(substr($s,1),8) ); } return $s; } 
protected function 
stripSlashesstring $s ):string { return stripcslashes($s); } }
class 
LocoJsTokens extends LocoTokenizer 
private static 
/*LocoEscapeParser*/ $lex null
protected static 
/*array*/ $words = [ 'true' => 1'false' => 1'null' => 1'break' => T_BREAK'else' => T_ELSE'new' => T_NEW'var' => 1'case' => T_CASE'finally' => T_FINALLY'return' => T_RETURN'void' => 1'catch' => T_CATCH'for' => T_FOR'switch' => T_SWITCH'while' => T_WHILE'continue' => T_CONTINUE'function' => T_FUNCTION'this' => T_STRING'with' => 1'default' => T_DEFAULT'if' => T_IF'throw' => T_THROW'delete' => 1'in' => 1'try' => T_TRY'do' => T_DO'instanceof' => 1'typeof' => 1, ]; 
public static function 
decapsestring $encapsed ):string $s substr($encapsed,1,-1); $l self::$lex; if( is_null($l) ){ $l = new LocoEscapeParser( [ 'U' => 'U''a' => 'a', ] ); self::$lex $l; } return $l->unescape($s); } 
public function 
__constructstring $src '' ){ $this->ignore(T_WHITESPACE); $this->define('/^(?:\\\\u[0-9A-F]{4,4}|[$_\\pL\\p{Nl}])(?:\\\\u[0-9A-F]{4}|[$_\\pL\\pN\\p{Mn}\\p{Mc}\\p{Pc}])*/ui', [$this,'matchWord'] ); $this->define('/^\\s+/u'T_WHITESPACE ); $this->define('!^//.*!'T_COMMENT ); $this->define('!^/\\*.*\\*/!Us', [$this,'matchComment'] ); $this->define('/^"(?:\\\\.|[^\\r\\n\\p{Zl}\\p{Zp}"\\\\])*"/u'T_CONSTANT_ENCAPSED_STRING ); $this->define('/^\'(?:\\\\.|[^\\r\\n\\p{Zl}\\p{Zp}\'\\\\])*\'/u'T_CONSTANT_ENCAPSED_STRING ); $this->define('/^[-+;,<>.=:|&^!?*%~(){}[\\]]/'); parent::__construct($src); } 
public function 
matchWordstring $s ):int { if( array_key_exists($s,self::$words) ){ return self::$words[$s]; } return T_STRING; } 
public function 
matchCommentstring $s ):int { if( substr($s,0,3) === '/**' ){ return T_DOC_COMMENT; } return T_COMMENT; } }
interface 
LocoExtractorInterface 
public function 
setDomainstring $default ):void
public function 
tokenizestring $src ):LocoTokensInterface
public function 
extractLocoExtracted $stringsLocoTokensInterface $tokensstring $fileref '' ):void
public function 
extractSourcestring $srcstring $fileref ):LocoExtracted; }
class 
LocoExtracted implements Countable 
private 
/*array*/ $exp = []; 
private 
/*array*/ $reg = []; 
private 
/*array*/ $dom = []; 
private 
/*string*/ $dflt ''
public function 
extractSourceLocoExtractorInterface $extstring $srcstring $fileref '' ):self $ext->extract$this$ext->tokenize($src), $fileref ); return $this; } 
public function 
export():array { return $this->exp; } 
#[
ReturnTypeWillChange]
public function 
count():int { return count$this->exp ); } 
public function 
getDomainCounts():array { return $this->dom; } 
public function 
setDomainstring $default ):self $this->dflt $default; return $this; } 
public function 
getDomain():string { return $this->dflt; } 
private function 
key( array $entry ):string $key = (string) $entry['source']; foreach( ['context','domain'] as $i => $prop ){ if( array_key_exists($prop,$entry) ) { $add = (string) $entry[$prop]; if( '' !== $add ){ $key .= ord($i).$add; } } } return $key; } 
public function 
pushEntry( array $entrystring $domain ):int { if( '' === $domain || '*' === $domain ){ $domain $this->dflt; } $entry['id'] = ''$entry['target'] = ''$entry['domain'] = $domain$key $this->key($entry); if( isset($this->reg[$key]) ){ $index $this->reg[$key]; $clash $this->exp[$index]; if( $value $this->mergeField$clash$entry'refs'' ') ){ $this->exp[$index]['refs'] = $value; } if( $value $this->mergeField$clash$entry'notes'"\n") ){ $this->exp[$index]['notes'] = $value; } } else { $index count($this->exp); $this->reg[$key] = $index$this->exp[$index] = $entry; if( isset($this->dom[$domain]) ){ $this->dom[$domain]++; } else { $this->dom[$domain] = 1; } } return $index; } 
public function 
pushPlural( array $entryint $sindex ):void $parent $this->exp[$sindex]; $domain $parent['domain']; $pkey $this->key($parent)."\2"; if( ! array_key_exists($pkey,$this->reg) ){ $pindex count($this->exp); $this->reg[$pkey] = $pindex$entry += [ 'id' => '''target' => '''plural' => 1'parent' => $sindex'domain' => $domain, ]; $this->exp[$pindex] = $entry; if( isset($entry['format']) && ! isset( $parent['format']) ) { $this->exp[$sindex]['format'] = $entry['format']; } if( $pindex !== $sindex $entry['plural']) { $this->exp[$sindex]['child'] = $pindex; } } } 
public function 
mergeField( array $old, array $newstring $fieldstring $glue ):string $prev = isset($old[$field]) ? $old[$field] : ''; if( isset($new[$field]) ){ $text $new[$field]; if( '' !== $prev && $prev !== $text ){ if( 'notes' === $field && preg_match'/^'.preg_quotertrim($text,'. '),'/').'[. ]*$/mu'$prev ) ) { $text $prev; } else { $text $prev.$glue.$text; } } return $text; } return $prev; } 
public function 
filterstring $domain ):array { if( '' === $domain ){ $domain $this->dflt; } $map = []; $newOffset 1$matchAll '*' === $domain$raw = [ [ 'id' => '''source' => '''target' => '''domain' => $matchAll '' $domain, ] ]; foreach( $this->exp as $oldOffset => $r ){ if( isset($r['parent']) ){ if( isset($map[$r['parent']]) ){ $r['parent'] = $map$r['parent'] ]; $raw$newOffset++ ] = $r; } } else { if( $matchAll ){ $match true; } else if( isset($r['domain']) ){ $match $domain === $r['domain']; } else { $match $domain === ''; } if( $match ){ $map$oldOffset ] = $newOffset$raw$newOffset++ ] = $r; } } } return $raw; } }
abstract class 
LocoExtractor implements LocoExtractorInterface 
private 
/*array*/ $rules
private 
/*array*/ $wp = []; 
private 
/*string*/ $domain ''
abstract protected function 
fsniffstring $str ):string
abstract protected function 
decapsestring $raw ):string
abstract protected function 
commentstring $comment ):string
public function 
__construct( array $rules ){ $this->rules $rules; } 
public function 
setDomainstring $default ):void $this->domain $default; } 
public function 
headerize( array $tagsstring $domain '' ):self { if( isset($this->wp[$domain]) ){ $this->wp[$domain] += $tags; } else { $this->wp[$domain] = $tags; } return $this; } 
protected function 
getHeaders():array { return $this->wp; } 
final public function 
extractSourcestring $srcstring $fileref ):LocoExtracted $strings = new LocoExtracted$this->extract$strings$this->tokenize($src), $fileref ); return $strings; } 
public function 
rulestring $keyword ):string { return isset($this->rules[$keyword]) ? $this->rules[$keyword] : ''; } 
protected function 
pushLocoExtracted $stringsstring $rule, array $argsstring $comment ''string $ref '' ):?int $s strpos$rule's'); $p strpos$rule'p'); $c strpos$rule'c'); $d strpos$rule'd'); if( false === $s || ! isset($args[$s]) ){ return null; } $msgid $args[$s]; if( ! is_string($msgid) ){ return null; } $entry = [ 'source' => $msgid, ]; if( is_int($c) && isset($args[$c]) ){ $entry['context'] = $args[$c]; } else if( '' === $msgid ){ return null; } if( $ref ){ $entry['refs'] = $ref; } if( is_int($d) && array_key_exists($d,$args) ){ $domain $args[$d]; if( is_null($domain) ){ $domain ''; } } else if( '' === $this->domain ) { $domain $strings->getDomain(); } else { $domain $this->domain; } $format ''$comment $this->comment($comment); if( '' !== $comment ){ if( preg_match('/^xgettext:\\s*([-a-z]+)-format\\s*/mi'$comment$rPREG_OFFSET_CAPTURE ) ){ $format $r[1][0]; $entry['format'] = $format$comment trimsubstr_replace$comment,''$r[0][1], strlen($r[0][0]) ) ); } if( preg_match('/^references?:( *.+:\\d+)*\\s*/mi'$comment$rPREG_OFFSET_CAPTURE ) ){ $entry['refs'] = trim($r[1][0],' '); $comment trimsubstr_replace$comment''$r[0][1], strlen($r[0][0]) ) ); } $entry['notes'] = $comment; } $msgid_plural is_int($p) && isset($args[$p]) ? $args[$p] : ''; if( '' === $format ){ $format $this->fsniff($msgid); if( '' !== $format ){ $entry['format'] = $format; } else if( '' !== $msgid_plural ){ $format $this->fsniff($msgid_plural); if( '' !== $format ){ $entry['format'] = $format; } } } $index $strings->pushEntry($entry,$domain); if( '' !== $msgid_plural ){ $entry = [ 'source' => $msgid_plural, ]; if( '' !== $format ) { $entry['format'] = $format; } $strings->pushPlural($entry,$index); } return $index; } 
protected function 
utf8string $str ):string { if( false === preg_match('//u',$str) ){ $str mb_convert_encoding$str'UTF-8''Windows-1252' ); } return $str; } }
class 
LocoPHPTokens implements LocoTokensInterfaceCountable 
private 
/*int*/ $i null
private 
/*array*/ $tokens
private 
/*array*/ $skip_tokens
private 
/*array*/ $literal_tokens
public function 
__construct( array $tokens ){ $this->tokens $tokens$this->reset(); } 
public function 
reset():void $this->rewind(); $this->literal_tokens = []; $this->skip_tokens = []; } 
public function 
literal( ...$symbols ):self $this->literal_tokens += array_fill_keys($symbols,true); return $this; } 
public function 
ignore( ...$symbols ):LocoTokensInterface $this->skip_tokens += array_fill_keys($symbols,true); return $this; } 
public function 
export():array { return array_valuesiterator_to_array($this) ); } 
public function 
advance() { if( $this->valid() ){ $tok $this->current(); $this->next(); return $tok; } return null; } 
#[
ReturnTypeWillChange]
public function 
rewind():void $this->= ( false === reset($this->tokens) ? null key($this->tokens) ); } 
#[
ReturnTypeWillChange]
public function 
valid():bool { while( is_int($this->i) ){ $tok $this->tokens[$this->i]; if( array_key_existsis_array($tok)?$tok[0]:$tok$this->skip_tokens ) ){ $this->next(); } else { return true; } } return false; } 
#[
ReturnTypeWillChange]
public function 
key():?int { return $this->i; } 
#[
ReturnTypeWillChange]
public function 
next():void $this->= ( false === next($this->tokens) ? null key($this->tokens) ); } 
#[
ReturnTypeWillChange]
public function 
current() { $tok $this->tokens[$this->i]; if( is_array($tok) && isset($this->literal_tokens[$tok[0]]) ){ return $tok[1]; } return $tok; } 
public function 
__toString():string $s = []; foreach( $this as $token ){ $s[] = is_array($token) ? $token[1] : $token; } return implode('',$s); } 
#[
ReturnTypeWillChange]
public function 
count():int { return count($this->tokens); } }
class 
LocoPHPEscapeParser extends LocoEscapeParser 
public function 
__construct(){ parent::__construct( [ 'n' => "\n"'r' => "\r"'t' => "\t"'v' => "\x0B"'f' => "\x0C"'e' => "\x1B"'$' => '$''\\' => '\\''"' => '"', ] ); } 
protected function 
stripSlashesstring $s ):string { return preg_replace_callback('/\\\\(x[0-9A-Fa-f]{1,2}|[0-3]?[0-7]{1,2})/', [$this,'unescapeMatch'], $s, -1$n ); } }
function 
loco_unescape_php_stringstring $s ):string { static $l; if( is_null($l) ) { $l = new LocoPHPEscapeParser; } return $l->unescape($s); }
function 
loco_decapse_php_stringstring $s ):string { if( '' === $s ){ return ''; } $q $s[0]; if( "'" === $q ){ return str_replace( ['\\'.$q'\\\\'], [$q'\\'], substr$s1, -) ); } if( '"' !== $q ){ return $s; } return loco_unescape_php_stringsubstr($s,1,-1) ); }
function 
loco_parse_php_commentstring $comment ):string $comment trim$comment,"/ \n\r\t" ); if( '' !== $comment && '*' === $comment[0] ){ $lines = []; $junk "\r\t/ *"; foreach( explode("\n",$comment) as $line ){ $line trim($line,$junk); if( '' !== $line ){ $lines[] = $line; } } $comment implode("\n"$lines); } return $comment; }
function 
loco_parse_wp_commentstring $block ):array { $header = []; if( '/*' === substr($block,0,2) ){ $junk "\r\t/ *"; foreach( explode("\n"$block) as $line ){ if( false !== ( $i strpos($line,':') ) ){ $key substr($line,0,$i); $val substr($line,++$i); $headertrim($key,$junk) ] = trim($val,$junk); } } } return $header; }
class 
LocoPHPExtractor extends LocoExtractor 
private 
/*array*/ $defs = []; 
public function 
tokenizestring $src ):LocoTokensInterface { return new LocoPHPTokenstoken_get_all($src) ); } 
public function 
decapsestring $raw ):string { return loco_decapse_php_string$raw ); } 
public function 
fsniffstring $str ):string $format ''$offset 0; while( preg_match('/%(?:[1-9]\\d*\\$)?(?:\'.|[-+0 ])*\\d*(?:\\.\\d+)?(.|$)/',$str,$r,PREG_OFFSET_CAPTURE,$offset) ){ $type $r[1][0]; list($match,$offset) = $r[0]; if( '%' === $type && '%%' !== $match ){ return ''; } if( '' === $type || ! preg_match('/^[bcdeEfFgGosuxX%]/',$type) ){ return ''; } $offset += strlen($match); if( preg_match('/^% +[a-z]/i',$match) || preg_match('/^%[b-ou-x]/i',$match) ){ continue; } $format 'php'; } return $format; } 
protected function 
commentstring $comment ):string { return preg_replace('/^translators:\\s+/mi'''loco_parse_php_comment($comment) ); } 
public function 
definestring $namestring $value ):self $this->defs[$name] = $value; return $this; } 
public function 
extractLocoExtracted $stringsLocoTokensInterface $tokensstring $fileref '' ):void $tokens->ignore(T_WHITESPACE); $n 0$depth 0$comment ''$narg 0$args = []; $ref ''$rule ''$wp $this->getHeaders(); $tokens->rewind(); while( $tok $tokens->advance() ){ if( is_string($tok) ){ $s $tok$t null; } else { $t $tok[0]; $s $tok[1]; } if( $depth ){ if( ')' === $s || ']' === $s ){ if( === --$depth ){ if( $this->push$strings$rule$args$comment$ref ) ){ $n++; } $comment ''; } } else if( '(' === $s || '[' === $s ){ $depth++; $args[$narg] = null; } else if( === $depth ){ if( ',' === $s ){ $narg++; } else if( T_CONSTANT_ENCAPSED_STRING === $t ){ $s self::utf8($s); $args[$narg] = $this->decapse($s); } else if( T_STRING === $t && array_key_exists($s,$this->defs) ){ $args[$narg] = $this->defs[$s]; } else { $args[$narg] = null; } } } else if( T_COMMENT === $t || T_DOC_COMMENT === $t ){ $was_header false$s self::utf8($s); if( === $n ){ if( false !== strpos($s,'* @package') ){ $was_header true; } if( $wp && ( $header loco_parse_wp_comment($s) ) ){ foreach( $wp as $domain => $tags ){ foreach( array_intersect_key($header,$tags) as $tag => $text ){ $ref $fileref $fileref.':'.$tok[2]: ''$meta $tags[$tag]; if( is_string($meta) ){ $meta = ['notes'=>$meta]; trigger_error$tag.' header defaulted to "notes"',E_USER_DEPRECATED); } $strings->pushEntry( ['source'=>$text,'refs'=>$ref] + $meta, (string) $domain ); $was_header true; } } } } if( ! $was_header ) { $comment $s; } } else if( T_STRING === $t && '(' === $tokens->advance() && ( $rule $this->rule($s) ) ){ $ref $fileref $fileref.':'.$tok[2]: ''$depth 1$args = []; $narg 0; } else if( '' !== $comment && ! preg_match('!^[/* ]+(translators|xgettext):!im',$comment) ){ $comment ''; } } } }
class 
LocoJsExtractor extends LocoPHPExtractor 
public function 
tokenizestring $src ):LocoTokensInterface { return new LocoJsTokens($src); } 
public function 
fsniffstring $str ):string { return parent::fsniff($str) ? 'javascript' ''; } 
public function 
decapsestring $raw ):string { return LocoJsTokens::decapse($raw); } }
class 
LocoTwigExtractor extends LocoPHPExtractor 
public function 
tokenizestring $src ):LocoTokensInterface { return parent::tokenize'<?php '.preg_replace('/{#([^#]+)#}/su','/*\\1*/',$src) ); } }
class 
LocoBladeExtractor extends LocoPHPExtractor 
public function 
tokenizestring $src ):LocoTokensInterface { return parent::tokenize'<?php '.preg_replace('/{{--(.+)--}}/su','/*\\1*/',$src) ); } }
class 
LocoWpJsonExtractor implements LocoExtractorInterface 
private static 
/*array*/ $types = []; 
private 
/*string*/ $base '.'
private 
/*string*/ $domain ''
public function 
__construct() { if( defined('ABSPATH') ){ $this->setBasertrim(ABSPATH,'/').'/wp-includes' ); } } 
public function 
setBasestring $path ):void $this->base $path; } 
private function 
getTypestring $type ):stdClass { if( array_key_exists($type,self::$types) ){ return self::$types[$type]; } $path $this->base.'/'.$type.'-i18n.json'; if ( ! file_exists($path) ) { throw new Exceptionbasename($path).' not found in '.$this->base ); } return json_decodefile_get_contents($path) ); } 
public function 
tokenizestring $src ): LocoTokensInterface $raw json_decode($src,true); if( ! is_array($raw) || ! array_key_exists('$schema',$raw) ){ throw new InvalidArgumentException('Invalid JSON'); } if( ! preg_match('!^https?://schemas.wp.org/trunk/(block|theme)\\.json!'$raw['$schema'], $r ) ){ throw new InvalidArgumentException('Unsupported schema'); } if( '' === $this->domain && array_key_exists('textdomain',$raw) ){ $this->domain $raw['textdomain']; } return new LocoWpJsonStrings$raw$this->getType($r[1]) ); } 
public function 
setDomainstring $default ):void $this->domain $default; } 
public function 
extractLocoExtracted $stringsLocoTokensInterface $tokensstring $fileref '' ):void { if( ! preg_match('/:\\d+$/',$fileref) ){ $fileref.=':1'; } $tokens->rewind(); while( $tok $tokens->advance() ){ $tok['refs'] = $fileref$strings->pushEntry$tok$this->domain ); } } 
final public function 
extractSourcestring $srcstring $fileref ):LocoExtracted $strings = new LocoExtracted$this->extract$strings$this->tokenize($src), $fileref ); return $strings; } }
class 
LocoWpJsonStrings extends ArrayIterator implements LocoTokensInterface 
public function 
__construct( array $rawstdClass $tpl ){ parent::__construct(); $this->walk$tpl$raw ); } 
public function 
advance() { $tok $this->current(); $this->next(); return $tok; } 
public function 
ignore( ...$symbols ):LocoTokensInterface { return $this; } 
private function 
walk/*mixed*/ $tpl/*mixed*/ $raw ):void { if( is_string($tpl) && is_string($raw) ) { $this->offsetSetnull, [ 'context' => $tpl'source' => $raw, ] ); return; } if( is_array($tpl) && is_array($raw) ) { foreach ( $raw as $value ) { self::walk$tpl[0], $value ); } } else if( is_object($tpl) && is_array($raw) ) { $group_key '*'; foreach ( $raw as $key => $value ) { if ( isset($tpl->$key) ) { $this->walk$tpl->$key$value ); } else if ( isset($tpl->$group_key) ) { $this->walk$tpl->$group_key$value ); } } } } }
function 
loco_wp_extractorstring $type 'php'string $ext '' ):LocoExtractorInterface { if( 'json' === $type ){ return new LocoWpJsonExtractor; } static $rules = [ '__' => 'sd''_e' => 'sd''_c' => 'sd''_n' => 'sp_d''_n_noop' => 'spd''_nc' => 'sp_d''__ngettext' => 'spd''__ngettext_noop' => 'spd''_x' => 'scd''_ex' => 'scd''_nx' => 'sp_cd''_nx_noop' => 'spcd''esc_attr__' => 'sd''esc_html__' => 'sd''esc_attr_e' => 'sd''esc_html_e' => 'sd''esc_attr_x' => 'scd''esc_html_x' => 'scd', ]; if( 'php' === $type ){ return substr($ext,-9) === 'blade.php' ? new LocoBladeExtractor($rules) : new LocoPHPExtractor($rules); } if( 'js' === $type ){ return new LocoJsExtractor($rules); } if( 'twig' === $type ){ return new LocoTwigExtractor($rules); } throw new InvalidArgumentException('No extractor for '.$type); }
function 
loco_string_percentint $nint $t ):string { if( ! $t || ! $n ){ return '0'; } if( $t === $n ){ return '100'; } $dp 0$n 100 $n $t; if( $n 99 ){ return rtrimnumber_formatmin$n99.9 ), ++$dp ), '.0' ); } if( $n 0.5 ){ $n max$n0.0001 ); do { $s number_format$n, ++$dp ); } while( preg_match('/^0\\.0+$/',$s) && $dp ); return substr($s,1); } return number_format$n$dp ); }
function 
loco_print_progressint $translatedint $untranslatedint $flagged ):void $total $translated $untranslated$complete loco_string_percent$translated $flagged$total ); $class 'progress'; if( ! $translated && ! $flagged ){ $class .= ' empty'; } else if( '100' === $complete ){ $class .= ' done'; } echo '<div class="',$class,'"><div class="t">'; if( $flagged ){ $s loco_string_percent$flagged$total ); echo '<div class="bar f" style="width:',$s,'%">&nbsp;</div>'; } if( '0' === $complete ){ echo '&nbsp;'; } else { $class 'bar p'$p = (int) $complete$class .= sprintf(' p-%u'10*floor($p/10) ); $style 'width:'.$complete.'%'; if( $flagged ){ $remain 100.0 - (float) $s$style .= '; max-width: '.sprintf('%s',$remain).'%'; } echo '<div class="',$class,'" style="'.$style.'">&nbsp;</div>'; } echo '</div><div class="l">',$complete,'%</div></div>'; }
class 
LocoFuzzyMatcher implements Countable 
private 
/*array*/ $pot = []; 
private 
/*array*/ $po = []; 
private 
/*array*/ $diff = []; 
private 
/*float*/ $dmax .20
#[
ReturnTypeWillChange]
public function 
count():int { return count($this->pot); } 
public function 
unmatched():array { return array_values($this->pot); } 
public function 
redundant():array { return array_values($this->po); } 
public function 
setFuzziness$s ):void { if( $this->po ){ throw new LogicException('Cannot setFuzziness() after calling match()'); } $this->dmax = (float) max0min( (int) $s100 ) ) / 100; } 
public function 
additerable $a ):void $source = isset($a['source']) ? (string) $a['source'] : ''$context = isset($a['context']) ? (string) $a['context'] : ''$key $source."\4".$context$this->pot[$key] = $a; } 
private function 
keyiterable $a ):string $source = isset($a['source']) ? (string) $a['source'] : ''$context = isset($a['context']) ? (string) $a['context'] : ''; return $source."\4".$context; } 
protected function 
getRefiterable $a ):?iterable $key $this->key($a); return array_key_exists($key,$this->pot) ? $this->pot[$key] : null; } 
public function match( 
iterable $a ):?iterable $old $this->key($a); if( isset($this->pot[$old]) ){ $new $this->pot[$old]; unset($this->pot[$old]); return $new; } $this->po[$old] = $a$target = isset($a['target']) ? (string) $a['target'] : ''$comment = isset($a['comment']) ? (string) $a['comment'] : ''; if( '' === $target && '' === $comment ){ return null; } if( $this->dmax ){ foreach( $this->pot as $new => $_ ){ $dist $this->distance($old,$new); if( -!== $dist ){ $this->diff[] = [ $old$new$dist ]; } } } return null; } 
private function 
distancestring $astring $b ):int $a strtolower($a); $b strtolower($b); if( $a === $b ){ return 0; } $lenA strlen($a); $lenB strlen($b); $lenDiff abs($lenA-$lenB); $max min($lenA,$lenB) + $lenDiff$max = (int) ceil$this->dmax $max ); if( $max $lenDiff ) { return -1; } $len max($lenA,$lenB); if( $len 256 ){ $d levenshtein($a,$b); return $d $max ? -$d; } $d 0; for( $i 0$i $len$i+=$max ){ $aa substr($a,$i,$max); $bb substr($b,$i,$max); $d += levenshtein($aa,$bb); if( $d $max ){ return -1; } } return $d; } 
public function 
getFuzzyMatches():array { $pairs = []; usort$this->diff, [__CLASS__,'compareDistance'] ); foreach( $this->diff as $pair ){ list($old,$new) = $pair; if( ! array_key_exists($new,$this->pot) || ! array_key_exists($old,$this->po) ){ continue; } $pairs[] = [ $this->po[$old], $this->pot[$new], ]; unset($this->po[$old]); unset($this->pot[$new]); if( ! $this->po || ! $this->pot ){ break; } } $this->diff = []; return $pairs; } 
public function 
exportPo():LocoPoIterator $p = new LocoPoIterator([ ['source' => ''], ]); $p->concat($this->pot); return $p; } 
private static function 
compareDistance( array $a, array $b ):int { return $a[2] - $b[2]; } }
if( 
function_exists('loco_check_extension') ) { loco_check_extension('mbstring'); }