Subversion Repositories oidplus

Rev

Rev 366 | Rev 386 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
366 daniel-mar 1
#!/usr/bin/php
2
<?php
3
 
4
/*
5
 * OIDplus 2.0
6
 * Copyright 2020 Daniel Marschall, ViaThinkSoft
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
 
21
// This script updates the language message files (adding new entries and
22
// removing entries that are not existing anymore).
23
// It requires that PHP scripts are using following syntax for translations:
24
//             _L('hello world',optionalParams) <recommended>
25
//             _L("hello world",optionalParams)
26
// and JS files:
27
//             _L('hello world',optionalParams)
28
//             _L("hello world",optionalParams) <recommended>
29
 
30
 
31
$dir = __DIR__ . '/../../';
32
 
33
// ---
34
 
35
$langs = array();
36
$tmp = glob($dir.'/plugins/language/*/messages.xml');
37
foreach ($tmp as $tmp2) {
38
        $tmp3 = explode('/', $tmp2);
39
        $lang = $tmp3[count($tmp3)-2];
40
        if ($lang == 'enus') continue; // ignore base lang
41
        $langs[] = $lang;
42
}
43
 
44
// ---
45
 
46
$all_strings = array();
47
 
48
$it = new RecursiveDirectoryIterator($dir);
49
foreach(new RecursiveIteratorIterator($it) as $file) {
50
        if (strpos(str_replace('\\','/',realpath($file)),'/3p/') !== false) continue; // ignore third-party-code
51
        if (strpos(str_replace('\\','/',realpath($file)),'/dev/') !== false) continue; // ignore development utilities
52
        if ($file->getExtension() == 'php') {
53
                $cont = file_get_contents($file);
54
                $cont = phpRemoveComments($cont);
55
                $cont = str_replace('function _L($str, ...$sprintfArgs) {', '', $cont);
56
                $strings = get_php_L_strings($cont);
57
                $strings_test = get_js_L_strings($cont);
58
 
59
                if (serialize($strings) != serialize($strings_test)) {
60
                        echo "Attention: File ".realpath($file)." ambiguous _L() functions\n";
61
                }
62
 
63
                $all_strings = array_merge($all_strings, $strings);
64
        }
65
        if ($file->getExtension() == 'js') {
66
                $cont = file_get_contents($file);
67
                $cont = str_replace('function _L()', '', $cont);
68
                $strings = get_js_L_strings($cont);
69
                $all_strings = array_merge($all_strings, $strings);
70
        }
71
}
72
 
73
foreach ($all_strings as $str) {
74
        test_missing_placeholder($str);
75
}
76
 
77
$all_strings = array_unique($all_strings);
78
sort($all_strings);
79
 
80
// ---
81
 
82
foreach ($langs as $lang) {
83
        $translation_array = array();
84
        $translation_file = $dir.'/plugins/language/'.$lang.'/messages.xml';
85
        if (file_exists($translation_file)) {
86
        $xml = simplexml_load_string(file_get_contents($translation_file));
87
        if (!$xml) {
88
                echo "STOP: Cannot load $translation_file\n";
89
                continue;
90
        }
91
        foreach ($xml->message as $msg) {
92
                        $src = trim($msg->source->__toString());
93
                        $dst = trim($msg->target->__toString());
94
                        $translation_array[$src] = $dst;
95
                }
96
        }
97
 
98
        // ---
99
 
100
        echo "Processing ".realpath($translation_file)." ...\n";
101
 
102
        $stats_total = 0;
103
        $stats_translated = 0;
104
        $stats_not_translated = 0;
105
 
106
        $cont = '';
107
        $cont .= "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
108
        $cont .= "<translation>\n";
109
        foreach ($all_strings as $string) {
110
                $stats_total++;
111
                $cont .= "      <message>\n";
112
                $cont .= "              <source><![CDATA[\n";
113
                $cont .= "              $string\n";
114
                $cont .= "              ]]></source>\n";
115
                if (isset($translation_array[$string]) && !empty($translation_array[$string])) {
116
                        $stats_translated++;
117
                        if (substr_count($string,'%') != substr_count($translation_array[$string],'%')) {
118
                                echo "\tAttention: Number of %-Replacements differs at translation of message '$string'\n";
119
                        }
120
                        $cont .= "              <target><![CDATA[\n";
121
                        $cont .= "              ".$translation_array[$string]."\n";
122
                        $cont .= "              ]]></target>\n";
123
                        test_missing_placeholder($translation_array[$string]);
124
                } else {
125
                        $stats_not_translated++;
126
                        $cont .= "              <target><![CDATA[\n";
127
                        $cont .= "              ]]></target><!-- TODO: TRANSLATE -->\n";
128
                }
129
                $cont .= "      </message>\n";
130
        }
131
        $cont .= "</translation>\n";
132
        file_put_contents($translation_file, $cont);
133
 
134
        echo "\t$stats_total total messages, $stats_translated already translated (".round($stats_translated/$stats_total*100,2)."%), $stats_not_translated not translated (".round($stats_not_translated/$stats_total*100,2)."%)\n";
135
        echo "\tDone...";
136
}
137
 
138
if (count($langs) > 0) {
139
        echo "All done!\n";
140
} else {
141
        echo "Attention: No language plugins found!\n";
142
}
143
 
144
# ---
145
 
146
function get_js_L_strings($cont) {
147
        // Works with JavaScript and PHP
148
        $cont = preg_replace('@/\\*.+\\*/@ismU', '', $cont);
149
        $cont = str_replace('\\"', chr(1), $cont);
150
        $cont = str_replace("\\'", chr(2), $cont);
151
        $cont = str_replace("\\\\", "\\", $cont);
152
        preg_match_all('@[^_A-Za-z0-9]_L\\(.*(["\'])(.+)\\1@ismU', $cont, $m);
153
        foreach ($m[2] as &$x) {
154
                $x = str_replace(chr(1), '"', $x);
155
                $x = str_replace(chr(2), "'", $x);
156
        }
157
        return $m[2];
158
}
159
 
160
function get_php_L_strings($cont) {
161
        // Works only with PHP
162
        $out = array();
163
        $tokens = token_get_all($cont);
164
        $activated = 0;
165
        foreach ($tokens as $token) {
166
                if (is_array($token)) {
167
                        if (($token[0] == T_STRING) && ($token[1] == '_L')) {
168
                                $activated = 1;
169
                        } else if (($activated == 1) && ($token[0] == T_CONSTANT_ENCAPSED_STRING)) {
170
                                $tmp = stripcslashes($token[1]);
171
                                $out[] = substr($tmp,1,strlen($tmp)-2);
172
                                $activated = 0;
173
                        }
174
                }
175
        }
176
        return $out;
177
}
178
 
179
function test_missing_placeholder($test) {
180
        $max = -1;
181
        for ($i=99; $i>=1; $i--) {
182
                if (strpos($test, '%'.$i) !== false) {
183
                        $max = $i;
184
                        break;
185
                }
186
        }
187
 
188
        for ($i=1; $i<=$max; $i++) {
189
                if (strpos($test, '%'.$i) === false) {
190
                        echo "Attention: %$i is missing in string '$test'!\n";
191
                        $max = $i;
192
                        break;
193
                }
194
        }
370 daniel-mar 195
 
196
        $test = preg_replace('@%([1-9][0-9]|%)*@ism', '', $test);
197
        if (strpos($test,'%') !== false) {
198
                echo "Attention: Wrong percentage sign in '$test'!\n";
199
        }
366 daniel-mar 200
}
201
 
202
# ---
203
 
204
function phpRemoveComments($fileStr) {
205
 
206
        // https://stackoverflow.com/questions/503871/best-way-to-automatically-remove-comments-from-php-code
207
 
208
        $newStr  = '';
209
 
210
        $commentTokens = array(T_COMMENT);
211
 
212
        if (defined('T_DOC_COMMENT')) $commentTokens[] = T_DOC_COMMENT; // PHP 5
213
        if (defined('T_ML_COMMENT'))  $commentTokens[] = T_ML_COMMENT;  // PHP 4
214
 
215
        $tokens = token_get_all($fileStr);
216
 
217
        foreach ($tokens as $token) {
218
                if (is_array($token)) {
219
                        if (in_array($token[0], $commentTokens)) continue;
220
                        $token = $token[1];
221
                }
222
                $newStr .= $token;
223
        }
224
 
225
        return $newStr;
226
 
227
}