PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / gettext / gettext / src / Generator / MoGenerator.php

MoGenerator.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at vendor/gettext/gettext/src/Generator/MoGenerator.php

152 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types = 1);
3
4 namespace Gettext\Generator;
5
6 use Gettext\Translation;
7 use Gettext\Translations;
8
9 final class MoGenerator extends Generator
10 {
11 private $includeHeaders = false;
12
13 public function includeHeaders(bool $includeHeaders = true): self
14 {
15 $this->includeHeaders = $includeHeaders;
16
17 return $this;
18 }
19
20 public function generateString(Translations $translations): string
21 {
22 $messages = [];
23
24 if ($this->includeHeaders) {
25 $lines = [];
26
27 foreach ($translations->getHeaders() as $name => $value) {
28 $lines[] = sprintf('%s: %s', $name, $value);
29 }
30
31 $messages[''] = implode("\n", $lines);
32 }
33
34 foreach ($translations as $translation) {
35 if (!$translation->getTranslation() || $translation->isDisabled()) {
36 continue;
37 }
38
39 if ($context = $translation->getContext()) {
40 $originalString = "{$context}\x04{$translation->getOriginal()}";
41 } else {
42 $originalString = $translation->getOriginal();
43 }
44
45 $messages[$originalString] = $translation;
46 }
47
48 ksort($messages, SORT_STRING);
49 $numEntries = count($messages);
50 $originalsTable = '';
51 $translationsTable = '';
52 $originalsIndex = [];
53 $translationsIndex = [];
54 $pluralForm = $translations->getHeaders()->getPluralForm();
55 $pluralSize = is_array($pluralForm) ? ($pluralForm[0] - 1) : null;
56
57 foreach ($messages as $originalString => $translation) {
58 if (is_string($translation)) {
59 $translationString = $translation;
60 } elseif (self::hasPluralTranslations($translation)) {
61 $originalString .= "\x00{$translation->getPlural()}";
62 $translationString = "{$translation->getTranslation()}\x00"
63 .implode("\x00", $translation->getPluralTranslations($pluralSize));
64 } else {
65 $translationString = $translation->getTranslation();
66 }
67
68 $originalsIndex[] = [
69 'relativeOffset' => strlen($originalsTable),
70 'length' => strlen((string) $originalString),
71 ];
72 $originalsTable .= $originalString."\x00";
73 $translationsIndex[] = [
74 'relativeOffset' => strlen($translationsTable),
75 'length' => strlen($translationString),
76 ];
77 $translationsTable .= $translationString."\x00";
78 }
79
80 // Offset of table with the original strings index: right after the header (which is 7 words)
81 $originalsIndexOffset = 7 * 4;
82
83 // Size of table with the original strings index
84 $originalsIndexSize = $numEntries * (4 + 4);
85
86 // Offset of table with the translation strings index: right after the original strings index table
87 $translationsIndexOffset = $originalsIndexOffset + $originalsIndexSize;
88
89 // Size of table with the translation strings index
90 $translationsIndexSize = $numEntries * (4 + 4);
91
92 // Hashing table starts after the header and after the index table
93 $originalsStringsOffset = $translationsIndexOffset + $translationsIndexSize;
94
95 // Translations start after the keys
96 $translationsStringsOffset = $originalsStringsOffset + strlen($originalsTable);
97
98 // Let's generate the .mo file binary data
99 $mo = '';
100
101 // Magic number
102 $mo .= pack('L', 0x950412de);
103
104 // File format revision
105 $mo .= pack('L', 0);
106
107 // Number of strings
108 $mo .= pack('L', $numEntries);
109
110 // Offset of table with original strings
111 $mo .= pack('L', $originalsIndexOffset);
112
113 // Offset of table with translation strings
114 $mo .= pack('L', $translationsIndexOffset);
115
116 // Size of hashing table: we don't use it.
117 $mo .= pack('L', 0);
118
119 // Offset of hashing table: it would start right after the translations index table
120 $mo .= pack('L', $translationsIndexOffset + $translationsIndexSize);
121
122 // Write the lengths & offsets of the original strings
123 foreach ($originalsIndex as $info) {
124 $mo .= pack('L', $info['length']);
125 $mo .= pack('L', $originalsStringsOffset + $info['relativeOffset']);
126 }
127
128 // Write the lengths & offsets of the translated strings
129 foreach ($translationsIndex as $info) {
130 $mo .= pack('L', $info['length']);
131 $mo .= pack('L', $translationsStringsOffset + $info['relativeOffset']);
132 }
133
134 // Write original strings
135 $mo .= $originalsTable;
136
137 // Write translation strings
138 $mo .= $translationsTable;
139
140 return $mo;
141 }
142
143 private static function hasPluralTranslations(Translation $translation): bool
144 {
145 if (!$translation->getPlural()) {
146 return false;
147 }
148
149 return implode('', $translation->getPluralTranslations()) !== '';
150 }
151 }
152