Odyssey
hcuTransAm.prg
1 <?php
2  /*
3  * File: hcuTransAm (TRANSlate And Maintain)
4  *
5  * Purpose: Maintains the various hcuTranslate.lang files so they do not need to be
6  * edited by hand.
7  *
8  * NOTES:
9  * 1. This file is independant of the home banking system and is used only to maintain
10  * the languange dictionary files.
11  * 2. There is no need for CU files or anything. The include files are only for look and feel and
12  * to import the correct Kendo UI and JQuery files.
13  * 3. SPB 10/30/2015-- Now uses monitorView.i
14  *
15  */
16 
17  $monLibrary= dirname(__FILE__) . "/../library";
18  $sharedLibrary= dirname(__FILE__) . "/../../shared/library";
19  $bankingDir = dirname(__FILE__) . "/../../banking";
20  require_once("$monLibrary/cu_top.i");
21  require_once("$monLibrary/ck_hticket.i");
22  require_once("$monLibrary/monitorView.i");
23  require_once("$sharedLibrary/hcuTranslate.i");
24  require_once("$sharedLibrary/cu_func.i");
25 
26  if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
27  // ** Permissions failed
28  // ** redirect to new page
29  header("Location: /hcuadm/hcu_noperm.prg");
30  exit;
31  }
32 
33  //********** functions (more functions at end of file) ************//
34  // Function for sorting the translation table keys
35  function TransTableSort( $a, $b ) {
36  $result = strcasecmp( $a, $b );
37 
38  if ( $result == 0 ) {
39  $result = strcmp( $a, $b );
40  }
41 
42  return $result;
43  } // end TransTableSort
44  /*
45  * Local Variables
46  *
47  */
48 
49  // ** INSERT BUSINESS LOGIC FOR THIS FORM
50 
51  $languageAry = array("en_US"=>"English", "es_US"=>"Spanish", "pl_US"=>"Polish");
52  $languageKeys = array_keys($languageAry);
53 
54  // this is a list of keys that would show up as duplicates (untranslated) to the English
55  $ignoreList["es_US"] = array( "Total", "Quicken WebConnect", "PIN", "No", "Error" );
56  $ignoreList["pl_US"] = array();
57 
58  try {
59  // ** Import the necessary fields
60  $dms_ok=array("action"=>"string", "key"=>"string", "screen" => "string",
61  "delimiter"=>"string" );
62  dms_import_v2( $HB_ENV, "MY_POST", $dms_ok);
63 
64  $self = $_SERVER['SCRIPT_NAME'];
65  $baseURL = $_SERVER["SCRIPT_NAME"];
66 
67  $action = $HB_ENV["MY_POST"]["action"];
68  $screen = $HB_ENV["MY_POST"]["screen"];
69 
70  if ( $action == "import" &&
71  $screen == "import" ) {
72  // import the data and add the appropriate entries to the translation
73 
74  // check the delimiter (make sure no one messed with it)
75  $delimiter = $HB_ENV["MY_POST"]["delimiter"];
76  $delimiterChoices = array( ",", "|", ";", "^" );
77  if ( !in_array( $delimiter, $delimiterChoices ) && $delimiter != "tab" ) {
78  throw new ErrorException("Error - Invalid Delimiter");
79  }
80 
81  if ( $delimiter == "tab" ) {
82  $delimiter = "\t";
83  }
84 
85  $uploadFile = "/tmp/hcuTransUpload.txt";
86 
87  // show the imported data
88  $importLines = file( $uploadFile, FILE_IGNORE_NEW_LINES );
89 
90  $importInfo = array();
91  $keyList = array();
92  for ( $i = 0; $i < count( $importLines ); $i++ ) {
93  $line = trim( $importLines[$i] );
94  if ( substr( $line, 0, 1) == "#" ) continue;
95 
96  $lineParts = explode( $delimiter, $line );
97 
98  // save the unique keys
99  if ( !in_array($lineParts[1], $keyList) ) {
100  $keyList[] = $lineParts[1];
101  }
102 
103  // put into array indexed by [key][lang]
104  $importInfo[$lineParts[1]][$lineParts[0]] = ConvertFromUTF8( $lineParts[2] );
105  }
106 
107  // now make each line have the key, lang1, lang2, ..., langN entries
108  $importEntries = array();
109  for ( $k = 0; $k < count( $keyList ); $k++ ) {
110  $entry = array();
111  $entry["key"] = $keyList[$k];
112 
113  $englishPhrase = "";
114  $englishEntry = 0;
115  for ( $l = 0; $l < count( $languageKeys ); $l++ ) {
116  // save the english phrase in case a language is missing
117  if ( $l == $englishEntry ) {
118  $englishPhrase = $importInfo[$keyList[$k]][$languageKeys[$l]];
119  }
120 
121  $phrase = $importInfo[$keyList[$k]][$languageKeys[$l]];
122  if ( !strlen( trim( $phrase ) ) ) {
123  $phrase = $englishPhrase;
124  }
125 
126  $entry[$languageKeys[$l]] = $phrase;
127  }
128 
129  $importEntries[] = $entry;
130  }
131 
132  // for each language, get the Translation table and update/add any keys
133  for ( $l = 0; $l < count( $languageKeys ); $l++ ) {
134  // get the Translation table
135  $transTable = new hcu_talk_base( $languageKeys[$l] );
136 
137  for ( $k = 0; $k < count( $keyList ); $k++ ) {
138  $key = $keyList[$k];
139  $found = false;
140  // search for the phrase
141  for ( $p = 0; $p < count( $importEntries ); $p++ ) {
142  if ( $importEntries[$p]["key"] == $key ) {
143  $phrase = trim( $importEntries[$p][$languageKeys[$l]] );
144  $found = true;
145  break;
146  }
147  }
148 
149  // add/update the key
150  if ( $found ) {
151  $transTable->messages[$key] = addslashes( $phrase );
152  }
153  }
154 
155  // sort so it is easier for humans to find the key
156  uksort( $transTable->messages, "TransTableSort" );
157 
158  // update the table file
159  WriteTranslationTableFile($languageKeys[$l], $transTable);
160  }
161 
162  // let the user edit things
163  $action = "edit";
164  }
165 
166  if ( $action == "sort" ) {
167  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
168  $transTable = new hcu_talk_base( $languageKeys[$i] );
169 
170  // sort so it is easier for humans to find the key
171  uksort( $transTable->messages, "TransTableSort" );
172 
173  WriteTranslationTableFile( $languageKeys[$i], $transTable );
174  }
175 
176  // go to the edit feature so the user can see what damage they have wrought
177  $action = "edit";
178  } else if ( $action == "removeEntry") {
179  $key = $HB_ENV["MY_POST"]["key"];
180 
181  // get the keys
182  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
183  $transTable = new hcu_talk_base( $languageKeys[$i] );
184 
185  // update/add the entry
186  unset( $transTable->messages[$key] );
187 
188  // sort so it is easier for humans to find the key
189  uksort( $transTable->messages, "TransTableSort" );
190 
191  WriteTranslationTableFile( $languageKeys[$i], $transTable );
192  }
193 
194 
195  header('Content-Type: application/json');
196  print json_encode("");
197 
198  // leave now so no more data gets returned
199  exit;
200  } else if ( $action == "updateEntry") {
201 
202  $key = $HB_ENV["MY_POST"]["key"];
203 
204  // get the keys
205  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
206  $transTable = new hcu_talk_base( $languageKeys[$i] );
207 
208  // update/add the entry (make sure no single quote in $key)
209  $key = str_replace( "'", "", $key );
210  $transTable->messages[$key] = $_REQUEST[$languageKeys[$i]] ;
211 
212  // sort so it is easier for humans to find the key
213  uksort( $transTable->messages, "TransTableSort" );
214 
215  WriteTranslationTableFile( $languageKeys[$i], $transTable );
216  }
217 
218 
219  header('Content-Type: application/json');
220  print json_encode("");
221 
222  // leave now so no more data gets returned
223  exit;
224  }
225 
226  /*
227  * ** START CONTENT
228  */
229  // change the header for certain actions
230  $actionName = "";
231  if ( $action == "edit" )
232  $actionName = "(Edit)";
233  else if ( $action == "check" )
234  $actionName = "(Check)";
235  else if ( $action == "import" )
236  $actionName = "(Import)";
237 
238  // figure out the callback host because this script can be called from Monitor or Dev
239  $callbackHost = trim( $_REQUEST["callback"] );
240  if ( $callbackHost == "" ) $callbackHost = "www.homecu.net";
241 
242  // set the content type appropriately
243  header('content-type: text/html; charset: utf-8');
244 
245  $title= "Credit Union Home Banking Settings $actionName";
246  printMonitorPageTop($title, $homecuKendoVersion, $cloudfrontDomainName);
247  ?>
248  <style>
249  body {
250  font-family: Arial, Helvetica, sans-serif;
251  background-color: #EFEFEF;
252  }
253  header {
254  margin: 0 0 20px 0;
255  background-color: #666;
256  color: white;
257  border-bottom: 5px solid #cc0000;
258  }
259  header .header-title {
260  padding: 12px 0 5px 56px;
261  font-size: 29px;
262  font-weight: 100;
263 
264  }
265 
266  .configuration {
267  margin: 0 0 0 15px;
268  padding: 0 10px 10px 10px;
269  -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.5);
270  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5);
271  box-shadow: 0 1px 2px rgba(0,0,0,0.5);
272  border: 1px solid rgba(255,255,255,0.2);
273  -moz-border-radius: 3px;
274  -webkit-border-radius: 3px;
275  border-radius: 3px;
276  background: -moz-linear-gradient(top, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.07) 100%);
277  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0.01)), color-stop(100%,rgba(0,0,0,0.07)));
278  background: -webkit-linear-gradient(top, rgba(0,0,0,0.01) 0%,rgba(0,0,0,0.07) 100%);
279  background: -o-linear-gradient(top, rgba(0,0,0,0.01) 0%,rgba(0,0,0,0.07) 100%);
280  background: -ms-linear-gradient(top, rgba(0,0,0,0.01) 0%,rgba(0,0,0,0.07) 100%);
281  background: linear-gradient(to bottom, rgba(0,0,0,0.01) 0%,rgba(0,0,0,0.07) 100%);
282  min-width: 170px;
283  max-width: 500px;
284  }
285  .configuration .options {
286  list-style:none;
287  margin: 0;
288  padding: 0;
289 }
290 .configuration .options li {
291  display: block;
292  margin: 0;
293  padding: 0.2em 0;
294  zoom: 1;
295 }
296 
297 .configuration .options li:after {
298  content: "";
299  display: block;
300  clear: both;
301  height: 0;
302 }
303 .configuration .configHead {
304  display: block;
305  font-size: 1.5em;
306  font-weight: bold;
307  text-indent: 0;
308  margin-top: 10px;
309  margin-bottom: 15px;
310  border-bottom: 1px solid #999;
311 }
312 .configuration .configHead label{
313  display:block;
314 }
315 
316 #detailConfiguration fieldset legend {
317  font-weight: bold;
318  font-size: 1.4em;
319  margin-bottom: 5px;
320  margin-left: 0px;
321 }
322 #detailConfiguration label {
323  display:block;
324  font-size: 1.2em;
325  margin: 3px 0 3px 0;
326 }
327 
328 #detailConfiguration fieldset.language div {
329  margin-left: 10px;
330 }
331 
332  .configuration-language {
333  width: 120px;
334  }
335  .configuration-language .lang-select {
336  display: table-cell;
337  /*width: 50px;*/
338  vertical-align: middle;
339  border-right: 1px solid #AAA;
340  padding: 10px 10px 10px 0px;
341  }
342 
343  .configuration-language .lang-title {
344  display: table-cell;
345 /* width: 50px;*/
346  vertical-align: middle;
347  padding-left: 10px;
348 
349  }
350  #editMenu {
351  font-size: 12px;
352  }
353  #editMenu .menuTree {
354  display: table-cell;
355  min-width: 400px;
356  }
357  #btnAddNode {
358  margin-bottom: 10px;
359  }
360  #editMenu .menuDetails {
361  display: table-cell;
362  }
363  .configuration-language ul {
364  list-style: none;
365  }
366  .configuration-language li {
367 
368  }
369  #sectionLine {
370  border-top:1px solid #DFDFDF;
371  padding-top:5px;
372 
373  }
374 .sectionTitle {
375  font-family: Arial, Helvetica, sans-serif;
376  font-weight: normal;
377 }
378 
379 .sectionTitle {
380  left:0;
381  font-size:23px;
382  line-height:1.6;
383  color:#4e4e4e;
384 }
385 
386 .sectionTitle strong {
387  color:#e26b1d;
388  font-weight:normal;
389 }
390 section {
391  margin: 5px 0 5px 0;
392  padding: 20px 0 20px 20px;
393  background-color: #fcfcfc;
394  background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#efefef));
395 
396  background: -webkit-linear-gradient(top, #ffffff, #efefef);
397  background: -moz-linear-gradient(top, #ffffff, #efefef);
398  background: -o-linear-gradient(top, #ffffff, #efefef);
399  background: -ms-linear-gradient(top, #ffffff, #efefef);
400  background: linear-gradient(top, #ffffff, #efefef);
401  -webkit-box-shadow: 0px 1px 2px #8e8e8e;
402  -moz-box-shadow: 0px 1px 2px #8e8e8e;
403  -o-box-shadow: 0px 1px 2px #8e8e8e;
404  box-shadow: 0px 1px 2px #8e8e8e;
405 }
406 
407 
408 #themeWrap
409 {
410  float: right;
411  margin-top: -35px;
412  font-size: .9em;
413  line-height: 26px;
414 }
415 
416 #themeWrap .get-kendoui
417 {
418  padding: 0 10px;
419  line-height: 24px;
420  -moz-border-radius:3px;
421  -webkit-border-radius:3px;
422  border-radius:3px;
423 }
424 
425 .k-theme-chooser,
426 .tc-theme,
427 .tc-color,
428 .tc-link,
429 .tc-theme-name
430 {
431  text-decoration: none;
432  display: inline-block;
433  *display: inline;
434  *zoom: 1;
435 }
436 
437 .tc-theme-name
438 {
439  vertical-align: middle;
440  padding-right: 4px;
441  width: 80px;
442 }
443 
444 .k-theme-chooser .tc-link
445 {
446  vertical-align: middle;
447  line-height: 23px;
448  padding: 0 4px 0 8px;
449  -moz-border-radius: 3px;
450  -webkit-border-radius: 3px;
451  border-radius: 3px;
452 }
453 
454 .tc-choose-theme
455 {
456  vertical-align: middle;
457  color: #939393;
458  margin: 0 10px 0 0;
459 }
460 
461 .tc-theme-container
462 {
463  display: none;
464  list-style-type: none;
465  margin: 0 0 18px;
466  padding: 0 0 18px 10px;
467  border-bottom: 1px solid #dfdfdf;
468  font:75% Arial,Helvetica,sans-serif;
469 }
470 
471 .tc-color
472 {
473  width: 23px;
474  height: 23px;
475  border-width: 1px;
476  border-style: solid;
477  border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(255,255,255,.1);
478  display: inline-block;
479  *display: inline;
480  *zoom: 1;
481 }
482 
483 .tc-theme
484 {
485  margin: 0 5px;
486 }
487 
488 .tc-theme .tc-link
489 {
490  color: #4f4f4f;
491  padding: 10px;
492  border: 1px solid #fff;
493 }
494 
495 .tc-theme .tc-link:hover
496 {
497  border-color: #d6d6d6;
498  -moz-box-shadow: 0 0 7px rgba(0,0,0,.15);
499  -webkit-box-shadow: 0 0 7px rgba(0,0,0,.15);
500  box-shadow: 0 0 7px rgba(0,0,0,.15);
501 }
502 
503 .tc-theme .tc-link.active
504 {
505  border-color: #d6d6d6;
506  -moz-box-shadow: inset 0 0 7px rgba(0,0,0,.15);
507  -webkit-box-shadow: inset 0 0 7px rgba(0,0,0,.15);
508  box-shadow: inset 0 0 7px rgba(0,0,0,.15);
509 }
510 
511 .tc-theme .tc-theme-name
512 {
513  padding: 0;
514  width: auto;
515  display: block;
516 }
517 
518 #themeChooser .skin-black .k-state-selected{background-color:#0070e4;color:#fff;}
519 #themeChooser .skin-blueopal .k-state-selected{background-color:#005c83;color:#fff;}
520 #themeChooser .skin-bootstrap .k-state-selected{background-color:#0044cc;color:#fff;}
521 #themeChooser .skin-default .k-state-selected{background-color:#f0713a;color:#fff;}
522 #themeChooser .skin-highcontrast .k-state-selected{background-color:#a7008f;color:#fff;}
523 #themeChooser .skin-metro .k-state-selected{background-color:#8ebc00;color:#fff;}
524 #themeChooser .skin-metroblack .k-state-selected{background-color:#00aba9;color:#fff;}
525 #themeChooser .skin-silver .k-state-selected{background-color:#0879C0;color:#fff;}
526 #themeChooser .skin-uniform .k-state-selected{background-color:#ccc;color:#666;}
527 
528  #gridProxy {
529  font-size: 12px;
530  width: 500px;
531  }
532  .k-tooltip-content { text-align: left;
533  font-size: 12px;
534  max-width: 300px;
535  }
536  </style>
537 <?php
538  printMonitorPageMiddle($title, array("REDIRECT" => array("list" => array("Monitor" => array("url" => "https://$callbackHost/monitor/mindex.html", "target" => "_top"))),
539  "Check" => array("url" => "$self?action=check&callback=$callbackHost"), "Edit" => array("url" => "$self?action=edit&callback=$callbackHost"), "Re-Sort" => array("url" => "$self?action=sort&callback=$callbackHost"),
540  "Import" => array("url" => "$self?action=import&callback=$callbackHost")));
541  if ( $action == "edit" || $action == "" ) {
542  // get the different language keys
543  $languageKeysInfo = array();
544  $englishEntry = 0;
545  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
546  $languageKeysInfo[$i]["language"] = $languageKeys[$i];
547  $languageKeysInfo[$i]["mc"] = new hcu_talk_base( $languageKeys[$i] );
548  if ( $languageKeys[$i] == "en_US" ) {
549  $englishEntry = $i;
550  }
551  }
552 
553  // set up the key values (same for all tabs)
554  $baseKeys = array_keys( $languageKeysInfo[$englishEntry]["mc"]->messages );
555 
556  // get the translation for each key (note: this assumes the English list is comprehensive).
557  $languageLists = array();
558  for ( $k = 0; $k < count( $baseKeys ); $k++ ) {
559  $entry = array();
560  $entry["key"] = $baseKeys[$k];
561 
562  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
563  $entry[$languageKeys[$i]] = $languageKeysInfo[$i]["mc"]->msg($baseKeys[$k], HCU_DISPLAY_AS_JS);
564  }
565 
566  $languageLists[] = $entry;
567  }
568 
569 ?>
570 
571  <div id="editList"></div>
572  <div id="helpInfo"></div>
573 
574  <div id="progressShow" style="z-index:20000;"></div>
575  <script id="popup-editor" type="text/x-kendo-template">
576  <h3 style='text-align:center; width:100%;'>Edit Translation Entry</h3>
577  <span>
578  <label for="key" style='font-weight:bold;'>Key:</label>
579  <textarea name="key"
580  style="float:right; width:90%;"
581  data-bind="value:key"
582  data-value-field="key"
583  data-text-field="key"
584  id="key"
585  name="key"
586  cols="80"
587  rows="5"></textarea>
588  <div style="clear:both"></div>
589  </span>
590 <?php
591  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
592  $lang = $languageKeys[$i];
593 ?>
594  <span>
595  <label for="<?php echo $lang ?>" style='font-weight:bold;'><?php echo $lang ?>:</label>
596  <textarea name="<?php echo $lang ?>"
597  id="<?php echo $lang ?>"
598  style="float:right; width:90%;"
599  data-bind="value:<?php echo $lang ?>"
600  data-value-field="<?php echo $lang ?>"
601  data-text-field="<?php echo $lang ?>"
602  cols="80"
603  rows="5"></textarea>
604  <div style="clear:both"></div>
605  </span>
606 <?php
607  }
608 ?>
609  </script>
610  <script id="cmdTemplate" type="text/x-kendo-template">
611  <a class="k-button" href="\#" onclick="return showHelp()">Help</a>
612  </script>
613  <style>
614  .k-edit-form-container { width: auto; }
615  .edit_label { text-align: left; font-weight: bold; font-size: larger; }
616  .edit_entry { text-align: left; }
617  .odd-row { background-color:lightcyan; }
618  .header-row { background-color: lightsteelblue; font-weight: bold; }
619  .td-detail { text-align: center; width: 33%; }
620  </style>
621  <script type="text/javascript">
622  $(document).ready(function() {
623  $("#tabstrip").kendoTabStrip({
624  animation: { open: { effects: "fadeIn"} }
625  });
626 
627  var containsFilter =
628  {
629  extra : false,
630  operators : { string : { contains : "Contains"}},
631  ui : function( element )
632  {
633  var parent = element.parent();
634  while( parent.children().length > 1 )
635  $(parent.children()[0]).remove( );
636 
637  parent.prepend( "<input data-bind=\"value:filters[0].value\" class=\"k-textbox\" type=\"text\">" );
638  }
639  }
640 
641  var phraseList = <?php echo str_replace('\\\u', '\u', json_encode( $languageLists )); ?>;
642  $('#editList').kendoGrid({
643  dataSource: phraseList,
644  sortable: {
645  mode: "single",
646  allowUnsort: false
647  },
648  filterable: { contains: true },
649  editable: {
650  mode: "popup",
651  confirmation: "Are you sure you want to delete this record?",
652  template: kendo.template($("#popup-editor").html())
653  },
654  save: function(e) {
655  if (confirm("Are you sure you want to save this change?")) {
656  var that = this;
657  var postData = JSON.parse(JSON.stringify(e.model));
658  postData["action"] = "updateEntry";
659 
660  var parameters = "";
661  $.each(postData, function( index, object ) {
662  if ( parameters.length > 0 ) parameters += "&";
663  parameters += index + "=" + encodeURIComponent(object);
664  });
665 
666  kendo.ui.progress($('#progressShow'), true);
667 
668  $.post( '<?php echo $baseURL ?>', parameters,
669  function (data, status, xhr) {
670  // find the document and update the changes
671  $.each(phraseList, function( index, object ) {
672  if ( object["key"] == postData["key"] ) {
673 <?php
674  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
675  print "object[\"{$languageKeys[$i]}\"] = postData[\"{$languageKeys[$i]}\"];\n";
676  }
677 ?>
678  // since found it, stop looking
679  return false;
680  }
681  });
682 
683  // signify updated
684  that.refresh();
685  })
686  .fail( function (xhr, status, error) {
687  alert('Some error happened:' + error);
688  that.cancelRow();
689  })
690  .always( function( xhr, status ) {
691  kendo.ui.progress($('#progressShow'), false);
692  });
693  } else {
694  e.preventDefault();
695  }
696  },
697  remove: removeEntry,
698  toolbar: [{ name: "create" }, { template: kendo.template($("#cmdTemplate").html()) } ],
699  columns: [
700  { command: ["edit", "destroy"], title: "&nbsp;", width: "172px" },
701  { field: "key", title: "Key", filterable: containsFilter, width: "200px" }
702 <?php
703  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
704  print ",\n{ field: \"{$languageKeys[$i]}\", title: \"{$languageKeys[$i]}\", filterable: containsFilter, encoded: false }\n";
705  }
706  ?>
707  ]
708  });
709 
710  var wnd,
711  detailsTemplate;
712 
713  wnd = $("#helpInfo")
714  .kendoWindow({
715  title: "Character Translation",
716  modal: true,
717  visible: false,
718  resizable: false,
719  width: 300
720  }).data("kendoWindow");
721 
722  });
723 
724  function showHelp(e) {
725  var dialog = $("#helpInfo").data("kendoWindow");
726  var windowContents =
727  ['<table style="width:100%">',
728  '<tbody>',
729  '<tr>',
730  ' <th class="header-row" colspan="3">Spanish</th>',
731  '</tr>',
732 <?php
733  $transString = array("&Aacute;"=>"&amp;\#194;", "&Eacute;"=>"&amp;\#201;", "&Iacute;"=>"&amp;\#205;", "&Oacute;"=>"&amp;\#211;",
734  "&Uacute;"=>"&amp;\#218;", "&Ntilde;"=>"&amp;\#209;", "&aacute;"=>"&amp;\#225;", "&eacute;"=>"&amp;\#233;",
735  "&iacute;"=>"&amp;\#237;", "&oacute;"=>"&amp;\#243;", "&uacute;"=>"&amp;\#250;", "&ntilde;"=>"&amp;\#241;",
736  "&iexcl;"=>"&amp;\#161;", "&iquest;"=>"&amp;\#191;");
737  $transKeys = array_keys($transString);
738 
739  $rowBackground = "";
740  for ( $i = 0; $i < count( $transKeys ); $i++ ) {
741  $htmlEntity = htmlentities($transKeys[$i]);
742  $hashCode = $transString[$transKeys[$i]];
743 ?>
744  '<tr class="<?php echo $rowBackground; ?>">',
745  ' <td class="td-detail"><?php echo $transKeys[$i]; ?></td><td class="td-detail"><?php echo $hashCode; ?></td><td class="td-detail"><?php echo $htmlEntity; ?></td>',
746  '</tr>',
747 <?php
748  $rowBackground = ( $rowBackground == "odd-row" ) ? "" : "odd-row";
749  }
750 ?>
751  '<tr>',
752  ' <th class="header-row" colspan="3">Polish</th>',
753  '</tr>',
754 <?php
755  $transString = array( "&#260;"=>"&amp;\#260;", "&#261;"=>"&amp;\#261;", "&#280;"=>"&amp;\#280;", "&#281;"=>"&amp;\#281;",
756  "&#211;"=>"&amp;\#211;", "&#243;"=>"&amp;\#243;", "&#262;"=>"&amp;\#262;", "&#263;"=>"&amp;\#263;",
757  "&#321;"=>"&amp;\#321;", "&#322;"=>"&amp;\#322;", "&#323;"=>"&amp;\#323;", "&#324;"=>"&amp;\#324;",
758  "&#346;"=>"&amp;\#346;", "&#347;"=>"&amp;\#347;", "&#377;"=>"&amp;\#377;", "&#378;"=>"&amp;\#378;",
759  "&#379;"=>"&amp;\#379;", "&#380;"=>"&amp;\#380;" );
760  $transKeys = array_keys($transString);
761 
762  $rowBackground = "";
763  for ( $i = 0; $i < count( $transKeys ); $i++ ) {
764  $htmlEntity = "&nbsp;";
765  $hashCode = $transString[$transKeys[$i]];
766 ?>
767  '<tr class="<?php echo $rowBackground; ?>">',
768  ' <td class="td-detail"><?php echo $transKeys[$i]; ?></td><td class="td-detail"><?php echo $hashCode; ?></td><td class="td-detail"><?php echo $htmlEntity; ?></td>',
769  '</tr>',
770 <?php
771  $rowBackground = ( $rowBackground == "odd-row" ) ? "" : "odd-row";
772  }
773 ?>
774  '</tbody>',
775  '</table>'].join("\n");
776 
777  dialog.content(windowContents).open().center();
778  }
779 
780  function textareaEditor(container, options) {
781  $('<textarea data-bind="value: ' + options.field + '" cols="80" rows="5"></textarea>')
782  .appendTo(container);
783  }
784 
785  function removeEntry(e) {
786  var that = this;
787 
788  var modelData = JSON.parse(JSON.stringify(e.model));
789  var postData = {};
790  postData["action"] = "removeEntry";
791  postData["key"] = modelData["key"];
792 
793  var parameters = "";
794  $.each(postData, function( index, object ) {
795  if ( parameters.length > 0 ) parameters += "&";
796  parameters += index + "=" + encodeURIComponent(object);
797  });
798 
799  kendo.ui.progress($('#progressShow'), true);
800 
801  $.post( '<?php echo $baseURL ?>', parameters,
802  function (data, status, xhr) {
803  // signify updated
804  that.refresh();
805  })
806  .fail( function (xhr, status, error) {
807  alert('Some error happened:' + error);
808  that.cancelRow();
809  })
810  .always( function( xhr, status ) {
811  kendo.ui.progress($('#progressShow'), false);
812  });
813  }
814  </script>
815 <?php
816  } else if ( $action == "check" ) {
817  // get the different language keys
818  $languageKeysInfo = array();
819  $englishEntry = 0;
820  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
821  $languageKeysInfo[$i]["language"] = $languageKeys[$i];
822  $languageKeysInfo[$i]["mc"] = new hcu_talk_base( $languageKeys[$i] );
823  $languageKeysInfo[$i]["keys"] = array_keys( $languageKeysInfo[$i]["mc"]->messages );
824 
825  if ( $languageKeys[$i] == "en_US" ) {
826  $englishEntry = $i;
827  }
828  }
829 
830  // see which phrases are duplicated in the others, meaning they have not been translated yet
831  // NOTE: Assume the english one is correct
832  $controlList = $languageKeysInfo[$englishEntry]["keys"];
833  $untransList = array();
834  for ( $i = 0; $i < count( $controlList ); $i++ ) {
835  // get the control key (the one assumed to be right)
836  $controlKey = $controlList[$i];
837  $controlPhrase = stripslashes( $languageKeysInfo[$englishEntry]["mc"]->messages[$controlKey] );
838 
839  $languagePresent = array();
840  for ( $t = 0; $t < count( $languageKeysInfo ); $t++ ) {
841 
842  // skip the english one
843  if ( $englishEntry == $t ) continue;
844 
845  // compare the two keys
846  $compareList = $languageKeysInfo[$t]["mc"];
847  $comparePhrase = stripslashes( HCU_array_key_value($controlKey, $languageKeysInfo[$t]["mc"]->messages) );
848 
849  if ( $comparePhrase == $controlPhrase ) {
850  // also make sure the key isn't on the ignore list
851  if ( !in_array( $controlKey, $ignoreList[$languageKeysInfo[$t]["language"]] ) ) {
852  $languagePresent[$languageKeysInfo[$t]["language"]] = true;
853  }
854  }
855  }
856 
857  // only add if a duplicate was found
858  if ( count( $languagePresent ) ) {
859  $entry = array();
860  $entry["key"] = $controlKey;
861  $entry["phrase"] = $controlPhrase;
862  $entry["selected"] = ""; // for user editing
863 
864  // add which languages found a duplicate
865  for ( $t = 0; $t < count( $languageKeysInfo ); $t++ ) {
866  // skip English
867  if ( $t == $englishEntry ) continue;
868 
869  $lang = $languageKeysInfo[$t]["language"];
870  if ( HCU_array_key_value($lang, $languagePresent) ) {
871  $entry[$lang] = "X";
872  } else {
873  $entry[$lang] = "";
874  }
875  }
876 
877  $untransList[] = $entry;
878  }
879  }
880 
881  // see which entries are missing from the others
882  $missingList = array();
883  for ( $i = 0; $i < count( $languageKeysInfo ); $i++ ) {
884  for ( $m = 0; $m < count( $languageKeysInfo ); $m++ ) {
885  // skip the current one
886  if ( $m == $i ) continue;
887 
888  // compare the two lists
889  $controlList = $languageKeysInfo[$i]["keys"];
890  $compareList = $languageKeysInfo[$m]["keys"];
891 
892  for ( $c = 0; $c < count( $controlList ); $c++ ) {
893  $controlKey = $controlList[$c];
894 
895  if ( !in_array( $controlKey, $compareList ) ) {
896  // see if key is in the missing list already
897  $found = false;
898  for ( $t = 0; $t < count( $missingList ); $t++ ) {
899  if ( $missingList[$t]["key"] == $controlKey ) {
900  // add it for the language being compared
901  $missingList[$t][$languageKeysInfo[$m]["language"]] = "X";
902  $found = true;
903  break;
904  }
905  }
906  if ( !$found ) {
907  // add an entry
908  $entry = array();
909  $entry["key"] = $controlKey;
910  $entry["phrase"] = stripslashes( HCU_array_key_value($controlKey, $languageKeysInfo[$t]["mc"]->messages) );
911  $entry["selected"] = ""; // for user editing
912 
913  // add all languages and signify which was missing
914  for ( $t = 0; $t < count( $languageKeysInfo ); $t++ ) {
915  $lang = $languageKeysInfo[$t]["language"];
916  // we need to flag the compare list
917  if ( $lang == $languageKeysInfo[$m]["language"] ) {
918  $entry[$lang] = "X";
919  } else {
920  $entry[$lang] = "";
921  }
922  }
923 
924  $missingList[] = $entry;
925  }
926  }
927  }
928  }
929  }
930 
931  // see which entries do not have phrases in the non-English translations
932  // NOTE: Assume the english one is correct
933  $controlList = $languageKeysInfo[$englishEntry]["keys"];
934  $missingPhraseList = array();
935  for ( $i = 0; $i < count( $controlList ); $i++ ) {
936  // get the control key (the one assumed to be right)
937  $controlKey = $controlList[$i];
938  $controlPhrase = $languageKeysInfo[$englishEntry]["mc"]->messages[$controlKey];
939 
940  $missingPhrase = array();
941  for ( $t = 0; $t < count( $languageKeysInfo ); $t++ ) {
942 
943  // skip the english one
944  if ( $englishEntry == $t ) continue;
945 
946  // compare the two keys
947  $comparePhrase = stripslashes( HCU_array_key_value($controlKey, $languageKeysInfo[$t]["mc"]->messages) );
948 
949  if ( trim( $comparePhrase ) == "" ) {
950  $missingPhrase[$languageKeysInfo[$t]["language"]] = true;
951  }
952  }
953 
954  // only add if a duplicate was found
955  if ( count( $missingPhrase ) ) {
956  $entry = array();
957  $entry["key"] = $controlKey;
958  $entry["phrase"] = $controlPhrase;
959  $entry["selected"] = ""; // for user editing
960 
961  // add which languages found a duplicate
962  for ( $t = 0; $t < count( $languageKeysInfo ); $t++ ) {
963  // skip English
964  if ( $t == $englishEntry ) continue;
965 
966  $lang = $languageKeysInfo[$t]["language"];
967  if ( HCU_array_key_value($lang, $missingPhrase) ) {
968  $entry[$lang] = "X";
969  } else {
970  $entry[$lang] = "";
971  }
972  }
973 
974  $missingPhraseList[] = $entry;
975  }
976  }
977 
978  // search to see which entries are not in use anymore
979  // NOTE: Assume the english one is correct
980  // remove them from the $notUsedList as they are found
981  $notUsedList = $languageKeysInfo[$englishEntry]["keys"];
982 
983  // get the list of files to search
984  // NOTE: This may need to be manually maintained
985  // NOTE: Don't forget the calculator files in /combin
986  $searchFileList = array();
987  $searchFileList[] = "$sharedLibrary/cu_data.i";
988  foreach (glob("$bankingDir/scripts/*.prg") as $fileName) {
989  $searchFileList[] = $fileName;
990  }
991 
992  // search through the files
993  for ( $i = 0; $i < count( $searchFileList ); $i++ ) {
994  // open the file
995  $fileTest = file_get_contents( $searchFileList[$i], FILE_USE_INCLUDE_PATH );
996 
997  // see which keys are used in this file
998  for ( $t = 0; $t < count( $notUsedList ); $t++ ) {
999  if ( strpos( $fileTest, HCU_array_key_value($t, $notUsedList) ) > 0 ) {
1000  // found, remove from unused list
1001  unset( $notUsedList[$t] );
1002  break;
1003  }
1004  }
1005  }
1006 
1007  // look in the CMS table since dictionary entries are used there
1008  $sql= "SELECT docs.docsdisplaytext FROM cucmsdocs docs";
1009 
1010  $sth = db_query( $sql, $dbh );
1011  $trow = 0;
1012  while ( $row = db_fetch_array( $sth, $trow++ ) ) {
1013  $phrase = $row["docsdisplaytext"];
1014 
1015  // see if key used
1016  for ( $t = 0; $t < count( $notUsedList ); $t++ ) {
1017  if ( !strcmp( $phrase, HCU_array_key_value($t, $notUsedList) ) ) {
1018  // found, remove from unused list
1019  unset( $notUsedList[$t] );
1020  break;
1021  }
1022  }
1023  }
1024  db_free_result($sth);
1025 
1026  // create an array for the datasource to display
1027  $notUsedListFinal = array();
1028  for ( $i = 0; $i < count( $notUsedList ); $i++ ) {
1029  if ( isset( $notUsedList[$i] ) ) {
1030  $notUsedListFinal[] = array( "key" => $notUsedList[$i], "phrase" => stripslashes( $languageKeysInfo[$englishEntry]["mc"]->messages[$notUsedList[$i]] ), "selected" => "" );
1031  }
1032  }
1033 
1034  // see which entries are duplicated with different case
1035  // NOTE: just test English
1036  $duplicateCase = array();
1037  $controlList = $languageKeysInfo[$englishEntry]["keys"];
1038  for ( $i = 0; $i < count( $controlList ); $i++ ) {
1039  $count = 0;
1040  for ( $m = 0; $m < count( $controlList ); $m++ ) {
1041  // skip the current one
1042  if ( $m == $i ) continue;
1043 
1044  // compare the two keys
1045  if ( !strcasecmp( $controlList[$i], $controlList[$m] ) ) {
1046  $count++;
1047  }
1048  }
1049 
1050  if ( $count > 0 ) {
1051  $duplicateCase[] = array( "key" => $controlList[$i], "phrase" => stripslashes( $languageKeysInfo[$englishEntry]["mc"]->messages[$controlList[$i]] ), "selected" => "" );
1052  }
1053  }
1054 
1055  // generate the full list of key/phrase for people to see
1056  $fullList = array();
1057  $controlList = $languageKeysInfo[$englishEntry]["keys"];
1058  for ( $i = 0; $i < count( $controlList ); $i++ ) {
1059  $fullList[] = array( "key" => $controlList[$i], "phrase" => stripslashes( $languageKeysInfo[$englishEntry]["mc"]->messages[$controlList[$i]] ), "selected" => "" );
1060  }
1061 
1062  // List of keys that have a duplicate in another language because the phrases are the same in both languages.
1063  // NOTE: this is the Ignore List
1064  $languageList = array_keys( $ignoreList );
1065  $ignoreExplainList = array();
1066  for ( $i = 0; $i < count( $languageList ); $i++ ) {
1067  // get the ingore keys for this language
1068  $ignoreListForLanguage = $ignoreList[$languageList[$i]];
1069 
1070  // process the keys
1071  for ( $k = 0; $k < count( $ignoreListForLanguage); $k++ ) {
1072  // get the key
1073  $controlKey = $ignoreListForLanguage[$k];
1074 
1075  // see if the entry for the key is already present
1076  $entryPresent = false;
1077  for ( $t = 0; $t < count( $ignoreExplainList ); $t++ ) {
1078  if ( $ignoreExplainList[$t]["key"] == $ignoreListForLanguage[$k] ) {
1079  $entryPresent = true;
1080  break;
1081  }
1082  }
1083 
1084  if ( $entryPresent) {
1085  // flag it for the current language
1086  $ignoreExplainList[$t][$languageList[$i]] = "X";
1087  } else {
1088  // add the key, phrase, and languages
1089  $entry = array();
1090  $entry["key"] = $controlKey;
1091  $entry["phrase"] = stripslashes( $languageKeysInfo[$englishEntry]["mc"]->messages[$controlKey] );
1092  $entry["selected"] = ""; // for user editing
1093 
1094  // add entries for all languages but only flag the current one
1095  for ( $l = 0; $l < count( $languageList ); $l++ ) {
1096  // flag as true if current $languageList[$i]
1097  $entry[$languageList[$l]] = ($l == $i) ? "X" : "";
1098  }
1099 
1100  // add it to the list
1101  $ignoreExplainList[] = $entry;
1102  }
1103  }
1104  }
1105 
1106 ?>
1107 
1108  <div id="tabstrip">
1109  <ul>
1110  <li class="k-state-active"><span id="tip_untranslated">Untranslated Keys</span></li>
1111  <li><span id="tip_missing_keys">Missing Keys</span></li>
1112  <li><span id="tip_missing_phrases">Missing Phrases</span></li>
1113  <li><span id="tip_not_in_use">Keys Not In Use</span></li>
1114  <li><span id="tip_duplicate_case">Duplicate Case</span></li>
1115  <li><span id="tip_full_list">Full List</span></li>
1116  <li><span id="tip_ignore_list">(Ignore List)</span></li>
1117  </ul>
1118  <div>
1119  <div>
1120  <div id="untransList"></div>
1121  </div>
1122  </div>
1123  <div>
1124  <div>
1125  <div id="missingList"></div>
1126  </div>
1127  </div>
1128  <div>
1129  <div>
1130  <div id="missingPhraseList"></div>
1131  </div>
1132  </div>
1133  <div>
1134  <div>
1135  <div id="notUsedList"></div>
1136  </div>
1137  </div>
1138  <div>
1139  <div>
1140  <div id="duplicateCase"></div>
1141  </div>
1142  </div>
1143  <div>
1144  <div>
1145  <div id="fullList"></div>
1146  </div>
1147  </div>
1148  <div>
1149  <div>
1150  <div id="ignoreList"></div>
1151  </div>
1152  </div>
1153  </div>
1154 
1155  <div id='submitWait' style='display:none;'>
1156  <h2><img src="https://www4.homecu.net/dash/homecu/images/busy.gif" /> Submitting data...</h2>
1157  </div>
1158  <script type="text/javascript">
1159  $(document).ready(function() {
1160 
1161  $("#tabstrip").kendoTabStrip({
1162  animation: { open: { effects: "fadeIn"} }
1163  });
1164 
1165  homecuTooltip.bind({
1166  tip_untranslated: "At least one language phrase is a duplicate of the English phrase.",
1167  tip_missing_keys: "Keys are missing in at least one language file.",
1168  tip_missing_phrases: "A language file is missing a key/phrase compared to the English keys.",
1169  tip_not_in_use: "In searching script files, some keys are not found to be in use.",
1170  tip_duplicate_case: "Identical keys found but with different case sensitivity.",
1171  tip_full_list: "The full list of English Key/Phrase pairs.",
1172  tip_ignore_list: "The list of keys that are ignored in the Untranslated List because they are the same in both languagues."
1173  });
1174 
1175  var untransList = <?php echo json_encode( $untransList ); ?>;
1176  var missingList = <?php echo json_encode( $missingList ); ?>;
1177  var missingPhraseList = <?php echo json_encode( $missingPhraseList ); ?>;
1178  var notUsedList = <?php echo json_encode( $notUsedListFinal ); ?>;
1179  var duplicateCase = <?php echo json_encode( $duplicateCase ); ?>;
1180  var fullList = <?php echo json_encode( $fullList ); ?>;
1181  var ignoreList = <?php echo json_encode( $ignoreExplainList ); ?>;
1182 
1183  var containsFilter =
1184  {
1185  extra : false,
1186  operators : { string : { contains : "Contains"}},
1187  ui : function( element )
1188  {
1189  var parent = element.parent();
1190  while( parent.children().length > 1 )
1191  $(parent.children()[0]).remove( );
1192 
1193  parent.prepend( "<input data-bind=\"value:filters[0].value\" class=\"k-textbox\" type=\"text\">" );
1194  }
1195  }
1196 
1197  $('#untransList').kendoGrid({
1198  dataSource: untransList,
1199  sortable: {
1200  mode: "single",
1201  allowUnsort: false
1202  },
1203  filterable: { contains: true },
1204  columns: [
1205  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1206 <?php
1207  // put in a field for each language other than englislh
1208  for ( $i = 0; $i < count( $languageKeysInfo ); $i++ ) {
1209  // skip english
1210  if ( $i == $englishEntry ) continue;
1211  $fieldName = $languageKeysInfo[$i]["language"];
1212  $title = $fieldName;
1213 ?>
1214  { field: "<?php echo $fieldName ?>", title: "<?php echo $title ?>", width:"45px", filterable: false },
1215 <?php
1216  }
1217 ?>
1218  { field: "phrase", title: "Phrase", filterable: containsFilter },
1219  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1220  ],
1221  selectable: "row",
1222  change: function(e) {
1223  var selectedRow = this.dataItem(this.select());
1224  var key = selectedRow.key;
1225  var selected = selectedRow.selected == "Y" ? "" : "Y";
1226 
1227  // find the entry in the data and update the change
1228  $.each(untransList, function( index, object ) {
1229  if ( object["key"] == key ) {
1230  object["selected"] = selected;
1231  // since found it, stop looking
1232  return false;
1233  }
1234  });
1235 
1236  var grid = $("#untransList").data("kendoGrid");
1237  grid.dataSource.data(untransList);
1238  grid.refresh();
1239  },
1240  dataBound: function () {
1241  $("table tbody tr").hover(
1242  function() {
1243  $(this).toggleClass("k-state-hover");
1244  }
1245 
1246  );
1247  }
1248  });
1249 
1250  $('#missingList').kendoGrid({
1251  dataSource: missingList,
1252  sortable: {
1253  mode: "single",
1254  allowUnsort: false
1255  },
1256  filterable: { contains: true },
1257  columns: [
1258  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1259 <?php
1260  // put in a field for each language
1261  for ( $i = 0; $i < count( $languageKeysInfo ); $i++ ) {
1262  // skip english
1263  if ( $i == $englishEntry ) continue;
1264 
1265  $fieldName = $languageKeysInfo[$i]["language"];
1266  $title = $fieldName;
1267 ?>
1268  { field: "<?php echo $fieldName ?>", title: "<?php echo $title ?>", width:"45px", filterable: false },
1269 <?php
1270  }
1271 ?>
1272  { field: "phrase", title: "Phrase", filterable: containsFilter },
1273  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1274  ],
1275  selectable: "row",
1276  change: function(e) {
1277  var selectedRow = this.dataItem(this.select());
1278  var key = selectedRow.key;
1279  var selected = selectedRow.selected == "Y" ? "" : "Y";
1280 
1281  // find the entry in the data and update the change
1282  $.each(missingList, function( index, object ) {
1283  if ( object["key"] == key ) {
1284  object["selected"] = selected;
1285  // since found it, stop looking
1286  return false;
1287  }
1288  });
1289 
1290  var grid = $("#missingList").data("kendoGrid");
1291  grid.dataSource.data(missingList);
1292  grid.refresh();
1293  },
1294  dataBound: function () {
1295  $("table tbody tr").hover(
1296  function() {
1297  $(this).toggleClass("k-state-hover");
1298  }
1299 
1300  );
1301  }
1302  });
1303 
1304  $('#missingPhraseList').kendoGrid({
1305  dataSource: missingPhraseList,
1306  sortable: {
1307  mode: "single",
1308  allowUnsort: false
1309  },
1310  filterable: { contains: true },
1311  columns: [
1312  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1313 <?php
1314  // put in a field for each language
1315  for ( $i = 0; $i < count( $languageKeysInfo ); $i++ ) {
1316  // skip english
1317  if ( $i == $englishEntry ) continue;
1318 
1319  $fieldName = $languageKeysInfo[$i]["language"];
1320  $title = $fieldName;
1321 ?>
1322  { field: "<?php echo $fieldName ?>", title: "<?php echo $title ?>", width:"45px", filterable: false },
1323 <?php
1324  }
1325 ?>
1326  { field: "phrase", title: "Phrase", filterable: containsFilter },
1327  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1328  ],
1329  selectable: "row",
1330  change: function(e) {
1331  var selectedRow = this.dataItem(this.select());
1332  var key = selectedRow.key;
1333  var selected = selectedRow.selected == "Y" ? "" : "Y";
1334 
1335  // find the entry in the data and update the change
1336  $.each(missingPhraseList, function( index, object ) {
1337  if ( object["key"] == key ) {
1338  object["selected"] = selected;
1339  // since found it, stop looking
1340  return false;
1341  }
1342  });
1343 
1344  var grid = $("#missingPhraseList").data("kendoGrid");
1345  grid.dataSource.data(missingPhraseList);
1346  grid.refresh();
1347  },
1348  dataBound: function () {
1349  $("table tbody tr").hover(
1350  function() {
1351  $(this).toggleClass("k-state-hover");
1352  }
1353 
1354  );
1355  }
1356  });
1357 
1358  $('#notUsedList').kendoGrid({
1359  dataSource: notUsedList,
1360  sortable: {
1361  mode: "single",
1362  allowUnsort: false
1363  },
1364  filterable: { contains: true },
1365  columns: [
1366  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1367  { field: "phrase", title: "Phrase", filterable: containsFilter },
1368  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1369  ],
1370  selectable: "row",
1371  change: function(e) {
1372  var selectedRow = this.dataItem(this.select());
1373  var key = selectedRow.key;
1374  var selected = selectedRow.selected == "Y" ? "" : "Y";
1375 
1376  // find the entry in the data and update the change
1377  $.each(notUsedList, function( index, object ) {
1378  if ( object["key"] == key ) {
1379  object["selected"] = selected;
1380  // since found it, stop looking
1381  return false;
1382  }
1383  });
1384 
1385  var grid = $("#notUsedList").data("kendoGrid");
1386  grid.dataSource.data(notUsedList);
1387  grid.refresh();
1388  },
1389  dataBound: function () {
1390  $("table tbody tr").hover(
1391  function() {
1392  $(this).toggleClass("k-state-hover");
1393  }
1394 
1395  );
1396  }
1397  });
1398 
1399  $('#duplicateCase').kendoGrid({
1400  dataSource: duplicateCase,
1401  sortable: {
1402  mode: "single",
1403  allowUnsort: false
1404  },
1405  filterable: { contains: true },
1406  columns: [
1407  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1408  { field: "phrase", title: "Phrase", filterable: containsFilter },
1409  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1410  ],
1411  selectable: "row",
1412  change: function(e) {
1413  var selectedRow = this.dataItem(this.select());
1414  var key = selectedRow.key;
1415  var selected = selectedRow.selected == "Y" ? "" : "Y";
1416 
1417  // find the entry in the data and update the change
1418  $.each(duplicateCase, function( index, object ) {
1419  if ( object["key"] == key ) {
1420  object["selected"] = selected;
1421  // since found it, stop looking
1422  return false;
1423  }
1424  });
1425 
1426  var grid = $("#duplicateCase").data("kendoGrid");
1427  grid.dataSource.data(duplicateCase);
1428  grid.refresh();
1429  },
1430  dataBound: function () {
1431  $("table tbody tr").hover(
1432  function() {
1433  $(this).toggleClass("k-state-hover");
1434  }
1435 
1436  );
1437  }
1438  });
1439 
1440  $('#fullList').kendoGrid({
1441  dataSource: fullList,
1442  sortable: {
1443  mode: "single",
1444  allowUnsort: false
1445  },
1446  filterable: { contains: true },
1447  columns: [
1448  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1449  { field: "phrase", title: "Phrase", filterable: containsFilter },
1450  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1451  ],
1452  selectable: "row",
1453  change: function(e) {
1454  var selectedRow = this.dataItem(this.select());
1455  var key = selectedRow.key;
1456  var selected = selectedRow.selected == "Y" ? "" : "Y";
1457 
1458  // find the entry in the data and update the change
1459  $.each(fullList, function( index, object ) {
1460  if ( object["key"] == key ) {
1461  object["selected"] = selected;
1462  // since found it, stop looking
1463  return false;
1464  }
1465  });
1466 
1467  var grid = $("#fullList").data("kendoGrid");
1468  grid.dataSource.data(fullList);
1469  grid.refresh();
1470  },
1471  dataBound: function () {
1472  $("table tbody tr").hover(
1473  function() {
1474  $(this).toggleClass("k-state-hover");
1475  }
1476 
1477  );
1478  }
1479  });
1480 
1481  $('#ignoreList').kendoGrid({
1482  dataSource: ignoreList,
1483  sortable: {
1484  mode: "single",
1485  allowUnsort: false
1486  },
1487  filterable: { contains: true },
1488  columns: [
1489  { field: "key", title: "Key", filterable: containsFilter, width: "200px" },
1490 <?php
1491  // put in a field for each language
1492  for ( $i = 0; $i < count( $languageKeysInfo ); $i++ ) {
1493  // skip english
1494  if ( $i == $englishEntry ) continue;
1495 
1496  $fieldName = $languageKeysInfo[$i]["language"];
1497  $title = $fieldName;
1498 ?>
1499  { field: "<?php echo $fieldName ?>", title: "<?php echo $title ?>", width:"45px", filterable: false },
1500 <?php
1501  }
1502 ?>
1503  { field: "phrase", title: "Phrase", filterable: containsFilter },
1504  { field: "selected", title: "Sel", filterable: containsFilter, width: "45px" }
1505  ],
1506  selectable: "row",
1507  change: function(e) {
1508  var selectedRow = this.dataItem(this.select());
1509  var key = selectedRow.key;
1510  var selected = selectedRow.selected == "Y" ? "" : "Y";
1511 
1512  // find the entry in the data and update the change
1513  $.each(ignoreList, function( index, object ) {
1514  if ( object["key"] == key ) {
1515  object["selected"] = selected;
1516  // since found it, stop looking
1517  return false;
1518  }
1519  });
1520 
1521  var grid = $("#ignoreList").data("kendoGrid");
1522  grid.dataSource.data(ignoreList);
1523  grid.refresh();
1524  },
1525  dataBound: function () {
1526  $("table tbody tr").hover(
1527  function() {
1528  $(this).toggleClass("k-state-hover");
1529  }
1530 
1531  );
1532  }
1533  });
1534 
1535  });
1536  </script>
1537  <style scoped>
1538  #display-block {
1539  min-height:100px;
1540  padding: 5px 20px 5px 20px;
1541  width: 350px;
1542  }
1543  #content-block {
1544  width: 400px;
1545  }
1546  #panels
1547  {
1548  /*margin-left: 20px;*/
1549  text-align: center;
1550 
1551  }
1552 
1553  #panels li
1554  {
1555  margin-right: 10px;
1556  margin-bottom: 10px;
1557  list-style: none;
1558  float: left;
1559 
1560  }
1561  #panels .k-block {
1562  min-height: 70px;
1563  min-width: 200px;
1564  }
1565  #panels .k-block .k-header {
1566  margin-bottom:5px;
1567  }
1568  .homecu-formStatus {
1569  margin-bottom: 10px
1570  }
1571  </style>
1572 <?php
1573  } else if ( $action == "import" || $action == "" ) {
1574 
1575  if ( $screen == "upload" || $screen == "" ) {
1576  // show a screen to upload the file and choose a delimiter
1577 ?>
1578  <h3>Pick a file to upload and specify the delimiter.</h3>
1579  <h5>Note: the default delimiter is a comma (',')</h5>
1580  <form method="post" style="width:45%">
1581  <input type="hidden" name="action" value="import">
1582  <input type="hidden" name="screen" value="confirm">
1583  <input name="upload_file" id="uploadFile" type="file" />
1584  <h3> Select Delimiter</h3>
1585  <p>
1586  <select name="delimiter">
1587  <option value=','>,</option>
1588  <option value='tab'>tab</option>
1589  <option value=';'>;</option>
1590  <option value='|'>|</option>
1591  <option value='^'>^</option>
1592  </select>
1593  </p>
1594  <br />
1595  <br />
1596  <p>
1597  <input type="submit" value="Review" id="submitButton" class="k-button" style="visibility: hidden;"/>
1598  </p>
1599  <br />
1600  <br />
1601  <h3>Notes:</h3>
1602  <ol>
1603  <li>The file is in the format:<br>
1604  language&lt;delim&gt;key&lt;delim&gt;phrase</li>
1605  <li>If the key exists then the phrase will be used with that key.</li>
1606  <li>If a key/phrase already exists the imported phrase will overwrite the existing.</li>
1607  <li>If a new key phrase's supported language is missing the English will be used.</li>
1608  <li>If a new key phrase is missing English, any missing phrases will be left blank.</li>
1609  <li>Lines starting with a '#' will be treated as comments.</li>
1610  <li>Any special characters need to use HTML Encoded entities.</li>
1611  </ol>
1612  </form>
1613  <style>
1614  </style>
1615  <script>
1616  $(document).ready(function() {
1617  $("#uploadFile").kendoUpload({
1618  localization: {
1619  select: "Select File..."
1620  },
1621  multiple: false,
1622  select: onSelect
1623  });
1624 
1625  function onSelect(e) {
1626  $("#submitButton").css("visibility", "visible");
1627  };
1628  });
1629  </script>
1630 <?php
1631  } else if ( $screen == "confirm" ) {
1632  // show the uploaded info as delimited by the user's choice
1633 
1634  // make sure have a file
1635  $uploadFile = "";
1636 
1637  if ( is_uploaded_file( $_FILES["upload_file"]["tmp_name"] ) &&
1638  ( $_FILES["upload_file"]["size"] > 0 ) &&
1639  ( $_FILES["upload_file"]["error"] == 0) ) {
1640  $tmpName = $_FILES["upload_file"]["tmp_name"];
1641  $saveName = "/tmp/hcuTransUpload.txt";
1642  if ( move_uploaded_file($tmpName, $saveName) ) {
1643  // signify the upload occurred
1644  $uploadFile = $saveName;
1645  }
1646  }
1647 
1648  // check the delimiter
1649  $delimiterPassed = $HB_ENV["MY_POST"]["delimiter"];
1650  $delimiterChoices = array( ",", "|", ";", "^" );
1651  if ( !in_array( $delimiterPassed, $delimiterChoices ) && $delimiterPassed != "tab" ) {
1652  throw new ErrorException("Error - Invalid Delimiter");
1653  }
1654 
1655  if ( $delimiterPassed == "tab" ) {
1656  $delimiter = "\t";
1657  } else {
1658  $delimiter = $delimiterPassed;
1659  }
1660 
1661  if ( $uploadFile == "" ) {
1662  throw new ErrorException("Error Uploading Translation Import File");
1663  }
1664 
1665  // show the imported data
1666  $importLines = file( $uploadFile, FILE_IGNORE_NEW_LINES );
1667 
1668  $importInfo = array();
1669  $keyList = array();
1670  for ( $i = 0; $i < count( $importLines ); $i++ ) {
1671  $line = trim( $importLines[$i] );
1672  if ( substr( $line, 0, 1) == "#" ) continue;
1673 
1674  $lineParts = explode( $delimiter, $line );
1675 
1676  // save the unique keys
1677  if ( !in_array($lineParts[1], $keyList) ) {
1678  $keyList[] = $lineParts[1];
1679  }
1680 
1681  // put into array indexed by [key][lang]
1682  $importInfo[$lineParts[1]][$lineParts[0]] = $lineParts[2];
1683  }
1684 
1685  // now make each line have the key, lang1, lang2, ..., langN entries
1686  $importEntries = array();
1687  for ( $k = 0; $k < count( $keyList ); $k++ ) {
1688  $entry = array();
1689  $entry["key"] = $keyList[$k];
1690 
1691  $englishPhrase = "";
1692  $englishEntry = 0;
1693  for ( $l = 0; $l < count( $languageKeys ); $l++ ) {
1694  // save the english phrase in case a language is missing
1695  if ( $l == $englishEntry ) {
1696  $englishPhrase = $importInfo[$keyList[$k]][$languageKeys[$l]];
1697  }
1698 
1699  $phrase = $importInfo[$keyList[$k]][$languageKeys[$l]];
1700  if ( !strlen( trim( $phrase ) ) ) {
1701  $phrase = $englishPhrase;
1702  }
1703 
1704  $entry[$languageKeys[$l]] = ConvertFromUTF8( $phrase );
1705  }
1706 
1707  $importEntries[] = $entry;
1708  }
1709 ?>
1710  <script type="text/x-kendo-template" id="actionTemplate">
1711  <div class="toolbar">
1712  <form method='post'>
1713  <input type="hidden" name="action" value="import">
1714  <input type="hidden" name="screen" value="import">
1715  <input type="hidden" name="delimiter" value="<?php echo $delimiterPassed ?>">
1716  <button type='submit' id='upload' <?php echo (!count( $importLines ) ? "disabled='DISABLED'" : "") ?> class='k-button'>Upload</button>
1717  </form>
1718  <form method='post'>
1719  <input type="hidden" name="action" value="">
1720  <input type="hidden" name="screen" value="">
1721  <button type='submit' id='cancel' class='k-button'>Cancel</button>
1722  </form>
1723  </div>
1724  </script>
1725 
1726  <div id="confirmList"></div>
1727 
1728  <div id="progressShow" style="z-index:20000;"></div>
1729  <script type="text/javascript">
1730  $(document).ready(function() {
1731 
1732  var confirmList = <?php echo json_encode( $importEntries ); ?>;
1733  $('#confirmList').kendoGrid({
1734  dataSource: confirmList,
1735  toolbar: kendo.template($("#actionTemplate").html()),
1736  columns: [
1737  { field: "key", title: "Key" }
1738 <?php
1739  for ( $i = 0; $i < count( $languageKeys ); $i++ ) {
1740  print ",\n{ field: \"{$languageKeys[$i]}\", title: \"{$languageKeys[$i]}\", encoded: false }\n";
1741  }
1742 ?>
1743  ]
1744  });
1745 
1746  });
1747 
1748  $("#upload").click(function() {
1749  kendo.ui.progress($('#progressShow'), true);
1750  });
1751 
1752  $("#cancel").click(function() {
1753  kendo.ui.progress($('#progressShow'), true);
1754  });
1755  </script>
1756  <style>
1757  form {
1758  display:inline;
1759  margin:0;
1760  padding:0;
1761  }
1762  </style>
1763 <?php
1764  } else if ( $screen == "import" ) {
1765  // show the imported data with the existing data, allowing the user to edit and save
1766  } else {
1767  // something unexpected
1768  throw new ErrorException("Unsupported Import Screen");
1769  }
1770  } else {
1771  throw new ErrorException("Unsupported Action");
1772  }
1773 
1774  printMonitorPageBottom();
1775  } catch (Exception $e) {
1776  // ERROR CAUGHT
1777  /*
1778  *
1779  */
1780  $errorTitle= "Credit Union Home Banking Translation Table Maintenance";
1781  printMonitorPageTop($errorTitle, $homecuKendoVersion, $cloudfrontDomainName);
1782  printMonitorPageMiddle($errorTitle);
1783  print "<h3>{$e->getMessage()}</h3>";
1784  printMonitorPageBottom();
1785  }
1786 
1787  // FUNCTIONS
1788 
1789  // Write out the translation table to the correct file.
1790  function WriteTranslationTableFile( $language, $transTable ) {
1791  $fileWarning = "// This file is created and maintained programatically. DO NOT EDIT THIS FILE DIRECTLY.\n";
1792  $fileWarning .= "// The script file hcuadm/hcuTransAm is used to edit and maintain this file.\n\n";
1793 
1794  // re-generate the translation language-specific file
1795  $fileName = dirname(__FILE__) . "/../../shared/includes/hcuTranslate." . $language . ".i";
1796 
1797  // change the ownership
1798  $file = fopen($fileName, "w", true);
1799  if ( $file ) {
1800  fwrite( $file, "<?php\n" );
1801 
1802  fwrite( $file, $fileWarning );
1803 
1804  // * preserver the html_decode setting
1805  $jsArrayStr = "\$html_decode = {$transTable->html_decode};\n";
1806  fwrite($file, $jsArrayStr );
1807 
1808  $jsFind = $transTable->js_find;
1809  $arrayContents = "";
1810  for ( $j = 0; $j < count( $jsFind ); $j++ ) {
1811  if ( strlen( $arrayContents ) > 0 ) $arrayContents .= ",";
1812  $arrayContents .= "\"" . $jsFind[$j] . "\"";
1813  }
1814 
1815  $jsArrayStr = "\$js_find = array($arrayContents);\n";
1816  fwrite($file, $jsArrayStr );
1817 
1818  $jsReplace = $transTable->js_replace;
1819  $arrayContents = "";
1820  for ( $j = 0; $j < count( $jsFind ); $j++ ) {
1821  if ( strlen( $arrayContents ) > 0 ) $arrayContents .= ",";
1822  $arrayContents .= "\"" . $jsReplace[$j] . "\"";
1823  }
1824 
1825  $jsArrayStr = "\$js_replace = array($arrayContents);\n";
1826  fwrite($file, $jsArrayStr );
1827 
1828  // read in and form the list of lower case characters
1829  $lowerCharArray = $transTable->lowerChar;
1830  $arrayContents = "";
1831  for ( $j = 0; $j < count( $lowerCharArray ); $j++ ) {
1832  if ( strlen( $arrayContents ) > 0 ) $arrayContents .= ",";
1833  $arrayContents .= "\"" . $lowerCharArray[$j] . "\"";
1834  }
1835 
1836  $jsArrayStr = "\$lowerChar = array($arrayContents);\n";
1837  fwrite($file, $jsArrayStr );
1838 
1839  // read in and form the list of lower case characters
1840  $upperCharArray = $transTable->upperChar;
1841  $arrayContents = "";
1842  for ( $j = 0; $j < count( $lowerCharArray ); $j++ ) {
1843  if ( strlen( $arrayContents ) > 0 ) $arrayContents .= ",";
1844  $arrayContents .= "\"" . $upperCharArray[$j] . "\"";
1845  }
1846 
1847  $jsArrayStr = "\$upperChar = array($arrayContents);\n";
1848  fwrite($file, $jsArrayStr );
1849 
1850  // the $lang string
1851  $langStr = "\$lang = '{$language}';\n";
1852  fwrite($file, $langStr );
1853 
1854  // the $langName string
1855  $langNameStr = "\$langName = '{$transTable->langName}';\n";
1856  fwrite($file, $langNameStr );
1857 
1858  // the actual messages
1859  fwrite( $file, "\$messages = array(\n" );
1860 
1861  $transKeys = array_keys( $transTable->messages );
1862 // need to sort the keys in case a new one was added
1863  $transString = "";
1864  for ( $k = 0; $k < count( $transKeys ); $k++ ) {
1865  if ( $k > 0 ) $transString .= ",\n";
1866 
1867  $findKey = $transKeys[$k];
1868  $newPhrase = str_replace("'", "\'", ConvertFromUTF8( $transTable->messages[$findKey]));
1869  $transString .= " '{$findKey}' => '{$newPhrase}'";
1870  }
1871 
1872  $transString .= "\n);\n";
1873 
1874  fwrite( $file, $transString );
1875 
1876  fclose( $file );
1877  }
1878  }
1879 
1880  // Translate certain characters into the html entities.
1881  function TranslateLetters( $string ) {
1882  $before = $string;
1883  $transList = array(
1884  193 => "&Aacute", // "�"
1885  201 => "&Eacute", // "�"
1886  205 => "&Iacute", // "�"
1887  209 => "&Ntilde", // "�"
1888  211 => "&Oacute", // "�"
1889  218 => "&Uacute", // "�"
1890  225 => "&aacute", // "�"
1891  233 => "&eacute", // "�"
1892  237 => "&iacute", // "�"
1893  241 => "&ntilde", // "�"
1894  243 => "&oacute", // "�"
1895  250 => "&uacute", // "�"
1896  161 => "&iexcl", // "�"
1897  191 => "&iquest" // "�"
1898  );
1899 
1900  $strLen = strlen( $string );
1901  $newString = "";
1902 print "<br> New String to translate: $string<br>";
1903  $chrArray = preg_split('//u',$string, -1, PREG_SPLIT_NO_EMPTY);
1904 print_r( $chrArray );
1905  for ( $s = 0; $s < count( $chrArray ); $s++ ) {
1906  $oldChar = substr( $chrArray, $s, 1 );
1907  $ord = ord( $oldChar );
1908 print "<br>found: $oldChar ($ord)";
1909 
1910  $newChar = $transList[$ord];
1911 
1912  if ( strlen( $newChar ) ) {
1913  print "<br>$ord, $oldChar --) $newChar";
1914  $transChar = $newChar;
1915  } else {
1916  $transChar = $oldChar;
1917  }
1918 
1919  $newString .= $transChar;
1920  }
1921 
1922  if ( strcmp( $newString, $string ) ) {
1923  print "<br>Changed: $string --) $newString";
1924  }
1925 
1926  return $newString;
1927  }