We now can produce the temporary folders correctly
[isso.git] / docs / mkstrings
1 #!/usr/bin/php
2 <?php
3 /*=====================================================================*\
4 || ###################################################################
5 || # mkstrings (ISSO: Lost In Translation) [#]version[#]
6 || # Copyright ©2002-[#]year[#] Iris Studios, Inc.
7 || #
8 || # This program is free software; you can redistribute it and/or modify
9 || # it under the terms of the GNU General Public License as published by
10 || # the Free Software Foundation; version [#]gpl[#] of the License.
11 || #
12 || # This program is distributed in the hope that it will be useful, but
13 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 || # more details.
16 || #
17 || # You should have received a copy of the GNU General Public License along
18 || # with this program; if not, write to the Free Software Foundation, Inc.,
19 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 || ###################################################################
21 \*=====================================================================*/
22
23 // ###################################################################
24
25 if ($argc < 3)
26 {
27 print("mkstrings creates XML string files from PHP sources that");
28 print("\nhave been localized using ISSO's localization module");
29 print("\n\n");
30 print("Usage: mkstrings <object caller> <ISSO path> [path] [-o <out>]");
31 print("\n\t<object caller> The PHP class that contains the string() method,");
32 print("\n\t\t\tthe localizer function; this is usually \"lang\".");
33 print("\n\t\t\tDo not include the object operator.");
34 print("\n\t<ISSO path> Path to the location of the ISSO framework");
35 print("\n\t[path] Path in which to parse strings of *.php");
36 print("\n\t[-o <out>] Out file path; by default this is ./out.strings.xml");
37 print("\n");
38 exit;
39 }
40
41 // ###################################################################
42
43 $caller = $argv[1];
44 $issopath = $argv[2];
45 $search = ($argv[3] ? $argv[3] : './');
46 $out = ($argv[4] ? $argv[5] : './out.strings.xml');
47
48 require_once($issopath . DIRECTORY_SEPARATOR . 'kernel.php');
49 $isso =& $_isso;
50 $isso->sourcepath = $isso->fetch_sourcepath($issopath);
51
52 $isso->load('functions');
53
54 if (is_dir($out))
55 {
56 $out = $isso->fetch_sourcepath($out) . 'out.strings.xml';
57 }
58
59 print("Linking framework and needed modules\n");
60
61 // ###################################################################
62
63 $filelist = $funct->scandir($search);
64
65 foreach ($filelist AS $dirpath => $nodes)
66 {
67 $dirpath = ($dirpath ? $isso->fetch_sourcepath($dirpath) : '');
68 foreach ($nodes AS $file)
69 {
70 $ext = $funct->fetch_extension($file);
71 if ($ext == 'php')
72 {
73 $files[] = $isso->fetch_sourcepath($search) . $dirpath . $file;
74 }
75 else if ($ext == 'xml' OR $ext == 'tpl' OR $ext == 'html' OR $ext == 'htm')
76 {
77 $templates[] = $isso->fetch_sourcepath($search) . $dirpath . $file;
78 }
79 }
80 }
81
82 print("Generating file node list\n");
83
84 // ###################################################################
85
86 foreach ($files AS $file)
87 {
88 $data = file_get_contents($file);
89 if ($data === false)
90 {
91 print("ERROR reading file: $file\n");
92 continue;
93 }
94 print("Read file node: $file\n");
95
96 $strings[] = break_tokens($data, $caller);
97 }
98
99 // ###################################################################
100
101 foreach ($templates AS $file)
102 {
103 $data = file_get_contents($file);
104 if ($data === false)
105 {
106 print("ERROR reading file: $file\n");
107 }
108 print("Read file node: $file\n");
109
110 $strings[] = parse_template($data);
111 }
112
113 // ###################################################################
114
115 foreach ($strings AS $subset)
116 {
117 foreach ($subset AS $string)
118 {
119 $masters["$string"] = $string;
120 }
121 }
122
123 // ###################################################################
124
125 print("Found a total of " . count($masters) . " localizable strings\n");
126
127 $f = fopen($out, 'w');
128
129 fwrite($f, '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n\n");
130 fwrite($f, '<localization>' . "\n\n");
131
132 foreach ($masters AS $string)
133 {
134 fwrite($f, "\t<string>\n");
135 fwrite($f, "\t\t<key><![CDATA[$string]]></key>\n");
136 fwrite($f, "\t\t<value><![CDATA[$string]]></value>\n");
137 fwrite($f, "\t</string>\n");
138 }
139
140 fwrite($f, "\n</localization>");
141
142 fclose($f);
143
144 print("Exported strings as localizable file: out.strings.xml");
145 print("\n");
146
147 // ###################################################################
148
149 function break_tokens($fileraw, $caller)
150 {
151 $tokens = token_get_all($fileraw);
152
153 print("\t... breaking symbols into tokens\n");
154
155 // nominalize tokens
156 foreach ($tokens AS $id => $token)
157 {
158 if (is_array($token))
159 {
160 $tokens["$id"][2] = $name = token_name($token[0]);
161 $tokens["$id"][3] = $id;
162 }
163 else
164 {
165 $tokens["$id"] = array(
166 0 => -1,
167 1 => $token,
168 2 => 'X_OTHER',
169 3 => $id
170 );
171 }
172 }
173
174 $stack = 0;
175 $count = 0;
176 $strings = array();
177
178 // parse calls
179 foreach ($tokens AS $id => $token)
180 {
181 // looking for initial operator
182 if ($stack == 0)
183 {
184 if ($token[2] == 'T_VARIABLE' OR $token[2] == 'T_STRING')
185 {
186 if ($token[1] == '$' . $caller OR $token[1] == $caller)
187 {
188 $stack++;
189 }
190 }
191 }
192 // need an object operator to continue
193 else if ($stack == 1)
194 {
195 if ($token[2] == 'T_OBJECT_OPERATOR')
196 {
197 $stack++;
198 }
199 else
200 {
201 $stack = 0;
202 }
203 }
204 // look for the string() method
205 else if ($stack == 2)
206 {
207 if ($token[1] == 'string')
208 {
209 $stack++;
210 }
211 else
212 {
213 $stack = 0;
214 }
215 }
216 // first T_CONSTANT_ENCAPSED_STRING will do
217 else if ($stack >= 3)
218 {
219 if ($token[2] == 'T_CONSTANT_ENCAPSED_STRING')
220 {
221 $strings[] = extract_string($token[1]);
222 $count++;
223 $stack = 0;
224 }
225 }
226 }
227
228 print("\t... found $count localizable strings\n");
229 print("\n");
230
231 return $strings;
232 }
233
234 // ###################################################################
235
236 function extract_string($string)
237 {
238 $encap = $string{0};
239
240 $string = str_replace('\\' . $encap, $encap, $string);
241 $string = substr($string, 1, strlen($string) - 2);
242
243 return $string;
244 }
245
246 // ###################################################################
247
248 function parse_template($raw)
249 {
250 $length = strlen($raw);
251
252 $stack = 0;
253 $capture = false;
254 $index = 0;
255 $strings = array();
256
257 for ($i = 0; $i < $length; $i++)
258 {
259 if ($capture)
260 {
261 if ($raw["$i"] == '"' AND $raw[ $i - 1 ] != '\\' AND $raw[ $i + 1 ] == '}' AND $raw[ $i - 1 ] != '@')
262 {
263 $stack = 0;
264 $capture = false;
265 $strings[ ++$index ] = '';
266 }
267 else
268 {
269 $strings["$index"] .= $raw["$i"];
270 }
271 }
272 else
273 {
274 if ($raw["$i"] == '{')
275 {
276 $stack++;
277 $capture = false;
278 }
279 else if ($stack == 1)
280 {
281 if ($raw["$i"] == '@')
282 {
283 $stack++;
284 }
285 else
286 {
287 $stack = 0;
288 }
289 $capture = false;
290 }
291 else if ($stack == 2)
292 {
293 if ($raw["$i"] == '"')
294 {
295 $stack++;
296 $capture = true;
297 }
298 else
299 {
300 $stack = 0;
301 $capture = false;
302 }
303 }
304 }
305 }
306
307 print("\t... found " . count($strings) . " localizable strings\n");
308 print("\n");
309
310 return $strings;
311 }
312
313 /*=====================================================================*\
314 || ###################################################################
315 || # $HeadURL$
316 || # $Id$
317 || ###################################################################
318 \*=====================================================================*/
319 ?>