1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51: function decodeQuotes($str) {
52: return preg_replace('/"/','"',$str);
53: }
54: function encodeQuotes($str) {
55: return htmlspecialchars($str);
56:
57: }
58:
59:
60:
61:
62:
63: if(!isset($messagePath))
64: $messagePath = 'protected/messages';
65:
66:
67: $targetFile = '';
68: if(isset($_GET['file'])){
69: if(strpos($_GET['file'],'/')!==false){
70: throw new CHttpException(400,'This file is not within allowed translations paths. Do not repeat this request.');
71: }
72: }
73: if(isset($_GET['file']) && file_exists($messagePath.'/template/'.$_GET['file']))
74: $targetFile = $_GET['file'];
75:
76: if(!file_exists($messagePath))
77: die('Error: '.$messagePath.' not found.');
78: $messageDir = scandir($messagePath);
79:
80: $messages = array();
81:
82: foreach($messageDir as $langPack) {
83: if($langPack == '.' || $langPack == '..' || filetype($messagePath.'/'.$langPack) != "dir")
84: continue;
85:
86: $messageFiles = scandir($messagePath.'/'.$langPack);
87: if(file_exists($messagePath.'/'.$langPack.'/app.php')) {
88: $appFile = include($messagePath.'/'.$langPack.'/app.php');
89: if(isset($appFile['languageName']) && !empty($appFile['languageName']))
90: $messages[$langPack][] = $appFile['languageName'];
91: else
92: continue;
93: }
94:
95: foreach($messageFiles as $messageFile) {
96: if($messageFile == '.' || $messageFile == '..' || filetype($messagePath.'/'.$langPack.'/'.$messageFile) == "dir")
97: continue;
98: $messages[$langPack][] = $messageFile;
99: }
100: }
101:
102:
103: if(!array_key_exists('template',$messages))
104: die('Error: Template files not found.');
105:
106:
107:
108:
109: if(isset($_POST['data']) && isset($_POST['file'])) {
110: ini_set('max_input_vars',9999);
111: foreach($messages as $langPack=>$messageFiles) {
112: if(!isset($_POST['data'][$langPack]))
113: die('Error: language pack <b>'.strtoupper($langPack).'</b> missing.');
114:
115: }
116:
117: $fileHeader = '<?php
118: return array (
119: ';
120:
121: foreach(array_keys($messages) as $langPack) {
122:
123: $file = fopen($messagePath.'/'.$langPack.'/'.$_POST['file'],'w');
124:
125: fwrite($file,$fileHeader);
126:
127: $index = 0;
128: for($i=0; $i<count($_POST['data']['template']); $i++) {
129:
130: $line = $_POST['data']['template'][$i];
131:
132:
133: if(preg_match('/^s*\/\/\s*$/u',$line)) {
134: fwrite($file,"\n");
135: } else if(preg_match('/^s*\/\/.*$/u',$line)) {
136: fwrite($file,$line."\n");
137: } else {
138: if($langPack == 'template') {
139: if($line == 'languageName')
140: fwrite($file,"'languageName'=>'Template',\n");
141: else
142: fwrite($file,"'".addcslashes(decodeQuotes($line),'\'')."'=>'',\n");
143: } else{
144: if(isset($_POST['data'][$langPack][$index])){
145: fwrite(
146: $file,
147: "'".addcslashes(decodeQuotes($line),'\'')."'=>'".
148: addcslashes(decodeQuotes($_POST['data'][$langPack][$index]),'\'') .
149: "',\n");
150: }else{
151: fwrite($file,"'".addcslashes(decodeQuotes($line),'\'')."'=>'". '' ."',\n");
152: }
153: }
154: $index++;
155: }
156: }
157: fwrite($file,');');
158: fclose($file);
159: }
160:
161:
162:
163:
164: }
165:
166: ?><!DOCTYPE html>
167: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
168: <head>
169: <meta name="language" content="en" />
170: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
171: <title>X2Engine Translation Manager</title>
172: <link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->baseUrl; ?>/css/translationManager.css" />
173: <script type="text/javascript" src="<?php echo Yii::app()->baseUrl; ?>/js/jquery-1.6.2.min.js"></script>
174: <script type="text/javascript" src="<?php echo Yii::app()->baseUrl; ?>/js/jquery-ui-1.8.16.custom.min.js"></script>
175: <script type="text/javascript">
176: var lang = 'none';
177:
178: $(function() {
179: $('input[type="text"]').bind('change keydown',function() {
180: if(this.value==this.defaultValue)
181: $(this).addClass('modified');
182: else
183: $(this).removeClass('modified');
184: });
185:
186: $('#translationForm').submit(function() { $('input.comment').val(function(index,value) { return '// '+value; }); });
187:
188: $('.content table').delegate('a.add-comment','click',function() { addComment(this); return false; })
189: .delegate('a.add-entry','click',function() { addLine(this); return false; })
190: .delegate('a.remove','click',function() { removeLine(this); return false; })
191: .delegate('.language','click',function() { googleTranslate(this); });
192:
193: showLang('none',null);
194: });
195: function showAll(object) {
196: if(lang != 'all')
197: $(object).closest('tr').find('.translation, .language').not('.'+lang).toggle();
198: }
199:
200: function showLang(newLang,object) {
201: lang = newLang;
202: $('#languageMenu tr').removeClass();
203: $(object).closest('tr').addClass('active');
204:
205:
206: if(lang == 'all')
207: $('.translation, .language').show();
208: else {
209: $('.translation, .language').hide();
210: if(lang != 'none')
211: $('.translation.'+lang+', .language.'+lang).show();
212: }
213: }
214:
215: function googleTranslate(object) {
216: var message = $(object).closest('tr').find('.source input').val();
217: var lang = $(object).html();
218: if(lang == 'zh_cn')
219: lang = 'zh-CN';
220: if(lang == 'he')
221: lang = 'iw';
222: var url = 'http://translate.google.com/#en|'+lang+'|'+encodeURI(message);
223:
224:
225: var windowName = "popUp";
226:
227: window.open(url, windowName, "width=800,height=400");
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242: }
243:
244: function toggleGoogle() {
245: if($('#iframeBox').height() == 0) {
246: $('#contentPane').animate({height:400});
247: $('#iframeBox').animate({height:250});
248: } else {
249: $('#contentPane').animate({height:650});
250: $('#iframeBox').animate({height:0});
251: }
252: }
253:
254: var entryHeader = ' <tr class="entry">\n';
255: var entryFooter = '\
256: <td class="controls" width="100">\
257: <a href="#" class="add-entry" title="Add Entry">[+]</a>\
258: <a href="#" class="add-comment" title="Add Comment">[/*]</a>\
259: <a href="#" class="remove" title="Delete Line">[–]</a>\
260: </td>\
261: </tr>';
262:
263: function (object) {
264: var commentField = ' <td colspan="3"><input name="data[template][]" type="text" class="comment"></td>'
265: $(object).closest('.entry').after(entryHeader + commentField + entryFooter);
266: }
267:
268: function addLine(object) {
269:
270: var langPacks = [<?php
271: foreach(array_keys($messages) as $langPack)
272: if($langPack != 'template') echo '"'.$langPack.'",';
273: ?>];
274:
275: var newEntry = '\
276: <td width="30" class="controls">\
277: <a href="#" onclick="showAll(this); return false;" title="Show all languages">All</a>\
278: </td>\
279: <td width="45%">\
280: <div class="source">\
281: <input name="data[template][]" type="text">\
282: </div>\
283: </td>\
284: <td>';
285:
286: for(var i=0; i<langPacks.length; i++) {
287: newEntry += '\
288: <div class="language '+langPacks[i]+'">'+langPacks[i]+'</div>\
289: <div class="translation '+langPacks[i]+'">\
290: <input name="data['+langPacks[i]+'][]" type="text">\
291: </div>\
292: ';
293: }
294: $(object).closest('.entry').after(entryHeader + newEntry + entryFooter);
295: }
296:
297: function removeLine(object) {
298: if(confirm('Are you sure you want to delete this entry from all language packs?')) {
299: $(object).closest('.entry').remove();
300: return true;
301: } else
302: return false
303: }
304: </script>
305: </head>
306: <body>
307:
308: <div class="side-bar">
309: <!-- File Menu - select which language files to edit -->
310: <table class="rounded" style="width:100%;">
311: <tr>
312: <th width="75%">File</th>
313: <th>Lines</th>
314: </tr>
315: <?php
316: for($i=1; $i<count($messages['template']); $i++) {
317: $fileName = $messages['template'][$i];
318: $lines = count(file($messagePath.'/template/'.$fileName));
319:
320: $active = ($fileName == $targetFile);
321: ?>
322: <tr<?php if($active) echo ' class="active"'; ?>>
323: <td><?php echo $active ? CHtml::encode ($fileName) : '<a href="translationManager?file='.CHtml::encode ($fileName).'">'.CHtml::encode ($fileName).'</a>'; ?></td>
324: <td><?php echo $lines; ?></td>
325: </tr>
326: <?php
327: }
328:
329:
330: ?>
331: </table>
332: <?php
333: if(!empty($targetFile)) {
334: ?>
335: <!-- Language Menu - select which language to show, and find out which languages are incomplete -->
336: <table class="rounded" id="languageMenu" style="width:100%;">
337: <tr>
338: <th width="50%">Language</th>
339: <th>Status</th>
340: </tr>
341: <tr class="active">
342: <td colspan="2">
343: <a href="#" onclick="showLang('all',this); return false;">Show All</a> |
344: <a href="#" onclick="showLang('none',this); return false;">Hide All</a>
345: </td>
346: </tr>
347: <?php
348: $langPackFiles = array();
349: $langPackFiles['template'] = include($messagePath.'/template/'.$targetFile);
350:
351: foreach($messages as $langPack => $messageFiles) {
352: if($langPack == 'template')
353: continue;
354:
355: $fileName = $messagePath.'/'.$langPack.'/'.$targetFile;
356:
357:
358: $missing = !file_exists($fileName);
359: $incomplete = false;
360:
361: $langPackFiles[$langPack] = $missing? array() : include($fileName);
362: foreach($langPackFiles['template'] as $key => $value) {
363: if(!array_key_exists($key,$langPackFiles[$langPack]) || $langPackFiles[$langPack][$key] == '')
364: $incomplete = true;
365: }
366:
367: ?>
368: <tr>
369: <td><a href="#" onclick="showLang('<?php echo $langPack; ?>',this); return false;"><?php echo $messageFiles[0]; ?></a></td>
370: <td><?php
371: if($missing)
372: echo '<span class="not-ok">File Missing</span>';
373: else if($incomplete)
374: echo '<span class="not-ok">Incomplete</span>';
375: else
376: echo '<span class="ok">OK</span>'; ?>
377: </td>
378: </tr>
379: <?php
380: }
381: ?>
382: </table>
383: </div>
384: <!-- Main window - view, edit and translations -->
385: <div class="content-container">
386: <div class="content">
387: <form method="POST" action="<?php echo Yii::app()->controller->createAbsoluteUrl('/admin/translationManager',array('file'=>$targetFile)); ?>" id="translationForm">
388: <?php
389: echo X2Html::csrfToken ();
390: ?>
391: <input type="hidden" name="file" value="<?php echo CHtml::encode ($_GET['file']); ?>">
392: <table class="rounded" style="table-layout:fixed;">
393: <tr>
394: <th width="50%" height="15" style="height:16px;">Message</th>
395: <th width="50%" height="15" style="height:16px;">Translation</th>
396: </tr>
397: <tr>
398: <td colspan="3" id="contentPane" style="padding:0;height:650px;">
399: <div class="scroll-box">
400: <table class="translation-list">
401: <?php
402: $dataStarted = false;
403: $currentTemplate = file($messagePath.'/template/'.$targetFile);
404: foreach($currentTemplate as $line) {
405:
406: if(!$dataStarted) {
407: if(preg_match('/^\s*return array/',$line))
408: $dataStarted = true;
409: else
410: continue;
411: }
412:
413: $matches = array();
414:
415: if(preg_match("/'(.+)'=>'(.*)',/u",$line,$matches)) { ?>
416: <tr class="entry">
417: <td width="30" class="controls"><a href="#" onclick="showAll(this); return false;" title="Show all languages">All</a></td>
418: <td width="42%">
419: <div class="source"><input name="data[template][]" type="text" value="<?php echo encodeQuotes(stripslashes($matches[1])); ?>"></div>
420: </td>
421: <td><?php
422: foreach($messages as $langPack => $messageFiles) {
423: if($langPack == 'template')
424: continue;
425:
426: $translation = isset($langPackFiles[$langPack][stripslashes($matches[1])])? $langPackFiles[$langPack][stripslashes($matches[1])] : '';
427: ?>
428: <div class="language <?php echo $langPack; ?>"><?php echo $langPack; ?></div>
429: <div class="translation <?php echo $langPack; if(empty($translation)) echo ' empty'; ?>">
430: <input name="data[<?php echo $langPack; ?>][]" type="text" value="<?php echo encodeQuotes(stripslashes($translation)); ?>">
431: </div>
432: <?php } ?>
433: </td>
434: <td class="controls" width="100">
435: <a href="#" class="add-entry" title="Add Entry">[+]</a>
436: <a href="#" class="add-comment" title="Add Comment">[437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: