e97e1ff3d9cfedd31751f4e1b29ba8e522e0a535
[friendica.git/.git] / src / Core / Console / PoToPhp.php
1 <?php
2
3 namespace Friendica\Core\Console;
4
5 /**
6  * Read a messages.po file and create strings.php in the same directory
7  *
8  * @author Hypolite Petovan <mrpetovan@gmail.com>
9  */
10 class PoToPhp extends \Asika\SimpleConsole\Console
11 {
12         protected $helpOptions = ['h', 'help', '?'];
13
14         const DQ_ESCAPE = "__DQ__";
15
16         protected function getHelp()
17         {
18                 $help = <<<HELP
19 console php2po - Generate a strings.php file from a messages.po file
20 Usage
21         bin/console php2po <path/to/messages.po> [-h|--help|-?] [-v]
22
23 Description
24         Read a messages.po file and create the according strings.php in the same directory
25
26 Options
27         -h|--help|-?  Show help information
28         -v            Show more debug information.
29 HELP;
30                 return $help;
31         }
32
33         protected function doExecute()
34         {
35                 if ($this->getOption('v')) {
36                         $this->out('Class: ' . __CLASS__);
37                         $this->out('Arguments: ' . var_export($this->args, true));
38                         $this->out('Options: ' . var_export($this->options, true));
39                 }
40
41                 if (count($this->args) == 0) {
42                         $this->out($this->getHelp());
43                         return 0;
44                 }
45
46                 if (count($this->args) > 1) {
47                         throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
48                 }
49
50                 $a = get_app();
51
52                 $pofile = realpath($this->getArgument(0));
53
54                 if (!file_exists($pofile)) {
55                         throw new \RuntimeException('Supplied file path doesn\'t exist.');
56                 }
57
58                 if (!is_writable(dirname($pofile))) {
59                         throw new \RuntimeException('Supplied directory isn\'t writable.');
60                 }
61
62                 $outfile = dirname($pofile) . DIRECTORY_SEPARATOR . 'strings.php';
63
64                 if (strstr($outfile, 'util')) {
65                         $lang = 'en';
66                 } else {
67                         $lang = str_replace('-', '_', basename(dirname($pofile)));
68                 }
69
70                 $this->out('Out to ' . $outfile);
71
72                 $out = "<?php\n\n";
73
74                 $infile = file($pofile);
75                 $k = '';
76                 $v = '';
77                 $arr = false;
78                 $ink = false;
79                 $inv = false;
80                 $escape_s_exp = '|[^\\\\]\$[a-z]|';
81
82                 foreach ($infile as $l) {
83                         $l = str_replace('\"', self::DQ_ESCAPE, $l);
84                         $len = strlen($l);
85                         if ($l[0] == "#") {
86                                 $l = "";
87                         }
88
89                         if (substr($l, 0, 15) == '"Plural-Forms: ') {
90                                 $match = [];
91                                 preg_match("|nplurals=([0-9]*); *plural=(.*)[;\\\\]|", $l, $match);
92                                 $cond = str_replace('n', '$n', $match[2]);
93                                 // define plural select function if not already defined
94                                 $fnname = 'string_plural_select_' . $lang;
95                                 $out .= 'if(! function_exists("' . $fnname . '")) {' . "\n";
96                                 $out .= 'function ' . $fnname . '($n){' . "\n";
97                                 $out .= '       $n = intval($n);' . "\n";
98                                 $out .= '       return ' . $cond . ';' . "\n";
99                                 $out .= '}}' . "\n";
100                         }
101
102                         if ($k != '' && substr($l, 0, 7) == 'msgstr ') {
103                                 if ($ink) {
104                                         $ink = false;
105                                         $out .= '$a->strings["' . $k . '"] = ';
106                                 }
107
108                                 if ($inv) {
109                                         $inv = false;
110                                         $out .= '"' . $v . '"';
111                                 }
112
113                                 $v = substr($l, 8, $len - 10);
114                                 $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
115
116                                 $inv = true;
117                         }
118
119                         if ($k != "" && substr($l, 0, 7) == 'msgstr[') {
120                                 if ($ink) {
121                                         $ink = false;
122                                         $out .= '$a->strings["' . $k . '"] = ';
123                                 }
124                                 if ($inv) {
125                                         $inv = false;
126                                         $out .= '"' . $v . '"';
127                                 }
128
129                                 if (!$arr) {
130                                         $arr = true;
131                                         $out .= "[\n";
132                                 }
133
134                                 $match = [];
135                                 preg_match("|\[([0-9]*)\] (.*)|", $l, $match);
136                                 $out .= "\t"
137                                         . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[1])
138                                         . ' => '
139                                         . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[2])
140                                         . ",\n";
141                         }
142
143                         if (substr($l, 0, 6) == 'msgid_') {
144                                 $ink = false;
145                                 $out .= '$a->strings["' . $k . '"] = ';
146                         }
147
148                         if ($ink) {
149                                 $k .= trim($l, "\"\r\n");
150                                 $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
151                         }
152
153                         if (substr($l, 0, 6) == 'msgid ') {
154                                 if ($inv) {
155                                         $inv = false;
156                                         $out .= '"' . $v . '"';
157                                 }
158
159                                 if ($k != "") {
160                                         $out .= ($arr) ? "];\n" : ";\n";
161                                 }
162
163                                 $arr = false;
164                                 $k = str_replace("msgid ", "", $l);
165                                 if ($k != '""') {
166                                         $k = trim($k, "\"\r\n");
167                                 } else {
168                                         $k = '';
169                                 }
170
171                                 $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
172                                 $ink = true;
173                         }
174
175                         if ($inv && substr($l, 0, 6) != "msgstr") {
176                                 $v .= trim($l, "\"\r\n");
177                                 $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
178                         }
179                 }
180
181                 if ($inv) {
182                         $inv = false;
183                         $out .= '"' . $v . '"';
184                 }
185
186                 if ($k != '') {
187                         $out .= ($arr ? "];\n" : ";\n");
188                 }
189
190                 $out = str_replace(self::DQ_ESCAPE, '\"', $out);
191                 if (!file_put_contents($outfile, $out)) {
192                         throw new \RuntimeException('Unable to write to ' . $outfile);
193                 }
194
195                 return 0;
196         }
197
198         private function escapeDollar($match)
199         {
200                 return str_replace('$', '\$', $match[0]);
201         }
202 }