Merge pull request #4678 from annando/issue-4666
[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 .= '       return ' . $cond . ';' . "\n";
98                                 $out .= '}}' . "\n";
99                         }
100
101                         if ($k != '' && substr($l, 0, 7) == 'msgstr ') {
102                                 if ($ink) {
103                                         $ink = false;
104                                         $out .= '$a->strings["' . $k . '"] = ';
105                                 }
106
107                                 if ($inv) {
108                                         $inv = false;
109                                         $out .= '"' . $v . '"';
110                                 }
111
112                                 $v = substr($l, 8, $len - 10);
113                                 $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
114
115                                 $inv = true;
116                         }
117
118                         if ($k != "" && substr($l, 0, 7) == 'msgstr[') {
119                                 if ($ink) {
120                                         $ink = false;
121                                         $out .= '$a->strings["' . $k . '"] = ';
122                                 }
123                                 if ($inv) {
124                                         $inv = false;
125                                         $out .= '"' . $v . '"';
126                                 }
127
128                                 if (!$arr) {
129                                         $arr = true;
130                                         $out .= "[\n";
131                                 }
132
133                                 $match = [];
134                                 preg_match("|\[([0-9]*)\] (.*)|", $l, $match);
135                                 $out .= "\t"
136                                         . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[1])
137                                         . ' => '
138                                         . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[2])
139                                         . ",\n";
140                         }
141
142                         if (substr($l, 0, 6) == 'msgid_') {
143                                 $ink = false;
144                                 $out .= '$a->strings["' . $k . '"] = ';
145                         }
146
147                         if ($ink) {
148                                 $k .= trim($l, "\"\r\n");
149                                 $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
150                         }
151
152                         if (substr($l, 0, 6) == 'msgid ') {
153                                 if ($inv) {
154                                         $inv = false;
155                                         $out .= '"' . $v . '"';
156                                 }
157
158                                 if ($k != "") {
159                                         $out .= ($arr) ? "];\n" : ";\n";
160                                 }
161
162                                 $arr = false;
163                                 $k = str_replace("msgid ", "", $l);
164                                 if ($k != '""') {
165                                         $k = trim($k, "\"\r\n");
166                                 } else {
167                                         $k = '';
168                                 }
169
170                                 $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
171                                 $ink = true;
172                         }
173
174                         if ($inv && substr($l, 0, 6) != "msgstr") {
175                                 $v .= trim($l, "\"\r\n");
176                                 $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
177                         }
178                 }
179
180                 if ($inv) {
181                         $inv = false;
182                         $out .= '"' . $v . '"';
183                 }
184
185                 if ($k != '') {
186                         $out .= ($arr ? "];\n" : ";\n");
187                 }
188
189                 $out = str_replace(self::DQ_ESCAPE, '\"', $out);
190                 if (!file_put_contents($outfile, $out)) {
191                         throw new \RuntimeException('Unable to write to ' . $outfile);
192                 }
193
194                 return 0;
195         }
196
197         private function escapeDollar($match)
198         {
199                 return str_replace('$', '\$', $match[0]);
200         }
201 }