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: