Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
557 daniel-mar 1
#!/usr/bin/env php
366 daniel-mar 2
<?php
3
 
4
/*
5
 * OIDplus 2.0
511 daniel-mar 6
 * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
366 daniel-mar 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
$dir = __DIR__ . '/../../';
31
 
32
// ---
33
 
34
$langs = array();
632 daniel-mar 35
$tmp1 = glob($dir.'/plugins/language/'.'*'.'/messages.xml');
36
$tmp2 = glob($dir.'/plugins/_thirdParty/'.'*'.'/language/'.'*'.'/messages.xml');
37
$tmp = array_merge($tmp1, $tmp2);
366 daniel-mar 38
foreach ($tmp as $tmp2) {
39
        $tmp3 = explode('/', $tmp2);
40
        $lang = $tmp3[count($tmp3)-2];
41
        if ($lang == 'enus') continue; // ignore base lang
42
        $langs[] = $lang;
43
}
44
 
45
// ---
46
 
47
$all_strings = array();
48
 
49
$it = new RecursiveDirectoryIterator($dir);
50
foreach(new RecursiveIteratorIterator($it) as $file) {
624 daniel-mar 51
        if ((strpos(str_replace('\\','/',realpath($file)),'/vendor/') !== false) && (strpos(str_replace('\\','/',realpath($file)),'/vendor/danielmarschall/') === false)) continue; // ignore third-party-code
366 daniel-mar 52
        if (strpos(str_replace('\\','/',realpath($file)),'/dev/') !== false) continue; // ignore development utilities
53
        if ($file->getExtension() == 'php') {
54
                $cont = file_get_contents($file);
55
                $cont = phpRemoveComments($cont);
624 daniel-mar 56
#               $cont = str_replace('function _L($str, ...$sprintfArgs) {', '', $cont);
57
                $cont = str_replace('_L($', '', $cont);
366 daniel-mar 58
                $strings = get_php_L_strings($cont);
59
                $strings_test = get_js_L_strings($cont);
60
 
61
                if (serialize($strings) != serialize($strings_test)) {
62
                        echo "Attention: File ".realpath($file)." ambiguous _L() functions\n";
63
                }
64
 
65
                $all_strings = array_merge($all_strings, $strings);
66
        }
67
        if ($file->getExtension() == 'js') {
68
                $cont = file_get_contents($file);
69
                $cont = str_replace('function _L()', '', $cont);
70
                $strings = get_js_L_strings($cont);
71
                $all_strings = array_merge($all_strings, $strings);
72
        }
73
}
74
 
75
foreach ($all_strings as $str) {
76
        test_missing_placeholder($str);
77
}
78
 
79
$all_strings = array_unique($all_strings);
80
sort($all_strings);
81
 
82
// ---
83
 
84
foreach ($langs as $lang) {
85
        $translation_array = array();
632 daniel-mar 86
        $translation_files = array_merge(
87
                glob($dir.'/plugins/language/'.$lang.'/messages.xml'),
88
                glob($dir.'/plugins/_thirdParty/'.'*'.'/language/'.$lang.'/messages.xml')
89
        );
90
        $translation_file = count($translation_files) > 0 ? $translation_files[0] : null;
366 daniel-mar 91
        if (file_exists($translation_file)) {
632 daniel-mar 92
                $xml = simplexml_load_string(file_get_contents($translation_file));
93
                if (!$xml) {
94
                        echo "STOP: Cannot load $translation_file\n";
95
                        continue;
96
                }
97
                foreach ($xml->message as $msg) {
366 daniel-mar 98
                        $src = trim($msg->source->__toString());
99
                        $dst = trim($msg->target->__toString());
100
                        $translation_array[$src] = $dst;
101
                }
102
        }
103
 
104
        // ---
105
 
106
        echo "Processing ".realpath($translation_file)." ...\n";
107
 
108
        $stats_total = 0;
109
        $stats_translated = 0;
110
        $stats_not_translated = 0;
111
 
112
        $cont = '';
394 daniel-mar 113
        $cont .= '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'."\n";
114
        $cont .= '<translation'."\n";
115
        $cont .= '      xmlns="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.4.1"'."\n";
116
        $cont .= '      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'."\n";
117
        $cont .= '      xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.4.1 https://oidplus.viathinksoft.com/oidplus/plugins/messages.xsd">'."\n";
118
        $cont .= "\n";
366 daniel-mar 119
        foreach ($all_strings as $string) {
120
                $stats_total++;
506 daniel-mar 121
                $string = trim($string);
366 daniel-mar 122
                $cont .= "      <message>\n";
123
                $cont .= "              <source><![CDATA[\n";
124
                $cont .= "              $string\n";
125
                $cont .= "              ]]></source>\n";
126
                if (isset($translation_array[$string]) && !empty($translation_array[$string])) {
506 daniel-mar 127
                        $translation_array[$string] = trim($translation_array[$string]);
366 daniel-mar 128
                        $stats_translated++;
129
                        if (substr_count($string,'%') != substr_count($translation_array[$string],'%')) {
130
                                echo "\tAttention: Number of %-Replacements differs at translation of message '$string'\n";
131
                        }
132
                        $cont .= "              <target><![CDATA[\n";
133
                        $cont .= "              ".$translation_array[$string]."\n";
134
                        $cont .= "              ]]></target>\n";
135
                        test_missing_placeholder($translation_array[$string]);
136
                } else {
137
                        $stats_not_translated++;
138
                        $cont .= "              <target><![CDATA[\n";
139
                        $cont .= "              ]]></target><!-- TODO: TRANSLATE -->\n";
140
                }
141
                $cont .= "      </message>\n";
142
        }
143
        $cont .= "</translation>\n";
144
        file_put_contents($translation_file, $cont);
145
 
146
        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";
147
        echo "\tDone...";
148
}
149
 
150
if (count($langs) > 0) {
151
        echo "All done!\n";
152
} else {
153
        echo "Attention: No language plugins found!\n";
154
}
155
 
156
# ---
157
 
158
function get_js_L_strings($cont) {
159
        // Works with JavaScript and PHP
160
        $cont = preg_replace('@/\\*.+\\*/@ismU', '', $cont);
161
        $cont = str_replace('\\"', chr(1), $cont);
162
        $cont = str_replace("\\'", chr(2), $cont);
163
        $cont = str_replace("\\\\", "\\", $cont);
386 daniel-mar 164
        $m = array();
366 daniel-mar 165
        preg_match_all('@[^_A-Za-z0-9]_L\\(.*(["\'])(.+)\\1@ismU', $cont, $m);
166
        foreach ($m[2] as &$x) {
167
                $x = str_replace(chr(1), '"', $x);
168
                $x = str_replace(chr(2), "'", $x);
169
        }
170
        return $m[2];
171
}
172
 
173
function get_php_L_strings($cont) {
174
        // Works only with PHP
175
        $out = array();
176
        $tokens = token_get_all($cont);
177
        $activated = 0;
178
        foreach ($tokens as $token) {
179
                if (is_array($token)) {
180
                        if (($token[0] == T_STRING) && ($token[1] == '_L')) {
181
                                $activated = 1;
182
                        } else if (($activated == 1) && ($token[0] == T_CONSTANT_ENCAPSED_STRING)) {
183
                                $tmp = stripcslashes($token[1]);
184
                                $out[] = substr($tmp,1,strlen($tmp)-2);
185
                                $activated = 0;
186
                        }
187
                }
188
        }
189
        return $out;
190
}
191
 
192
function test_missing_placeholder($test) {
193
        $max = -1;
194
        for ($i=99; $i>=1; $i--) {
195
                if (strpos($test, '%'.$i) !== false) {
196
                        $max = $i;
197
                        break;
198
                }
199
        }
200
 
201
        for ($i=1; $i<=$max; $i++) {
202
                if (strpos($test, '%'.$i) === false) {
203
                        echo "Attention: %$i is missing in string '$test'!\n";
204
                        $max = $i;
205
                        break;
206
                }
207
        }
370 daniel-mar 208
 
209
        $test = preg_replace('@%([1-9][0-9]|%)*@ism', '', $test);
210
        if (strpos($test,'%') !== false) {
211
                echo "Attention: Wrong percentage sign in '$test'!\n";
212
        }
366 daniel-mar 213
}
214
 
215
# ---
216
 
217
function phpRemoveComments($fileStr) {
218
 
219
        // https://stackoverflow.com/questions/503871/best-way-to-automatically-remove-comments-from-php-code
220
 
221
        $newStr  = '';
222
 
223
        $commentTokens = array(T_COMMENT);
224
 
225
        if (defined('T_DOC_COMMENT')) $commentTokens[] = T_DOC_COMMENT; // PHP 5
226
        if (defined('T_ML_COMMENT'))  $commentTokens[] = T_ML_COMMENT;  // PHP 4
227
 
228
        $tokens = token_get_all($fileStr);
229
 
230
        foreach ($tokens as $token) {
231
                if (is_array($token)) {
232
                        if (in_array($token[0], $commentTokens)) continue;
233
                        $token = $token[1];
234
                }
235
                $newStr .= $token;
236
        }
237
 
238
        return $newStr;
239
 
240
}