Transposh WordPress Translation - Version 0.6.0

Version Description

Much improved translation interface engine

Download this release

Release Info

Developer oferwald
Plugin Icon 128x128 Transposh WordPress Translation
Version 0.6.0
Comparing to
See all releases

Code changes from version 0.5.7 to 0.6.0

core/constants.php CHANGED
@@ -102,6 +102,7 @@ $rtl_languages = array('ar', 'he', 'fa', 'ur', 'yi');
102
  //@updated 2010-Jul-01 (hy,az,eu,ka,ur)
103
  //$google_languages = array('en', 'af', 'sq', 'ar', 'hy', 'az', 'eu', 'be', 'bg', 'ca', 'zh', 'zh-tw', 'hr', 'cs', 'da', 'nl', 'et', 'fi', 'fr', 'gl', 'ka', 'de', 'el', 'ht', 'he', 'hi', 'hu', 'id', 'it', 'is', 'ga', 'ja', 'ko', 'lv', 'lt', 'mk', 'ms', 'mt', 'no', 'fa', 'pl', 'pt', 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sw', 'sv', 'tl', 'th', 'tr', 'uk', 'ur', 'vi', 'cy', 'yi');
104
  $google_languages = array('en', 'af', 'sq', 'ar', 'be', 'bg', 'ca', 'zh', 'zh-tw', 'hr', 'cs', 'da', 'nl', 'et', 'fi', 'fr', 'gl', 'de', 'el', 'ht', 'he', 'hi', 'hu', 'id', 'it', 'is', 'ga', 'ja', 'ko', 'lv', 'lt', 'mk', 'ms', 'mt', 'no', 'fa', 'pl', 'pt', 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sw', 'sv', 'tl', 'th', 'tr', 'uk', 'vi', 'cy', 'yi');
 
105
  //Bing supported languages
106
  //(got this using Microsoft.Translator.GetLanguages() - fixed to match our codes)
107
  //@updated 2010-Jun-30
@@ -111,7 +112,7 @@ $bing_languages = array('en', 'ar', 'bg', 'zh', 'zh-tw', 'cs', 'da', 'nl', 'et',
111
  define('TRANSLATOR', 'translator');
112
 
113
  //Define for transposh plugin version
114
- define('TRANSPOSH_PLUGIN_VER', '0.5.7');
115
 
116
  //Define segment id prefix, will be included in span tag. also used as class identifier
117
  define('SPAN_PREFIX', 'tr_');
102
  //@updated 2010-Jul-01 (hy,az,eu,ka,ur)
103
  //$google_languages = array('en', 'af', 'sq', 'ar', 'hy', 'az', 'eu', 'be', 'bg', 'ca', 'zh', 'zh-tw', 'hr', 'cs', 'da', 'nl', 'et', 'fi', 'fr', 'gl', 'ka', 'de', 'el', 'ht', 'he', 'hi', 'hu', 'id', 'it', 'is', 'ga', 'ja', 'ko', 'lv', 'lt', 'mk', 'ms', 'mt', 'no', 'fa', 'pl', 'pt', 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sw', 'sv', 'tl', 'th', 'tr', 'uk', 'ur', 'vi', 'cy', 'yi');
104
  $google_languages = array('en', 'af', 'sq', 'ar', 'be', 'bg', 'ca', 'zh', 'zh-tw', 'hr', 'cs', 'da', 'nl', 'et', 'fi', 'fr', 'gl', 'de', 'el', 'ht', 'he', 'hi', 'hu', 'id', 'it', 'is', 'ga', 'ja', 'ko', 'lv', 'lt', 'mk', 'ms', 'mt', 'no', 'fa', 'pl', 'pt', 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sw', 'sv', 'tl', 'th', 'tr', 'uk', 'vi', 'cy', 'yi');
105
+ $google_proxied_languages = array('hy','az','eu','ka','ur');
106
  //Bing supported languages
107
  //(got this using Microsoft.Translator.GetLanguages() - fixed to match our codes)
108
  //@updated 2010-Jun-30
112
  define('TRANSLATOR', 'translator');
113
 
114
  //Define for transposh plugin version
115
+ define('TRANSPOSH_PLUGIN_VER', '0.6.0');
116
 
117
  //Define segment id prefix, will be included in span tag. also used as class identifier
118
  define('SPAN_PREFIX', 'tr_');
core/parser.php CHANGED
@@ -51,7 +51,7 @@ class parserstats {
51
  * This function is when the object is initialized, which is a good time to start ticking.
52
  */
53
  function parserstats() {
54
- $this->start_time = microtime(true);
55
  }
56
 
57
  /**
@@ -59,7 +59,7 @@ class parserstats {
59
  * @return int How many phrases were auto-translated
60
  */
61
  function get_computer_translated_phrases() {
62
- return $this->translated_phrases - $this->human_translated_phrases;
63
  }
64
 
65
  /**
@@ -67,21 +67,21 @@ class parserstats {
67
  * @return int How many phrases are missing
68
  */
69
  function get_missing_phrases() {
70
- return $this->total_phrases - $this->translated_phrases;
71
  }
72
 
73
  /**
74
  * Start the timer
75
  */
76
  function start_timing() {
77
- $this->start_time = microtime(true);
78
  }
79
 
80
  /**
81
  * Stop timing, store time for reference
82
  */
83
  function stop_timing() {
84
- $this->time = number_format(microtime(true) - $this->start_time, 3);
85
  }
86
 
87
  }
@@ -112,6 +112,7 @@ class parser {
112
  public $is_edit_mode;
113
  public $is_auto_translate;
114
  public $feed_fix;
 
115
  //first three are html, later 3 come from feeds xml (link is problematic...)
116
  protected $ignore_tags = array('script' => 1, 'style' => 1, 'code' => 1, 'wfw:commentrss' => 1, 'comments' => 1, 'guid' => 1);
117
  /** @var parserstats Contains parsing statistics */
@@ -123,8 +124,8 @@ class parser {
123
  * @return boolean true if current position marks a white space
124
  */
125
  function is_white_space($char) {
126
- if (!$char) return TRUE;
127
- return strspn($char, " \t\r\n\0\x0B");
128
  }
129
 
130
  /**
@@ -133,7 +134,7 @@ class parser {
133
  * @return boolean true if a-z
134
  */
135
  function is_a_to_z_character($char) {
136
- return (($char >= 'a' && $char <= 'z') || ($char >= 'A' && $char <= 'Z')) ? true : false;
137
  }
138
 
139
  /**
@@ -141,7 +142,7 @@ class parser {
141
  * @return boolean true if a digit
142
  */
143
  function is_digit($char) {
144
- return (($char >= '0' && $char <= '9')) ? true : false;
145
  }
146
 
147
  /**
@@ -151,13 +152,13 @@ class parser {
151
  * @return int length of entity
152
  */
153
  function is_html_entity($string, $position) {
154
- if ($string[$position] == "&") {
155
- $end_pos = $position + 1;
156
- while ($string[$end_pos] == "#" || $this->is_digit($string[$end_pos]) || $this->is_a_to_z_character($string[$end_pos]))
157
- ++$end_pos;
158
- if ($string[$end_pos] == ';') return $end_pos - $position + 1;
159
- }
160
- return 0;
161
  }
162
 
163
  /**
@@ -169,7 +170,7 @@ class parser {
169
  * @return boolean true if not a breaker (apostrophy)
170
  */
171
  function is_entity_breaker($entity) {
172
- return!(stripos('&#8217;&apos;&quot;&#039;&#39;', $entity) !== FALSE);
173
  }
174
 
175
  /**
@@ -240,15 +241,15 @@ class parser {
240
  &yuml; &#255; ÿ ÿ latin small letter y with diaeresis
241
  */
242
  function is_entity_letter($entity) {
243
-
244
- $entnum = (int) substr($entity, 2);
245
- if (($entnum >= 192 && $entnum <= 214) || ($entnum >= 216 && $entnum <= 246) || ($entnum >= 248 && $entnum <= 255)) {
246
- return true;
247
- }
248
- $entities = '&Agrave;&Aacute;&Acirc;&Atilde;&Auml;&Aring;&AElig;&Ccedil;&Egrave;&Eacute;&Ecirc;&Euml;&Igrave;&Iacute;&Icirc;&Iuml;&ETH;' .
249
- '&Ntilde;&Ograve;&Oacute;&Ocirc;&Otilde;&Ouml;&Oslash;&Ugrave;&Uacute;&Ucirc;&Uuml;&Yacute;&THORN;&szlig;' .
250
- '&oslash;&ugrave;&yuml;';
251
- return (stripos($entities, $entity) !== FALSE);
252
  }
253
 
254
  /**
@@ -259,14 +260,14 @@ class parser {
259
  * @return int length of breaker if current position marks a break in sentence
260
  */
261
  function is_sentence_breaker($char, $nextchar, $nextnextchar) {
262
- if (($char == '.' || $char == '-') && ($this->is_white_space($nextchar)))
263
- return 1;
264
- //∙
265
- if (ord($char) == 226 && ord($nextchar) == 136 && ord($nextnextchar) == 153)
266
- return 3;
267
- //·
268
- if (ord($char) == 194 && ord($nextchar) == 183) return 2;
269
- return (strpos(',?()[]"!:|;', $char) !== false) ? 1 : 0; // TODO: might need to add < and > here
270
  }
271
 
272
  /**
@@ -274,7 +275,7 @@ class parser {
274
  * @return int length of number.
275
  */
276
  function is_number($page, $position) {
277
- return strspn($page, '0123456789-+$%,.\\/', $position);
278
  }
279
 
280
  /**
@@ -283,18 +284,18 @@ class parser {
283
  * @param int $end - end of pharse in element
284
  */
285
  function tag_phrase($string, $start, $end) {
286
- $phrase = trim(substr($string, $start, $end - $start));
287
- if ($phrase) {
288
-
289
- $node = new simple_html_dom_node($this->html);
290
- $node->tag = 'phrase';
291
- $node->parent = $this->currentnode;
292
- $this->currentnode->nodes[] = $node;
293
- $node->_[HDOM_INFO_OUTER] = '';
294
- $node->phrase = $phrase;
295
- if ($this->inbody) $node->inbody = $this->inbody;
296
- if ($this->inselect) $node->inselect = true;
297
- }
298
  }
299
 
300
  /**
@@ -302,72 +303,72 @@ class parser {
302
  * @param string $string - the string which is "broken" into smaller strings
303
  */
304
  function parsetext($string) {
305
- $pos = 0;
306
- // $pos = skip_white_space($string, $pos);
307
- // skip CDATA in feed_fix mode
308
- if ($this->feed_fix) {
309
- if (strpos($string, '<![CDATA[') === 0) {
310
- $pos = 9; // CDATA length
311
- $string = substr($string, 0, -3); // chop the last ]]>;
312
- }
313
- }
314
-
315
- $start = $pos;
316
-
317
- while ($pos < strlen($string)) {
318
- // Some HTML entities make us break, almost all but apostrophies
319
- if ($len_of_entity = $this->is_html_entity($string, $pos)) {
320
- $entity = substr($string, $pos, $len_of_entity);
321
- if (($this->is_white_space($string[$pos + $len_of_entity]) || $this->is_entity_breaker($entity)) && !$this->is_entity_letter($entity)) {
322
-
323
- $this->tag_phrase($string, $start, $pos);
324
- $start = $pos + $len_of_entity;
325
- }
326
- //skip past entity
327
- $pos += $len_of_entity;
328
- }
329
- // we have a special case for <> tags which might have came to us (maybe in xml feeds) (we'll skip them...)
330
- elseif ($string[$pos] == '<') {
331
- $this->tag_phrase($string, $start, $pos);
332
- while ($string[$pos] != '>' && $pos < strlen($string))
333
- $pos++;
334
- $pos++;
335
- $start = $pos;
336
- }
337
- // will break translation unit when there's a breaker ",.[]()..."
338
- elseif ($senb_len = $this->is_sentence_breaker($string[$pos], $string[$pos + 1], $string[$pos + 2])) {
339
- $this->tag_phrase($string, $start, $pos);
340
- $pos += $senb_len;
341
- $start = $pos;
342
- }
343
- // Numbers also break, if they are followed by whitespace (or a sentence breaker) (don't break 42nd) // TODO: probably by breaking entities too...
344
- // also prefixed by whitespace?
345
- elseif ($num_len = $this->is_number($string, $pos)) {
346
- // this is the case of B2 or B2,
347
- if (($this->is_white_space($string[$pos - 1]) || ($start == $pos)
348
- || ($this->is_sentence_breaker($string[$pos + $num_len - 1], $string[$pos + $num_len], $string[$pos + $num_len + 1]))) &&
349
- ($this->is_white_space($string[$pos + $num_len]) || $this->is_sentence_breaker($string[$pos + $num_len], $string[$pos + $num_len + 1], $string[$pos + $num_len + 2]))) {
350
- // we will now compensate on the number followed by breaker case, if we need to
351
- if (!($this->is_white_space($string[$pos - 1]) || ($start == $pos))) {
352
- if ($this->is_sentence_breaker($string[$pos + $num_len - 1], $string[$pos + $num_len], $string[$pos + $num_len + 1])) {
353
- $num_len--; //this makes the added number shorter by one, and the pos will be at a sentence breaker next so we don't have to compensate
354
- }
355
- $pos += $num_len;
356
- $num_len = 0; // we have already added this
357
- }
358
- $this->tag_phrase($string, $start, $pos);
359
- $start = $pos + $num_len + 1;
360
- }
361
- $pos += $num_len + 1;
362
- } else {
363
- $pos++;
364
- }
365
- }
366
-
367
- // the end is also some breaker
368
- if ($pos > $start) {
369
- $this->tag_phrase($string, $start, $pos);
370
- }
371
  }
372
 
373
  /**
@@ -376,86 +377,88 @@ class parser {
376
  * @param simple_html_dom_node $node
377
  */
378
  function translate_tagging($node, $level = 0) {
379
- $this->currentnode = $node;
380
- // we don't want to translate non-translatable classes
381
- if (stripos($node->class, NO_TRANSLATE_CLASS) !== false ||
382
- stripos($node->class, NO_TRANSLATE_CLASS_GOOGLE) !== false ||
383
- strtolower($node->lang) === $this->lang) return;
384
-
385
- if ($this->inselect && $level <= $this->inselect) $this->inselect = false;
386
-
387
- if ($this->inlangnondef && $level <= $this->inlangnondef)
388
- $this->inlangnondef = false;
389
-
390
- if ($this->default_lang && $node->lang != '' && stripos($node->lang, $this->lang) === false)
391
- $this->inlangnondef = $level;
392
-
393
- // we can only do translation for elements which are in the body, not in other places, and this must
394
- // move here due to the possibility of early recurse in default language
395
- if ($node->tag == 'body') {
396
- $this->inbody = true;
397
- }
398
- // this again should be here, the different behaviour on select and textarea
399
- elseif ($node->tag == 'select' || $node->tag == 'textarea') {
400
- $this->inselect = $level;
401
- }
402
-
403
- //support only_thislanguage class, (nulling the node if it should not display)
404
- if (strtolower($node->lang) != $this->lang && stripos($node->class, ONLY_THISLANGUAGE_CLASS) !== false) {
405
- $node->outertext = '';
406
- return;
407
- }
408
-
409
- // if we are in the default lang, and we have no foreign langs classes, we'll recurse from here
410
- if ($this->default_lang && !$this->inlangnondef) {
411
- foreach ($node->nodes as $c) {
412
- $this->translate_tagging($c, $level + 1);
413
- }
414
- return;
415
- }
416
-
417
- if (isset($this->ignore_tags[$node->tag])) return;
418
-
419
- if ($node->tag == 'text') {
420
- // this prevents translation of a link that just surrounds its address
421
- if ($node->parent->tag == 'a' && $node->parent->href == $node->outertext) {
422
- return;
423
- }
424
- // link tags inners are to be ignored
425
- if ($node->parent->tag == 'link') {
426
- return;
427
- }
428
- if (trim($node->outertext)) {
429
- $this->parsetext($node->outertext);
430
- }
431
- }
432
- // for anchors we will rewrite urls if we can
433
- elseif ($node->tag == 'a') {
434
- if ($this->url_rewrite_func != null) {
435
- $node->href = call_user_func_array($this->url_rewrite_func, array($node->href));
436
- }
437
- }
438
- // same for options, although normally not required (ticket #34)
439
- elseif ($node->tag == 'option') {
440
- if ($this->url_rewrite_func != null) {
441
- $node->value = call_user_func_array($this->url_rewrite_func, array($node->value));
442
- }
443
- }
444
- // in submit type inputs, we want to translate the value
445
- elseif ($node->tag == 'input' && $node->type == 'submit') {
446
- $this->parsetext($node->value);
447
- }
448
-
449
- // titles are also good places to translate, exist in a, img, abbr, acronym
450
- if ($node->title) $this->parsetext($node->title);
451
-
452
- // Meta content (keywords, description) are also good places to translate
453
- if ($node->tag == 'meta' && $node->content) $this->parsetext($node->content);
454
-
455
- // recurse
456
- foreach ($node->nodes as $c) {
457
- $this->translate_tagging($c, $level + 1);
458
- }
 
 
459
  }
460
 
461
  /**
@@ -467,23 +470,39 @@ class parser {
467
  * @return string
468
  */
469
  function create_edit_span($original_text, $translated_text, $source, $for_hidden_element = false) {
470
- // Use base64 encoding to make that when the page is translated (i.e. update_translation) we
471
- // get back exactlly the same string without having the client decode/encode it in anyway.
472
- $span = '<span class ="' . SPAN_PREFIX . '" id="' . SPAN_PREFIX . $this->segment_id . '" data-token="' . base64_url_encode($original_text) . "\" data-source=\"$source\"";
473
- // those are needed for on the fly image creation / hidden elements translations
474
- if ($this->is_edit_mode || $for_hidden_element) {
475
- $span .= " data-orig=\"$original_text\"";
476
- if ($for_hidden_element) {
477
- $span.= ' data-hidden="y"';
478
- // hidden elements currently have issues figuring what they translated in the JS
479
- if ($translated_text != null) {
480
- $span.= " data-trans=\"$translated_text\"";
481
- }
482
- }
483
- }
484
- $span .= '>';
485
- ++$this->segment_id;
486
- return $span;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  }
488
 
489
  /**
@@ -492,220 +511,227 @@ class parser {
492
  * @return string Translated content is here
493
  */
494
  function fix_html($string) {
495
- // ready our stats
496
- $this->stats = new parserstats();
497
- // create our dom
498
- $this->html = str_get_html($string);
499
- // mark translateable elements
500
- $this->translate_tagging($this->html->root);
501
-
502
- // first fix the html tag itself - we might need to to the same for all such attributes with flipping
503
- if ($this->dir_rtl) $this->html->find('html', 0)->dir = "rtl";
504
- else $this->html->find('html', 0)->dir = "ltr";
505
-
506
- if ($this->lang) {
507
- $this->html->find('html', 0)->lang = $this->lang;
508
- // add support for <meta name="language" content="<lang>">
509
- if ($this->html->find('meta[name=language]')) {
510
- $this->html->find('meta[name=language]')->content = $this->lang;
511
- }
512
- }
513
-
514
- // not much point in further processing if we don't have a function that does it
515
- if ($this->fetch_translate_func == null) {
516
- return $this->html;
517
- }
518
-
519
- // fix feed
520
- if ($this->feed_fix) {
521
- // fix urls on feed
522
-
523
- foreach (array('link', 'wfw:commentrss', 'comments') as $tag) {
524
- foreach ($this->html->find($tag) as $e) {
525
- $e->innertext = call_user_func_array($this->url_rewrite_func, array($e->innertext));
526
- // no need to translate anything here
527
- unset($e->nodes);
528
- }
529
- }
530
- // guid is not really a url -- in some future, we can check if permalink is true and probably falsify it
531
- foreach ($this->html->find('guid') as $e) {
532
- $e->innertext = $e->innertext . '-' . $this->lang;
533
- unset($e->nodes);
534
- }
535
- // fix feed language
536
- $this->html->find('language', 0)->innertext = $this->lang;
537
- unset($this->html->find('language', 0)->nodes);
538
- } else {
539
- // since this is not a feed, we might have references to such in the <link rel="alternate">
540
- foreach ($this->html->find('link') as $e) {
541
- if (strcasecmp($e->rel, 'alternate') == 0 || strcasecmp($e->rel, 'canonical') == 0) {
542
- $e->href = call_user_func_array($this->url_rewrite_func, array($e->href));
543
- }
544
- }
545
- }
546
-
547
- // try some prefetching... (//todo - maybe move directly to the phrase create)
548
- if ($this->prefetch_translate_func != null) {
549
- foreach ($this->html->find('text') as $e) {
550
- foreach ($e->nodes as $ep) {
551
- $originals[] = $ep->phrase;
552
- }
553
- }
554
- foreach (array('title', 'value') as $title) {
555
- foreach ($this->html->find('[' . $title . ']') as $e) {
556
- foreach ($e->nodes as $ep) {
557
- $originals[] = $ep->phrase;
558
- }
559
- }
560
- }
561
- foreach ($this->html->find('[content]') as $e) {
562
- foreach ($e->nodes as $ep) {
563
- $originals[] = $ep->phrase;
564
- }
565
- }
566
- call_user_func_array($this->prefetch_translate_func, array($originals, $this->lang));
567
- }
568
-
569
- // actually translate tags
570
- // texts are first
571
- foreach ($this->html->find('text') as $e) {
572
- $right = '';
573
- $newtext = '';
574
- foreach ($e->nodes as $ep) {
575
- list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
576
- //stats
577
- $this->stats->total_phrases++;
578
- if ($translated_text) {
579
- $this->stats->translated_phrases++;
580
- if ($source == 0) $this->stats->human_translated_phrases++;
581
- }
582
- if (($this->is_edit_mode || ($this->is_auto_translate && $translated_text == null))/* && $ep->inbody */) {
583
- $spanend = "</span>";
584
- if ($ep->inselect || !$ep->inbody) {
585
- $savedspan .= $this->create_edit_span($ep->phrase, $translated_text, $source, true) . $spanend;
586
- $span = '';
587
- $spanend = '';
588
- } else {
589
- $span = $this->create_edit_span($ep->phrase, $translated_text, $source);
590
- if ($translated_text == null) $translated_text = $ep->phrase;
591
- }
592
- }
593
- else {
594
- $span = '';
595
- $spanend = '';
596
- }
597
- if ($translated_text) {
598
- list ($left, $right) = explode($ep->phrase, $e->outertext, 2);
599
- $newtext .= $left . $span . $translated_text . $spanend;
600
- $e->outertext = $right;
601
- }
602
- }
603
- if ($newtext) {
604
- $e->outertext = $newtext . $right;
605
-
606
- }
607
- // hmm?
608
- if (!$ep->inselect && $savedspan && $ep->inbody) {
609
- $e->outertext = $savedspan . $e->outertext;
610
- $savedspan = "";
611
- }
612
- }
613
-
614
- // now we handle the title attributes (and the value of submit buttons)
615
- foreach (array('title', 'value') as $title) {
616
- $hidden_phrases = array();
617
- foreach ($this->html->find('[' . $title . ']') as $e) {
618
- $span = '';
619
- $spanend = '';
620
- $right = '';
621
- $newtext = '';
622
- // when we already have a parent outertext we'll have to update it directly
623
- if ($e->parent->_[HDOM_INFO_OUTER]) {
624
- $saved_outertext = $e->outertext;
625
- }
626
-
627
- foreach ($e->nodes as $ep) {
628
- if ($ep->tag == 'phrase') {
629
- list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
630
- // more stats
631
- $this->stats->total_phrases++;
632
- if ($ep->inbody) $this->stats->hidden_phrases++; else
633
- $this->stats->meta_phrases++;
634
- if ($translated_text) {
635
- $this->stats->translated_phrases++;
636
- if ($ep->inbody) $this->stats->hidden_translated_phrases++; else
637
- $this->stats->meta_translated_phrases++;
638
- if ($source == 0) $this->stats->human_translated_phrases++;
639
- }
640
- if (($this->is_edit_mode || ($this->is_auto_translate && $translated_text == null)) && $ep->inbody) {
641
- // prevent duplicate translation (title = text)
642
- if (strpos($e->innertext, base64_url_encode($ep->phrase)) === false) {
643
- //no need to translate span the same hidden phrase more than once
644
- if (!in_array($ep->phrase, $hidden_phrases)) {
645
- $this->stats->hidden_translateable_phrases++;
646
- $span .= $this->create_edit_span($ep->phrase, $translated_text, $source, true) . "</span>";
647
- //
648
- $hidden_phrases[] = $ep->phrase;
649
- }
650
- }
651
- }
652
- if ($translated_text) {
653
- list ($left, $right) = explode($ep->phrase, $e->$title, 2);
654
- $newtext .= $left . $translated_text;
655
- $e->$title = $right;
656
- }
657
- }
658
- }
659
- if ($newtext) {
660
- $e->$title = $newtext . $right;
661
-
662
- }
663
-
664
- $e->outertext .= $span;
665
- // this is where we update in the outercase issue
666
- if ($e->parent->_[HDOM_INFO_OUTER]) {
667
- $e->parent->outertext = implode($e->outertext, explode($saved_outertext, $e->parent->outertext, 2));
668
- }
669
- }
670
- }
671
-
672
- // now we handle the meta content - which is simpler because they can't be edited or auto-translated
673
- // we also don't expect any father modifications here
674
- foreach ($this->html->find('[content]') as $e) {
675
- $right = '';
676
- $newtext = '';
677
-
678
- foreach ($e->nodes as $ep) {
679
- if ($ep->tag == 'phrase') {
680
- // even more stats
681
- $this->stats->total_phrases++;
682
- $this->stats->meta_phrases++;
683
- list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
684
- if ($translated_text) {
685
- $this->stats->translated_phrases++;
686
- $this->stats->meta_translated_phrases++;
687
- if ($source == 0) $this->stats->human_translated_phrases++;
688
- list ($left, $right) = explode($ep->phrase, $e->content, 2);
689
- $newtext .= $left . $translated_text;
690
- $e->content = $right;
691
- }
692
- }
693
- }
694
- if ($newtext) {
695
- $e->content = $newtext . $right;
696
-
697
- }
698
- }
699
-
700
- // This adds a meta tag with our statistics json-encoded inside...
701
- $this->stats->stop_timing();
702
- $head = $this->html->find('head', 0);
703
- if ($head != null)
704
- $head->lastChild()->outertext .= "\n<meta name=\"translation-stats\" content='" . json_encode($this->stats) . "'/>";
705
-
706
- // Changed because of places where tostring failed
707
- //return $this->html;
708
- return $this->html->outertext;
 
 
 
 
 
 
 
709
  }
710
 
711
  /**
@@ -715,17 +741,17 @@ class parser {
715
  * @since 0.3.5
716
  */
717
  function get_phrases_list($string) {
718
- $result = array();
719
- // create our dom
720
- $this->html = str_get_html($string);
721
- // mark translateable elements
722
- $this->translate_tagging($this->html->root);
723
- foreach ($this->html->nodes as $ep) {
724
- if ($ep->tag == 'phrase') {
725
- $result[$ep->phrase] = $ep->phrase;
726
- }
727
- }
728
- return $result;
729
  }
730
 
731
  }
51
  * This function is when the object is initialized, which is a good time to start ticking.
52
  */
53
  function parserstats() {
54
+ $this->start_time = microtime(true);
55
  }
56
 
57
  /**
59
  * @return int How many phrases were auto-translated
60
  */
61
  function get_computer_translated_phrases() {
62
+ return $this->translated_phrases - $this->human_translated_phrases;
63
  }
64
 
65
  /**
67
  * @return int How many phrases are missing
68
  */
69
  function get_missing_phrases() {
70
+ return $this->total_phrases - $this->translated_phrases;
71
  }
72
 
73
  /**
74
  * Start the timer
75
  */
76
  function start_timing() {
77
+ $this->start_time = microtime(true);
78
  }
79
 
80
  /**
81
  * Stop timing, store time for reference
82
  */
83
  function stop_timing() {
84
+ $this->time = number_format(microtime(true) - $this->start_time, 3);
85
  }
86
 
87
  }
112
  public $is_edit_mode;
113
  public $is_auto_translate;
114
  public $feed_fix;
115
+ public $allow_ad = false;
116
  //first three are html, later 3 come from feeds xml (link is problematic...)
117
  protected $ignore_tags = array('script' => 1, 'style' => 1, 'code' => 1, 'wfw:commentrss' => 1, 'comments' => 1, 'guid' => 1);
118
  /** @var parserstats Contains parsing statistics */
124
  * @return boolean true if current position marks a white space
125
  */
126
  function is_white_space($char) {
127
+ if (!$char) return TRUE;
128
+ return strspn($char, " \t\r\n\0\x0B");
129
  }
130
 
131
  /**
134
  * @return boolean true if a-z
135
  */
136
  function is_a_to_z_character($char) {
137
+ return (($char >= 'a' && $char <= 'z') || ($char >= 'A' && $char <= 'Z')) ? true : false;
138
  }
139
 
140
  /**
142
  * @return boolean true if a digit
143
  */
144
  function is_digit($char) {
145
+ return (($char >= '0' && $char <= '9')) ? true : false;
146
  }
147
 
148
  /**
152
  * @return int length of entity
153
  */
154
  function is_html_entity($string, $position) {
155
+ if ($string[$position] == "&") {
156
+ $end_pos = $position + 1;
157
+ while ($string[$end_pos] == "#" || $this->is_digit($string[$end_pos]) || $this->is_a_to_z_character($string[$end_pos]))
158
+ ++$end_pos;
159
+ if ($string[$end_pos] == ';') return $end_pos - $position + 1;
160
+ }
161
+ return 0;
162
  }
163
 
164
  /**
170
  * @return boolean true if not a breaker (apostrophy)
171
  */
172
  function is_entity_breaker($entity) {
173
+ return!(stripos('&#8217;&apos;&quot;&#039;&#39;', $entity) !== FALSE);
174
  }
175
 
176
  /**
241
  &yuml; &#255; ÿ ÿ latin small letter y with diaeresis
242
  */
243
  function is_entity_letter($entity) {
244
+
245
+ $entnum = (int) substr($entity, 2);
246
+ if (($entnum >= 192 && $entnum <= 214) || ($entnum >= 216 && $entnum <= 246) || ($entnum >= 248 && $entnum <= 255)) {
247
+ return true;
248
+ }
249
+ $entities = '&Agrave;&Aacute;&Acirc;&Atilde;&Auml;&Aring;&AElig;&Ccedil;&Egrave;&Eacute;&Ecirc;&Euml;&Igrave;&Iacute;&Icirc;&Iuml;&ETH;' .
250
+ '&Ntilde;&Ograve;&Oacute;&Ocirc;&Otilde;&Ouml;&Oslash;&Ugrave;&Uacute;&Ucirc;&Uuml;&Yacute;&THORN;&szlig;' .
251
+ '&oslash;&ugrave;&yuml;';
252
+ return (stripos($entities, $entity) !== FALSE);
253
  }
254
 
255
  /**
260
  * @return int length of breaker if current position marks a break in sentence
261
  */
262
  function is_sentence_breaker($char, $nextchar, $nextnextchar) {
263
+ if (($char == '.' || $char == '-') && ($this->is_white_space($nextchar)))
264
+ return 1;
265
+ //∙
266
+ if (ord($char) == 226 && ord($nextchar) == 136 && ord($nextnextchar) == 153)
267
+ return 3;
268
+ //·
269
+ if (ord($char) == 194 && ord($nextchar) == 183) return 2;
270
+ return (strpos(',?()[]"!:|;', $char) !== false) ? 1 : 0; // TODO: might need to add < and > here
271
  }
272
 
273
  /**
275
  * @return int length of number.
276
  */
277
  function is_number($page, $position) {
278
+ return strspn($page, '0123456789-+$%,.\\/', $position);
279
  }
280
 
281
  /**
284
  * @param int $end - end of pharse in element
285
  */
286
  function tag_phrase($string, $start, $end) {
287
+ $phrase = trim(substr($string, $start, $end - $start));
288
+ if ($phrase) {
289
+
290
+ $node = new simple_html_dom_node($this->html);
291
+ $node->tag = 'phrase';
292
+ $node->parent = $this->currentnode;
293
+ $this->currentnode->nodes[] = $node;
294
+ $node->_[HDOM_INFO_OUTER] = '';
295
+ $node->phrase = $phrase;
296
+ if ($this->inbody) $node->inbody = $this->inbody;
297
+ if ($this->inselect) $node->inselect = true;
298
+ }
299
  }
300
 
301
  /**
303
  * @param string $string - the string which is "broken" into smaller strings
304
  */
305
  function parsetext($string) {
306
+ $pos = 0;
307
+ // $pos = skip_white_space($string, $pos);
308
+ // skip CDATA in feed_fix mode
309
+ if ($this->feed_fix) {
310
+ if (strpos($string, '<![CDATA[') === 0) {
311
+ $pos = 9; // CDATA length
312
+ $string = substr($string, 0, -3); // chop the last ]]>;
313
+ }
314
+ }
315
+
316
+ $start = $pos;
317
+
318
+ while ($pos < strlen($string)) {
319
+ // Some HTML entities make us break, almost all but apostrophies
320
+ if ($len_of_entity = $this->is_html_entity($string, $pos)) {
321
+ $entity = substr($string, $pos, $len_of_entity);
322
+ if (($this->is_white_space($string[$pos + $len_of_entity]) || $this->is_entity_breaker($entity)) && !$this->is_entity_letter($entity)) {
323
+
324
+ $this->tag_phrase($string, $start, $pos);
325
+ $start = $pos + $len_of_entity;
326
+ }
327
+ //skip past entity
328
+ $pos += $len_of_entity;
329
+ }
330
+ // we have a special case for <> tags which might have came to us (maybe in xml feeds) (we'll skip them...)
331
+ elseif ($string[$pos] == '<') {
332
+ $this->tag_phrase($string, $start, $pos);
333
+ while ($string[$pos] != '>' && $pos < strlen($string))
334
+ $pos++;
335
+ $pos++;
336
+ $start = $pos;
337
+ }
338
+ // will break translation unit when there's a breaker ",.[]()..."
339
+ elseif ($senb_len = $this->is_sentence_breaker($string[$pos], $string[$pos + 1], $string[$pos + 2])) {
340
+ $this->tag_phrase($string, $start, $pos);
341
+ $pos += $senb_len;
342
+ $start = $pos;
343
+ }
344
+ // Numbers also break, if they are followed by whitespace (or a sentence breaker) (don't break 42nd) // TODO: probably by breaking entities too...
345
+ // also prefixed by whitespace?
346
+ elseif ($num_len = $this->is_number($string, $pos)) {
347
+ // this is the case of B2 or B2,
348
+ if (($this->is_white_space($string[$pos - 1]) || ($start == $pos)
349
+ || ($this->is_sentence_breaker($string[$pos + $num_len - 1], $string[$pos + $num_len], $string[$pos + $num_len + 1]))) &&
350
+ ($this->is_white_space($string[$pos + $num_len]) || $this->is_sentence_breaker($string[$pos + $num_len], $string[$pos + $num_len + 1], $string[$pos + $num_len + 2]))) {
351
+ // we will now compensate on the number followed by breaker case, if we need to
352
+ if (!($this->is_white_space($string[$pos - 1]) || ($start == $pos))) {
353
+ if ($this->is_sentence_breaker($string[$pos + $num_len - 1], $string[$pos + $num_len], $string[$pos + $num_len + 1])) {
354
+ $num_len--; //this makes the added number shorter by one, and the pos will be at a sentence breaker next so we don't have to compensate
355
+ }
356
+ $pos += $num_len;
357
+ $num_len = 0; // we have already added this
358
+ }
359
+ $this->tag_phrase($string, $start, $pos);
360
+ $start = $pos + $num_len + 1;
361
+ }
362
+ $pos += $num_len + 1;
363
+ } else {
364
+ $pos++;
365
+ }
366
+ }
367
+
368
+ // the end is also some breaker
369
+ if ($pos > $start) {
370
+ $this->tag_phrase($string, $start, $pos);
371
+ }
372
  }
373
 
374
  /**
377
  * @param simple_html_dom_node $node
378
  */
379
  function translate_tagging($node, $level = 0) {
380
+ $this->currentnode = $node;
381
+ // we don't want to translate non-translatable classes
382
+ if (stripos($node->class, NO_TRANSLATE_CLASS) !== false ||
383
+ stripos($node->class, NO_TRANSLATE_CLASS_GOOGLE) !== false ||
384
+ strtolower($node->lang) === $this->lang) return;
385
+
386
+ if ($this->inselect && $level <= $this->inselect)
387
+ $this->inselect = false;
388
+
389
+ if ($this->inlangnondef && $level <= $this->inlangnondef)
390
+ $this->inlangnondef = false;
391
+
392
+ if ($this->default_lang && $node->lang != '' && stripos($node->lang, $this->lang) === false)
393
+ $this->inlangnondef = $level;
394
+
395
+ // we can only do translation for elements which are in the body, not in other places, and this must
396
+ // move here due to the possibility of early recurse in default language
397
+ if ($node->tag == 'body') {
398
+ $this->inbody = true;
399
+ }
400
+ // this again should be here, the different behaviour on select and textarea
401
+ elseif ($node->tag == 'select' || $node->tag == 'textarea') {
402
+ $this->inselect = $level;
403
+ }
404
+
405
+ //support only_thislanguage class, (nulling the node if it should not display)
406
+ if (strtolower($node->lang) != $this->lang && stripos($node->class, ONLY_THISLANGUAGE_CLASS) !== false) {
407
+ $node->outertext = '';
408
+ return;
409
+ }
410
+
411
+ // if we are in the default lang, and we have no foreign langs classes, we'll recurse from here
412
+ if ($this->default_lang && !$this->inlangnondef) {
413
+ foreach ($node->nodes as $c) {
414
+ $this->translate_tagging($c, $level + 1);
415
+ }
416
+ return;
417
+ }
418
+
419
+ if (isset($this->ignore_tags[$node->tag])) return;
420
+
421
+ if ($node->tag == 'text') {
422
+ // this prevents translation of a link that just surrounds its address
423
+ if ($node->parent->tag == 'a' && $node->parent->href == $node->outertext) {
424
+ return;
425
+ }
426
+ // link tags inners are to be ignored
427
+ if ($node->parent->tag == 'link') {
428
+ return;
429
+ }
430
+ if (trim($node->outertext)) {
431
+ $this->parsetext($node->outertext);
432
+ }
433
+ }
434
+ // for anchors we will rewrite urls if we can
435
+ elseif ($node->tag == 'a') {
436
+ if ($this->url_rewrite_func != null) {
437
+ $node->href = call_user_func_array($this->url_rewrite_func, array($node->href));
438
+ }
439
+ }
440
+ // same for options, although normally not required (ticket #34)
441
+ elseif ($node->tag == 'option') {
442
+ if ($this->url_rewrite_func != null) {
443
+ $node->value = call_user_func_array($this->url_rewrite_func, array($node->value));
444
+ }
445
+ }
446
+ // in submit type inputs, we want to translate the value
447
+ elseif ($node->tag == 'input' && $node->type == 'submit') {
448
+ $this->parsetext($node->value);
449
+ }
450
+
451
+ // titles are also good places to translate, exist in a, img, abbr, acronym
452
+ if ($node->title) $this->parsetext($node->title);
453
+
454
+ // Meta content (keywords, description) are also good places to translate
455
+ if ($node->tag == 'meta' && $node->content)
456
+ $this->parsetext($node->content);
457
+
458
+ // recurse
459
+ foreach ($node->nodes as $c) {
460
+ $this->translate_tagging($c, $level + 1);
461
+ }
462
  }
463
 
464
  /**
470
  * @return string
471
  */
472
  function create_edit_span($original_text, $translated_text, $source, $for_hidden_element = false) {
473
+ // Use base64 encoding to make that when the page is translated (i.e. update_translation) we
474
+ // get back exactlly the same string without having the client decode/encode it in anyway.
475
+ $span = '<span class ="' . SPAN_PREFIX . '" id="' . SPAN_PREFIX . $this->segment_id . '" data-token="' . base64_url_encode($original_text) . "\" data-source=\"$source\"";
476
+ // those are needed for on the fly image creation / hidden elements translations
477
+ if ($this->is_edit_mode || $for_hidden_element) {
478
+ $span .= " data-orig=\"$original_text\"";
479
+ if ($for_hidden_element) {
480
+ $span.= ' data-hidden="y"';
481
+ // hidden elements currently have issues figuring what they translated in the JS
482
+ if ($translated_text != null) {
483
+ $span.= " data-trans=\"$translated_text\"";
484
+ }
485
+ }
486
+ }
487
+ $span .= '>';
488
+ ++$this->segment_id;
489
+ return $span;
490
+ }
491
+
492
+ /**
493
+ * This function does some ad replacement for transposh benefit
494
+ */
495
+ function do_ad_switch() {
496
+ foreach ($this->html->noise as $key => $value) {
497
+ if (strpos($value, 'google_ad_client') !== false) {
498
+ $publoc = strpos($value, 'pub-');
499
+ $sufloc = strpos($value, '"', $publoc);
500
+ if (!$sufloc) $sufloc = strpos($value, "'", $publoc);
501
+ echo $publoc . " " . $sufloc;
502
+ if ($publoc && $sufloc)
503
+ $this->html->noise[$key] = substr($value, 0, $publoc) . 'pub-7523823497771676' . substr($value, $sufloc);
504
+ }
505
+ }
506
  }
507
 
508
  /**
511
  * @return string Translated content is here
512
  */
513
  function fix_html($string) {
514
+ // ready our stats
515
+ $this->stats = new parserstats();
516
+ // create our dom
517
+ $this->html = str_get_html($string);
518
+ // mark translateable elements
519
+ $this->translate_tagging($this->html->root);
520
+
521
+ // first fix the html tag itself - we might need to to the same for all such attributes with flipping
522
+ if ($this->dir_rtl) $this->html->find('html', 0)->dir = "rtl";
523
+ else $this->html->find('html', 0)->dir = "ltr";
524
+
525
+ if ($this->lang) {
526
+ $this->html->find('html', 0)->lang = $this->lang;
527
+ // add support for <meta name="language" content="<lang>">
528
+ if ($this->html->find('meta[name=language]')) {
529
+ $this->html->find('meta[name=language]')->content = $this->lang;
530
+ }
531
+ }
532
+
533
+ // not much point in further processing if we don't have a function that does it
534
+ if ($this->fetch_translate_func == null) {
535
+ return $this->html;
536
+ }
537
+
538
+ // fix feed
539
+ if ($this->feed_fix) {
540
+ // fix urls on feed
541
+
542
+ foreach (array('link', 'wfw:commentrss', 'comments') as $tag) {
543
+ foreach ($this->html->find($tag) as $e) {
544
+ $e->innertext = call_user_func_array($this->url_rewrite_func, array($e->innertext));
545
+ // no need to translate anything here
546
+ unset($e->nodes);
547
+ }
548
+ }
549
+ // guid is not really a url -- in some future, we can check if permalink is true and probably falsify it
550
+ foreach ($this->html->find('guid') as $e) {
551
+ $e->innertext = $e->innertext . '-' . $this->lang;
552
+ unset($e->nodes);
553
+ }
554
+ // fix feed language
555
+ $this->html->find('language', 0)->innertext = $this->lang;
556
+ unset($this->html->find('language', 0)->nodes);
557
+ } else {
558
+ // since this is not a feed, we might have references to such in the <link rel="alternate">
559
+ foreach ($this->html->find('link') as $e) {
560
+ if (strcasecmp($e->rel, 'alternate') == 0 || strcasecmp($e->rel, 'canonical') == 0) {
561
+ $e->href = call_user_func_array($this->url_rewrite_func, array($e->href));
562
+ }
563
+ }
564
+ }
565
+
566
+ // try some prefetching... (//todo - maybe move directly to the phrase create)
567
+ if ($this->prefetch_translate_func != null) {
568
+ foreach ($this->html->find('text') as $e) {
569
+ foreach ($e->nodes as $ep) {
570
+ $originals[] = $ep->phrase;
571
+ }
572
+ }
573
+ foreach (array('title', 'value') as $title) {
574
+ foreach ($this->html->find('[' . $title . ']') as $e) {
575
+ foreach ($e->nodes as $ep) {
576
+ $originals[] = $ep->phrase;
577
+ }
578
+ }
579
+ }
580
+ foreach ($this->html->find('[content]') as $e) {
581
+ foreach ($e->nodes as $ep) {
582
+ $originals[] = $ep->phrase;
583
+ }
584
+ }
585
+ call_user_func_array($this->prefetch_translate_func, array($originals, $this->lang));
586
+ }
587
+
588
+ // actually translate tags
589
+ // texts are first
590
+ foreach ($this->html->find('text') as $e) {
591
+ $right = '';
592
+ $newtext = '';
593
+ foreach ($e->nodes as $ep) {
594
+ list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
595
+ //stats
596
+ $this->stats->total_phrases++;
597
+ if ($translated_text) {
598
+ $this->stats->translated_phrases++;
599
+ if ($source == 0) $this->stats->human_translated_phrases++;
600
+ }
601
+ if (($this->is_edit_mode || ($this->is_auto_translate && $translated_text == null))/* && $ep->inbody */) {
602
+ $spanend = "</span>";
603
+ if ($ep->inselect || !$ep->inbody) {
604
+ $savedspan .= $this->create_edit_span($ep->phrase, $translated_text, $source, true) . $spanend;
605
+ $span = '';
606
+ $spanend = '';
607
+ } else {
608
+ $span = $this->create_edit_span($ep->phrase, $translated_text, $source);
609
+ if ($translated_text == null)
610
+ $translated_text = $ep->phrase;
611
+ }
612
+ }
613
+ else {
614
+ $span = '';
615
+ $spanend = '';
616
+ }
617
+ if ($translated_text) {
618
+ list ($left, $right) = explode($ep->phrase, $e->outertext, 2);
619
+ $newtext .= $left . $span . $translated_text . $spanend;
620
+ $e->outertext = $right;
621
+ }
622
+ }
623
+ if ($newtext) {
624
+ $e->outertext = $newtext . $right;
625
+
626
+ }
627
+ // hmm?
628
+ if (!$ep->inselect && $savedspan && $ep->inbody) {
629
+ $e->outertext = $savedspan . $e->outertext;
630
+ $savedspan = "";
631
+ }
632
+ }
633
+
634
+ // now we handle the title attributes (and the value of submit buttons)
635
+ foreach (array('title', 'value') as $title) {
636
+ $hidden_phrases = array();
637
+ foreach ($this->html->find('[' . $title . ']') as $e) {
638
+ $span = '';
639
+ $spanend = '';
640
+ $right = '';
641
+ $newtext = '';
642
+ // when we already have a parent outertext we'll have to update it directly
643
+ if ($e->parent->_[HDOM_INFO_OUTER]) {
644
+ $saved_outertext = $e->outertext;
645
+ }
646
+
647
+ foreach ($e->nodes as $ep) {
648
+ if ($ep->tag == 'phrase') {
649
+ list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
650
+ // more stats
651
+ $this->stats->total_phrases++;
652
+ if ($ep->inbody) $this->stats->hidden_phrases++; else
653
+ $this->stats->meta_phrases++;
654
+ if ($translated_text) {
655
+ $this->stats->translated_phrases++;
656
+ if ($ep->inbody)
657
+ $this->stats->hidden_translated_phrases++; else
658
+ $this->stats->meta_translated_phrases++;
659
+ if ($source == 0)
660
+ $this->stats->human_translated_phrases++;
661
+ }
662
+ if (($this->is_edit_mode || ($this->is_auto_translate && $translated_text == null)) && $ep->inbody) {
663
+ // prevent duplicate translation (title = text)
664
+ if (strpos($e->innertext, base64_url_encode($ep->phrase)) === false) {
665
+ //no need to translate span the same hidden phrase more than once
666
+ if (!in_array($ep->phrase, $hidden_phrases)) {
667
+ $this->stats->hidden_translateable_phrases++;
668
+ $span .= $this->create_edit_span($ep->phrase, $translated_text, $source, true) . "</span>";
669
+ //
670
+ $hidden_phrases[] = $ep->phrase;
671
+ }
672
+ }
673
+ }
674
+ if ($translated_text) {
675
+ list ($left, $right) = explode($ep->phrase, $e->$title, 2);
676
+ $newtext .= $left . $translated_text;
677
+ $e->$title = $right;
678
+ }
679
+ }
680
+ }
681
+ if ($newtext) {
682
+ $e->$title = $newtext . $right;
683
+
684
+ }
685
+
686
+ $e->outertext .= $span;
687
+ // this is where we update in the outercase issue
688
+ if ($e->parent->_[HDOM_INFO_OUTER]) {
689
+ $e->parent->outertext = implode($e->outertext, explode($saved_outertext, $e->parent->outertext, 2));
690
+ }
691
+ }
692
+ }
693
+
694
+ // now we handle the meta content - which is simpler because they can't be edited or auto-translated
695
+ // we also don't expect any father modifications here
696
+ foreach ($this->html->find('[content]') as $e) {
697
+ $right = '';
698
+ $newtext = '';
699
+
700
+ foreach ($e->nodes as $ep) {
701
+ if ($ep->tag == 'phrase') {
702
+ // even more stats
703
+ $this->stats->total_phrases++;
704
+ $this->stats->meta_phrases++;
705
+ list ($translated_text, $source) = call_user_func_array($this->fetch_translate_func, array($ep->phrase, $this->lang));
706
+ if ($translated_text) {
707
+ $this->stats->translated_phrases++;
708
+ $this->stats->meta_translated_phrases++;
709
+ if ($source == 0)
710
+ $this->stats->human_translated_phrases++;
711
+ list ($left, $right) = explode($ep->phrase, $e->content, 2);
712
+ $newtext .= $left . $translated_text;
713
+ $e->content = $right;
714
+ }
715
+ }
716
+ }
717
+ if ($newtext) {
718
+ $e->content = $newtext . $right;
719
+
720
+ }
721
+ }
722
+ // only in 5 out of 100 pages, with just translated pages, we might show an ad for transposh
723
+ if ($this->allow_ad && !$this->default_lang && mt_rand(1, 100) > 95) {
724
+ $this->do_ad_switch();
725
+ }
726
+ // This adds a meta tag with our statistics json-encoded inside...
727
+ $this->stats->stop_timing();
728
+ $head = $this->html->find('head', 0);
729
+ if ($head != null)
730
+ $head->lastChild()->outertext .= "\n<meta name=\"translation-stats\" content='" . json_encode($this->stats) . "'/>";
731
+
732
+ // Changed because of places where tostring failed
733
+ //return $this->html;
734
+ return $this->html->outertext;
735
  }
736
 
737
  /**
741
  * @since 0.3.5
742
  */
743
  function get_phrases_list($string) {
744
+ $result = array();
745
+ // create our dom
746
+ $this->html = str_get_html($string);
747
+ // mark translateable elements
748
+ $this->translate_tagging($this->html->root);
749
+ foreach ($this->html->nodes as $ep) {
750
+ if ($ep->tag == 'phrase') {
751
+ $result[$ep->phrase] = $ep->phrase;
752
+ }
753
+ }
754
+ return $result;
755
  }
756
 
757
  }
core/shd/simple_html_dom.php CHANGED
@@ -491,7 +491,7 @@ class simple_html_dom {
491
  protected $size;
492
  protected $cursor;
493
  protected $parent;
494
- protected $noise = array();
495
  protected $token_blank = " \t\r\n";
496
  protected $token_equal = ' =/>';
497
  protected $token_slash = " />\r\n\t";
491
  protected $size;
492
  protected $cursor;
493
  protected $parent;
494
+ public $noise = array();
495
  protected $token_blank = " \t\r\n";
496
  protected $token_equal = ' =/>';
497
  protected $token_slash = " />\r\n\t";
index.php → index.html RENAMED
File without changes
js/transposh.js CHANGED
@@ -1,6 +1,7 @@
1
- (function(a){function w(d,c){if(a.trim(c).length!==0){var f=function(){var b=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),p=a("#"+e+"img_"+b);a("#"+e+b).attr("data-source",1);p.removeClass("tr-icon-yellow").removeClass("tr-icon-green").addClass("tr-icon-yellow")};a("*[data-token='"+d+"'][data-hidden!='y']").html(c).each(f);a("*[data-token='"+d+"'][data-hidden='y']").attr("data-trans",c).each(f)}}function l(d,c){t_jp.progress&&a("#"+d).progressbar("value",c)}function q(d,c){clearTimeout(r);
2
- h.push(d);m.push(c);w(d,c);r=setTimeout(function(){var f={ln0:t_jp.lang,sr0:s,translation_posted:"2",items:h.length},b;for(b=0;b<h.length;b+=1){f["tk"+b]=h[b];f["tr"+b]=m[b];t+=a("*[data-token='"+h[b]+"']").size()}a.ajax({type:"POST",url:t_jp.post_url,data:f,success:function(){l(j,t/g*100)}});m=[];h=[]},200)}function u(){var d=[],c=t_jp.lang;a("."+e+'[data-source=""]').each(function(){var f=a(this).attr("data-token"),b=a(this).attr("data-orig");if(b===undefined)b=a(this).html();if(d[b]!==1){d[b]=
3
- 1;if(typeof Microsoft!=="undefined"){if(c==="zh")c="zh-chs";else if(c==="zh-tw")c="zh-cht";try{Microsoft.Translator.translate(b,"",c,function(k){q(f,a("<div>"+k+"</div>").text());l(i,(g-a("."+e+'[data-source=""]').size())/g*100)})}catch(p){}}else google.language.translate(b,"",t_jp.lang,function(k){if(!k.error){q(f,a("<div>"+k.translation+"</div>").text());l(i,(g-a("."+e+'[data-source=""]').size())/g*100)}})}})}var n,v,o,g,e=t_jp.prefix,i=e+"pbar",j=i+"_s",s=1,t=0,r,h=[],m=[];v=function(){google.load("language",
4
- "1",{callback:n})};a(document).ready(function(){a("#"+e+"setdeflang").click(function(){a.get(t_jp.post_url+"?tr_cookie="+Math.random());a(this).hide("slow");return false});var d;g=a("."+e+'[data-source=""]').size();d=new Date;a.ajaxSetup({cache:true});if((g>5||d.getHours()===4&&g>0)&&(t_jp.google||t_jp.msn)){n=function(){if(t_jp.progress){var c=function(){a.xLazyLoader({js:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.3/jquery-ui.min.js",css:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.3/themes/ui-lightness/jquery-ui.css",
5
- success:function(){a("#"+e+"credit").css({overflow:"auto"}).append('<div style="float: left;width: 90%;height: 10px" id="'+i+'"/><div style="margin-bottom:10px;float:left;width: 90%;height: 10px" id="'+j+'"/>');a("#"+i).progressbar({value:0});a("#"+j).progressbar({value:0});a("#"+j+" > div").css({background:"#28F828",border:"#08A908 1px solid"});u()}})};typeof a.xLazyLoader==="function"?c():a.getScript(t_jp.plugin_url+"/js/lazy.js",c)}else u()};if(t_jp.msn&&t_jp.preferred===2||!t_jp.google){s=2;o=
6
- function(){a.getScript("http://api.microsofttranslator.com/V1/Ajax.svc/Embed?appId="+t_jp.msnkey,n)};t_jp.edit&&t_jp.progress?a.getScript(t_jp.plugin_url+"/js/lazy.js",o):o()}else a.getScript("http://www.google.com/jsapi",v)}t_jp.edit&&a.getScript(t_jp.plugin_url+"/js/transposhedit.js")})})(jQuery);
 
1
+ (function(a){function u(c,d){if(a.trim(d).length!==0){var b=function(){var e=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),i=a("#"+f+"img_"+e);a("#"+f+e).attr("data-source",1);i.removeClass("tr-icon-yellow").removeClass("tr-icon-green").addClass("tr-icon-yellow")};a("*[data-token='"+c+"'][data-hidden!='y']").html(d).each(b);a("*[data-token='"+c+"'][data-hidden='y']").attr("data-trans",d).each(b)}}function v(c,d){clearTimeout(o);h.push(c);n.push(d);u(c,d);o=setTimeout(function(){var b=
2
+ {ln0:t_jp.lang,sr0:p,translation_posted:"2",items:h.length},e;for(e=0;e<h.length;e+=1){b["tk"+e]=h[e];b["tr"+e]=n[e];q+=a("*[data-token='"+h[e]+"']").size()}a.ajax({type:"POST",url:t_jp.post_url,data:b,success:function(){var i=q/j*100;t_jp.progress&&a("#"+k).progressbar("value",i)}});n=[];h=[]},200)}function l(c,d){v(c,a("<div>"+d+"</div>").text());var b=(j-a("."+f+'[data-source=""]').size())/j*100;t_jp.progress&&a("#"+m).progressbar("value",b)}function w(c,d){var b="";a(c).each(function(e){b+="&q="+
3
+ escape(c[e])});a.ajax({url:"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0"+b+"&langpair=%7C"+t_jp.lang,dataType:"jsonp",success:d})}function x(c,d){w(d,function(b){if(b.responseStatus>=200&&b.responseStatus<300)b.responseData.translatedText!==undefined?l(c[0],b.responseData.translatedText):a(b.responseData).each(function(e){this.responseStatus===200&&l(c[e],this.responseData.translatedText)})})}function y(c,d){var b="[";a(c).each(function(e){b+='"'+escape(c[e])+'",'});b=b.slice(0,
4
+ -1)+"]";a.ajax({url:"http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray?appId="+t_jp.MSN_APPID+"&to="+t_jp.binglang+"&texts="+b,dataType:"jsonp",jsonp:"oncomplete",success:d})}function z(c,d){p=2;y(d,function(b){a(b).each(function(e){l(c[e],this.TranslatedText)})})}function A(c,d){a.getJSON(t_jp.post_url+"?tgp="+d+"&tgl="+t_jp.lang,function(b){b.sentences[0].trans&&l(c,b.sentences[0].trans)})}function r(c,d){if(t_jp.msn&&t_jp.preferred==="2")z(c,d);else if(t_jp.tgp)d[0]&&A(c[0],d[0]);else x(c,
5
+ d)}function s(){var c=[],d=0,b=[],e=[];if(t_jp.tgp)t=0;a("."+f+'[data-source=""]').each(function(){var i=a(this).attr("data-token"),g=a(this).attr("data-orig");if(g===undefined)g=a(this).html();if(c[g]!==1){c[g]=1;if(d+g.length>t){r(e,b);d=0;b=[];e=[]}d+=g.length;e.push(i);b.push(g)}});r(e,b)}var t=128,j,f=t_jp.prefix,m=f+"pbar",k=m+"_s",p=1,q=0,o,h=[],n=[];t_jp.MSN_APPID="FACA8E2DF8DCCECE0DC311C6E57DA98EFEFA9BC6";a(document).ready(function(){if(t_jp.msn){t_jp.binglang=t_jp.lang;if(t_jp.binglang===
6
+ "zh")t_jp.binglang="zh-chs";else if(t_jp.binglang==="zh-tw")t_jp.binglang="zh-cht"}a("#"+f+"setdeflang").click(function(){a.get(t_jp.post_url+"?tr_cookie="+Math.random());a(this).hide("slow");return false});j=a("."+f+'[data-source=""]').size();a.ajaxSetup({cache:true});if(j&&(t_jp.google||t_jp.msn||t_jp.tgp))if(t_jp.progress){var c=function(){a.xLazyLoader({js:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js",css:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/ui-lightness/jquery-ui.css",
7
+ success:function(){a("#"+f+"credit").css({overflow:"auto"}).append('<div style="float: left;width: 90%;height: 10px" id="'+m+'"/><div style="margin-bottom:10px;float:left;width: 90%;height: 10px" id="'+k+'"/>');a("#"+m).progressbar({value:0});a("#"+k).progressbar({value:0});a("#"+k+" > div").css({background:"#28F828",border:"#08A908 1px solid"});s()}})};typeof a.xLazyLoader==="function"?c():a.getScript(t_jp.plugin_url+"/js/lazy.js",c)}else s();t_jp.edit&&a.getScript(t_jp.plugin_url+"/js/transposhedit.js")})})(jQuery);
js/transposhadmin.js CHANGED
@@ -1,5 +1,8 @@
1
- var timer,items=0,translations=[],tokens=[],langs=[];
2
- function ajax_translate_me(g,c,e){clearTimeout(timer);items++;tokens.push(g);translations.push(c);langs.push(e);timer=setTimeout(function(){for(var b={sr0:1,translation_posted:"2",items:items},a=0;a<items;a++){if(tokens[a]!=tokens[a-1])b["tk"+a]=tokens[a];if(langs[a]!=langs[a-1])b["ln"+a]=langs[a];if(translations[a]!=translations[a-1])b["tr"+a]=translations[a]}jQuery.ajax({type:"POST",url:t_jp.post_url,data:b,success:function(){},error:function(){}});items=0;translations=[];tokens=[];langs=[]},200)}
3
- function translate_post(g){var c=0,e="",b=0;jQuery("#tr_loading").data("done",false);jQuery.getJSON(t_jp.post_url+"?tr_phrases_post=y&post="+g+"&random="+Math.random(),function(a){jQuery("#tr_translate_title").html("Translating post: "+a.posttitle);if(a.length===undefined){jQuery("#tr_loading").html("Nothing left to translate");jQuery("#tr_loading").data("done",true)}else{jQuery("#tr_loading").html('Translating<br/>Phrase: <span id="p"></span><div id="progress_bar"/>Target lanaguage: <span id="l"></span><div id="progress_bar2"/><span id="r"></span>');
4
- jQuery("#progress_bar").progressbar({value:0});jQuery("#progress_bar2").progressbar({value:0});jQuery.each(a.p,function(f,d){jQuery("#progress_bar2").progressbar("value",b/d.l.length*100);jQuery.each(d.l,function(j,h){google.language.translate(f,"",h,function(i){if(!i.error){if(e!=f){e=f;b=0;c++}jQuery("#progress_bar").progressbar("value",c/a.length*100);b++;jQuery("#progress_bar2").progressbar("value",b/d.l.length*100);jQuery("#p").text(jQuery("<div>"+f+"</div>").text());jQuery("#l").text(h);jQuery("#r").text(jQuery("<div>"+
5
- i.translation+"</div>").text());c===a.length&&b===d.l.length&&jQuery("#tr_loading").data("done",true);ajax_translate_me(d.t,jQuery("<div>"+i.translation+"</div>").text(),h)}})})})}})}google.load("language","1");jQuery(document).ready(function(){t_jp.post&&translate_post(t_jp.post)});
 
 
 
1
+ var timer,items=0,translations=[],tokens=[],langs=[],sources=[],BATCH_SIZE=128,pair_count=0,curr_pair=0;t_jp.MSN_APPID="FACA8E2DF8DCCECE0DC311C6E57DA98EFEFA9BC6";function make_progress(e,c){curr_pair+=1;jQuery("#progress_bar").progressbar("value",curr_pair/pair_count*100);jQuery("#p").text("("+c+") "+jQuery("<div>"+e+"</div>").text());curr_pair===pair_count&&jQuery("#tr_loading").data("done",true)}
2
+ function ajax_translate_me(e,c,b,d){make_progress(c,b);clearTimeout(timer);items+=1;tokens.push(e);translations.push(c);langs.push(b);sources.push(d);timer=setTimeout(function(){var f={translation_posted:"2",items:items},a;for(a=0;a<items;a+=1){if(tokens[a]!==tokens[a-1])f["tk"+a]=tokens[a];if(langs[a]!==langs[a-1])f["ln"+a]=langs[a];if(translations[a]!==translations[a-1])f["tr"+a]=translations[a];if(sources[a]!==sources[a-1])f["sr"+a]=sources[a]}jQuery.ajax({type:"POST",url:t_jp.post_url,data:f,
3
+ success:function(){},error:function(){}});items=0;translations=[];tokens=[];langs=[];sources=[]},200)}function do_mass_ms_translate(e,c){var b="[";jQuery(e).each(function(d){b+='"'+escape(e[d])+'",'});b=b.slice(0,-1)+"]";jQuery.ajax({url:"http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray?appId="+t_jp.MSN_APPID+"&to="+t_jp.binglang+"&texts="+b,dataType:"jsonp",jsonp:"oncomplete",success:c})}
4
+ function do_mass_ms_invoker(e,c,b){t_jp.binglang=b;do_mass_ms_translate(c,function(d){jQuery(d).each(function(f){ajax_translate_me(e[f],this.TranslatedText,b,2)})})}function do_mass_google_translate_l(e,c,b){var d="",f;for(f in c)d+="&langpair=%7C"+c[f];jQuery.ajax({url:"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="+escape(e)+d,dataType:"jsonp",success:b})}
5
+ function do_mass_google_invoker_l(e,c,b){do_mass_google_translate_l(c,b,function(d){if(d.responseStatus===200)d.responseData.translatedText!==undefined?ajax_translate_me(e,d.responseData.translatedText,b[0],1):jQuery(d.responseData).each(function(f){this.responseStatus===200&&ajax_translate_me(e,this.responseData.translatedText,b[f],1)})})}
6
+ function translate_post(e){var c="",b=[],d=[],f,a,h,i,m=0,j=[],k=[],l;jQuery("#tr_loading").data("done",false);jQuery.getJSON(t_jp.post_url+"?tr_phrases_post=y&post="+e+"&random="+Math.random(),function(g){jQuery("#tr_translate_title").html("Translating post: "+g.posttitle);if(g.length===undefined){jQuery("#tr_loading").html("Nothing left to translate");jQuery("#tr_loading").data("done",true)}else{curr_pair=pair_count=0;for(h in g.p)pair_count+=g.p[h].l.length;jQuery("#tr_loading").html('<br/>Translation: <span id="p"></span><div id="progress_bar"/>');
7
+ jQuery("#progress_bar").progressbar({value:0});if(t_jp.preferred==="2")for(f in t_jp.m_langs){c=t_jp.m_langs[f];d=[];b=[];for(h in g.p){i=g.p[h];if(i.l.indexOf(c)!==-1){d.push(h);b.push(i.t);i.l.splice(i.l.indexOf(c),1);if(i.l.length===0){g.length-=1;delete g.p[h]}}}if(d.length){for(a in d){l=d[a];if(m+l.length>BATCH_SIZE){do_mass_ms_invoker(k,j,c);m=0;j=[];k=[]}m+=l.length;k.push(b[a]);j.push(l)}do_mass_ms_invoker(k,j,c)}}for(h in g.p){i=g.p[h];do_mass_google_invoker_l(i.t,h,i.l)}}})}
8
+ jQuery(document).ready(function(){t_jp.post&&translate_post(t_jp.post)});
js/transposhedit.js CHANGED
@@ -1,13 +1,13 @@
1
- (function(a){function l(b,c){if(a.trim(c).length===0)c=a("[data-token='"+b+"']").attr("data-orig");var e=function(){var f=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),d=a("#"+t_jp.prefix+"img_"+f);a("#"+t_jp.prefix+f).attr("data-source",0);d.removeClass("tr-icon-yellow").removeClass("tr-icon-green").addClass("tr-icon-green")};a("*[data-token='"+b+"'][data-hidden!='y']").html(c).each(e);a("*[data-token='"+b+"'][data-hidden='y']").attr("data-trans",c).each(e)}function m(b,c){l(b,
2
- c);a.ajax({type:"POST",url:t_jp.post_url,data:{ln0:t_jp.lang,sr0:0,translation_posted:"2",items:1,tk0:b,tr0:c},success:function(){},error:function(e){alert("Error !!! failed to translate.\n\nServer's message: "+e.statusText)}})}function g(){if(typeof google==="undefined"){h=function(){google.load("language","1",{callback:i})};i=function(){g()};a.xLazyLoader({js:"http://www.google.com/jsapi",success:h})}else{a(":button:contains('Suggest - Google')").attr("disabled","disabled").addClass("ui-state-disabled");
3
- google.language.translate(a("#"+t_jp.prefix+"original").val(),"",t_jp.lang,function(b){b.error||a("#"+t_jp.prefix+"translation").val(a("<div>"+b.translation+"</div>").text()).keyup()})}}function j(){if(typeof Microsoft==="undefined")a.xLazyLoader({js:"http://api.microsofttranslator.com/V1/Ajax.svc/Embed?appId="+t_jp.msnkey,success:function(){j()}});else{a(":button:contains('Suggest - Bing')").attr("disabled","disabled").addClass("ui-state-disabled");var b=t_jp.lang;if(b==="zh")b="zh-chs";if(b==="zh-tw")b=
4
- "zh-cht";try{Microsoft.Translator.translate(a("#"+t_jp.prefix+"original").val(),"",b,function(e){a("#"+t_jp.prefix+"translation").val(a("<div>"+e+"</div>").text()).keyup()})}catch(c){alert("There was an error using Microsoft.Translator - probably a bad key or URL used in key. ("+c+")")}}}function n(){a('<div id="dial" title="Close without saving?"><p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>You have made a change to the translation. Are you sure you want to discard it?</p></div>').appendTo("body").dialog({bgiframe:true,
5
- resizable:false,height:140,modal:true,overlay:{backgroundColor:"#000",opacity:0.5},buttons:{Discard:function(){a("#"+t_jp.prefix+"translation").data("edit",{changed:false});a(this).dialog("close");a("#"+t_jp.prefix+"d-tabs").dialog("close")},Cancel:function(){a(this).dialog("close")}}})}function k(b){var c={},e={};if(t_jp.msn)c["Suggest - Bing"]=function(){j()};if(t_jp.google)c["Suggest - Google"]=function(){g()};c.Ok=function(){var f=a("#"+t_jp.prefix+"translation").val(),d=a("#"+t_jp.prefix+b).attr("data-token");
6
- if(a("#"+t_jp.prefix+"translation").data("edit").changed){m(d,f);a("#"+t_jp.prefix+"translation").data("edit",{changed:false})}a(this).dialog("close")};e={Close:function(){a(this).dialog("close")}};a("#"+t_jp.prefix+"d-tabs").remove();a('<div id="'+t_jp.prefix+'d-tabs" title="Edit Translation"/>').appendTo("body");a("#"+t_jp.prefix+"d-tabs").append("<ul/>").tabs({cache:true}).tabs("add","#"+t_jp.prefix+"d-tabs-1","Translate").tabs("add",t_jp.post_url+"?tr_token_hist="+a("#"+t_jp.prefix+b).attr("data-token")+
7
  "&lang="+t_jp.lang,"History").css("text-align","left").css("padding",0).bind("tabsload",function(f,d){a("table",d.panel).addClass("ui-widget ui-widget-content").css({width:"95%",padding:"0"});a("table thead tr",d.panel).addClass("ui-widget-header");a("table tbody td[source='2']",d.panel).append('<span title="computer" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-gear"></span>');a("table tbody td[source='1']",d.panel).append('<span title="computer" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-gear"></span>');
8
  a("table tbody td[source='0']",d.panel).append('<span title="human" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-person"></span>')}).bind("tabsselect",function(f,d){a(d.tab).text()==="Translate"?a("#"+t_jp.prefix+"d-tabs").dialog("option","buttons",c):a("#"+t_jp.prefix+"d-tabs").dialog("option","buttons",e)}).bind("dialogbeforeclose",function(){if(a("#"+t_jp.prefix+"translation").data("edit").changed){n();return false}return true});a("#"+t_jp.prefix+"d-tabs li").css("list-style-type",
9
  "none").css("list-style-position","outside");a("#"+t_jp.prefix+"d-tabs-1").css("padding","1px").append('<form id="'+t_jp.prefix+'form"><fieldset><label for="original">Original Text</label><textarea cols="80" row="3" name="original" id="'+t_jp.prefix+'original" class="text ui-widget-content ui-corner-all" readonly="y"/><label for="translation">Translate To</label><textarea cols="80" row="3" name="translation" id="'+t_jp.prefix+'translation" value="" class="text ui-widget-content ui-corner-all"/></fieldset></form>');
10
  a("#"+t_jp.prefix+"d-tabs-1 label").css("display","block");a("#"+t_jp.prefix+"d-tabs-1 textarea.text").css({"margin-bottom":"12px",width:"95%",padding:".4em"});a("#"+t_jp.prefix+"original").val(a("#"+t_jp.prefix+b).attr("data-orig"));a("#"+t_jp.prefix+"translation").val(a("#"+t_jp.prefix+b).html());a("#"+t_jp.prefix+b).attr("data-trans")&&a("#"+t_jp.prefix+"translation").val(a("#"+t_jp.prefix+b).attr("data-trans"));a("#"+t_jp.prefix+"translation").data("edit",{changed:false});a("#"+t_jp.prefix+"translation").keyup(function(){if(a("#"+
11
- t_jp.prefix+b).text()!==a(this).val()){a(this).css("background","yellow");a(this).data("edit",{changed:true})}else{a(this).css("background","");a(this).data("edit",{changed:false})}});a("#"+t_jp.prefix+"d-tabs").dialog({bgiframe:true,modal:true,width:500,buttons:c})}var h,i;a("."+t_jp.prefix).each(function(){var b=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),c;a(this).after('<span id="'+t_jp.prefix+"img_"+b+'" class="tr-icon" title="'+a(this).attr("data-orig")+'"></span>');c=a("#"+
12
- t_jp.prefix+"img_"+b);c.click(function(){if(typeof a.fn.tabs!=="function"||typeof a.fn.dialog!=="function"){a.ajaxSetup({cache:true});a.getScript(t_jp.plugin_url+"/js/lazy.js",function(){a.xLazyLoader({js:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.3/jquery-ui.min.js",css:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.3/themes/ui-lightness/jquery-ui.css",success:function(){k(b)}})})}else k(b);return false}).css({border:"0px",margin:"1px",padding:"0px"});if(a(this).attr("data-source")===
13
- "0")c.addClass("tr-icon-green");else a(this).attr("data-source")&&c.addClass("tr-icon-yellow");a(this).attr("data-hidden")==="y"&&c.css({opacity:"0.6"})})})(jQuery);
1
+ (function(a){function h(b,c){if(a.trim(c).length===0)c=a("[data-token='"+b+"']").attr("data-orig");var e=function(){var f=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),d=a("#"+t_jp.prefix+"img_"+f);a("#"+t_jp.prefix+f).attr("data-source",0);d.removeClass("tr-icon-yellow").removeClass("tr-icon-green").addClass("tr-icon-green")};a("*[data-token='"+b+"'][data-hidden!='y']").html(c).each(e);a("*[data-token='"+b+"'][data-hidden='y']").attr("data-trans",c).each(e)}function i(b,c){h(b,
2
+ c);a.ajax({type:"POST",url:t_jp.post_url,data:{ln0:t_jp.lang,sr0:0,translation_posted:"2",items:1,tk0:b,tr0:c},success:function(){},error:function(e){alert("Error !!! failed to translate.\n\nServer's message: "+e.statusText)}})}function j(b,c){a.ajax({url:"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="+escape(b)+"&langpair=%7C"+t_jp.lang,dataType:"jsonp",success:c})}function k(){a(":button:contains('Suggest - Google')").attr("disabled","disabled").addClass("ui-state-disabled");
3
+ a(":button:contains('Suggest - Bing')").attr("disabled","").removeClass("ui-state-disabled");j(a("#"+t_jp.prefix+"original").val(),function(b){b.responseStatus===200&&a("#"+t_jp.prefix+"translation").val(a("<div>"+b.responseData.translatedText+"</div>").text()).keyup()})}function l(b,c){a.ajax({url:"http://api.microsofttranslator.com/V2/Ajax.svc/Translate?appId="+t_jp.MSN_APPID+"&to="+t_jp.binglang+"&text="+escape(b),dataType:"jsonp",jsonp:"oncomplete",success:c})}function m(){a(":button:contains('Suggest - Bing')").attr("disabled",
4
+ "disabled").addClass("ui-state-disabled");a(":button:contains('Suggest - Google')").attr("disabled","").removeClass("ui-state-disabled");l(a("#"+t_jp.prefix+"original").val(),function(b){a("#"+t_jp.prefix+"translation").val(a("<div>"+b+"</div>").text()).keyup()})}function n(){a('<div id="dial" title="Close without saving?"><p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>You have made a change to the translation. Are you sure you want to discard it?</p></div>').appendTo("body").dialog({bgiframe:true,
5
+ resizable:false,height:140,modal:true,overlay:{backgroundColor:"#000",opacity:0.5},buttons:{Discard:function(){a("#"+t_jp.prefix+"translation").data("edit",{changed:false});a(this).dialog("close");a("#"+t_jp.prefix+"d-tabs").dialog("close")},Cancel:function(){a(this).dialog("close")}}})}function g(b){var c={},e={};if(t_jp.msn)c["Suggest - Bing"]=function(){m()};if(t_jp.google)c["Suggest - Google"]=function(){k()};c.Ok=function(){var f=a("#"+t_jp.prefix+"translation").val(),d=a("#"+t_jp.prefix+b).attr("data-token");
6
+ if(a("#"+t_jp.prefix+"translation").data("edit").changed){i(d,f);a("#"+t_jp.prefix+"translation").data("edit",{changed:false})}a(this).dialog("close")};e={Close:function(){a(this).dialog("close")}};a("#"+t_jp.prefix+"d-tabs").remove();a('<div id="'+t_jp.prefix+'d-tabs" title="Edit Translation"/>').appendTo("body");a("#"+t_jp.prefix+"d-tabs").append("<ul/>").tabs({cache:true}).tabs("add","#"+t_jp.prefix+"d-tabs-1","Translate").tabs("add",t_jp.post_url+"?tr_token_hist="+a("#"+t_jp.prefix+b).attr("data-token")+
7
  "&lang="+t_jp.lang,"History").css("text-align","left").css("padding",0).bind("tabsload",function(f,d){a("table",d.panel).addClass("ui-widget ui-widget-content").css({width:"95%",padding:"0"});a("table thead tr",d.panel).addClass("ui-widget-header");a("table tbody td[source='2']",d.panel).append('<span title="computer" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-gear"></span>');a("table tbody td[source='1']",d.panel).append('<span title="computer" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-gear"></span>');
8
  a("table tbody td[source='0']",d.panel).append('<span title="human" style="display: inline-block; margin-right: 0.3em;" class="ui-icon ui-icon-person"></span>')}).bind("tabsselect",function(f,d){a(d.tab).text()==="Translate"?a("#"+t_jp.prefix+"d-tabs").dialog("option","buttons",c):a("#"+t_jp.prefix+"d-tabs").dialog("option","buttons",e)}).bind("dialogbeforeclose",function(){if(a("#"+t_jp.prefix+"translation").data("edit").changed){n();return false}return true});a("#"+t_jp.prefix+"d-tabs li").css("list-style-type",
9
  "none").css("list-style-position","outside");a("#"+t_jp.prefix+"d-tabs-1").css("padding","1px").append('<form id="'+t_jp.prefix+'form"><fieldset><label for="original">Original Text</label><textarea cols="80" row="3" name="original" id="'+t_jp.prefix+'original" class="text ui-widget-content ui-corner-all" readonly="y"/><label for="translation">Translate To</label><textarea cols="80" row="3" name="translation" id="'+t_jp.prefix+'translation" value="" class="text ui-widget-content ui-corner-all"/></fieldset></form>');
10
  a("#"+t_jp.prefix+"d-tabs-1 label").css("display","block");a("#"+t_jp.prefix+"d-tabs-1 textarea.text").css({"margin-bottom":"12px",width:"95%",padding:".4em"});a("#"+t_jp.prefix+"original").val(a("#"+t_jp.prefix+b).attr("data-orig"));a("#"+t_jp.prefix+"translation").val(a("#"+t_jp.prefix+b).html());a("#"+t_jp.prefix+b).attr("data-trans")&&a("#"+t_jp.prefix+"translation").val(a("#"+t_jp.prefix+b).attr("data-trans"));a("#"+t_jp.prefix+"translation").data("edit",{changed:false});a("#"+t_jp.prefix+"translation").keyup(function(){if(a("#"+
11
+ t_jp.prefix+b).text()!==a(this).val()){a(this).css("background","yellow");a(this).data("edit",{changed:true})}else{a(this).css("background","");a(this).data("edit",{changed:false})}});a("#"+t_jp.prefix+"d-tabs").dialog({width:500,buttons:c})}a("."+t_jp.prefix).each(function(){var b=a(this).attr("id").substr(a(this).attr("id").lastIndexOf("_")+1),c;a(this).after('<span id="'+t_jp.prefix+"img_"+b+'" class="tr-icon" title="'+a(this).attr("data-orig")+'"></span>');c=a("#"+t_jp.prefix+"img_"+b);c.click(function(){if(typeof a.fn.tabs!==
12
+ "function"||typeof a.fn.dialog!=="function"){a.ajaxSetup({cache:true});a.getScript(t_jp.plugin_url+"/js/lazy.js",function(){a.xLazyLoader({js:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js",css:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/ui-lightness/jquery-ui.css",success:function(){g(b)}})})}else g(b);return false}).css({border:"0px",margin:"1px",padding:"0px"});if(a(this).attr("data-source")==="0")c.addClass("tr-icon-green");else a(this).attr("data-source")&&
13
+ c.addClass("tr-icon-yellow");a(this).attr("data-hidden")==="y"&&c.css({opacity:"0.6"})})})(jQuery);
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: oferwald
3
  Donate link: http://transposh.org/donate/
4
  Tags: translation, widget, filter, bilingual, multilingual, transposh, translate, language, crowdsourcing, context, wiki, RTL, Hebrew, Spanish, French, Russian, English, Arabic, Portuguese
5
- Requires at least: 2.7
6
- Tested up to: 3.0
7
- Stable tag: 0.5.7
8
 
9
  Transposh filter allows in context quick translation of websites, it allows you to crowd-source the translation to your users
10
 
@@ -18,11 +18,12 @@ Transposh translation filter for WordPress offers a unique approach to blog tran
18
  * Multiple selection for widget appearances - with pluggable widgets
19
  * Translation of external plugins without a need for .po/.mo files
20
  * Automatic translation mode for all content (including comments!)
 
21
  * Automatic translation can be triggered on demand by the readers or on the server side
22
  * RSS feeds are translated too
23
  * Takes care of hidden elements, link tags and titles
24
  * Translated languages are searchable
25
- * Fine grained control for advanced users
26
 
27
  ***Our goals:***
28
 
@@ -159,6 +160,8 @@ images based on the current language
159
  5. Widget style selection box, with three basic appearances, flags below (in Hebrew), language selection on the top right and language list on the bottom right.
160
 
161
  == Upgrade Notice ==
 
 
162
  = 0.5.7 =
163
  Fix for critical bug in 0.5.6
164
  = 0.5.6 =
@@ -183,6 +186,16 @@ This version provides integration with google-sitemaps-xml and wp-super-cache
183
  This version allows sorting of languages within the widget
184
 
185
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
186
  = 2010/07/11 - 0.5.7 =
187
  * Fix for critical bug in widget inclusion (thanks [dgrut](http://www.buyacomputer.info/))
188
  = 2010/07/11 - 0.5.6 =
@@ -323,7 +336,7 @@ This version allows sorting of languages within the widget
323
  * Fixed IE8 hover quirk in flags widget
324
  * Avoid translating admin pages (even if we can)
325
  = 2009/05/25 - 0.2.2 =
326
- * Fixed wrong handling of multy-byte chars as terminators (middle dots) which caused a regression bug
327
  = 2009/05/21 - 0.2.1 =
328
  * Fixed unique breaking case in parser (style used within script and not properly terminated) (thanks again Fernanda)
329
  * Added language list mode to widget
2
  Contributors: oferwald
3
  Donate link: http://transposh.org/donate/
4
  Tags: translation, widget, filter, bilingual, multilingual, transposh, translate, language, crowdsourcing, context, wiki, RTL, Hebrew, Spanish, French, Russian, English, Arabic, Portuguese
5
+ Requires at least: 2.8
6
+ Tested up to: 3.0.1
7
+ Stable tag: 0.6.0
8
 
9
  Transposh filter allows in context quick translation of websites, it allows you to crowd-source the translation to your users
10
 
18
  * Multiple selection for widget appearances - with pluggable widgets
19
  * Translation of external plugins without a need for .po/.mo files
20
  * Automatic translation mode for all content (including comments!)
21
+ * Use either Google Translate or MS Translate backends - 57 languages supported!
22
  * Automatic translation can be triggered on demand by the readers or on the server side
23
  * RSS feeds are translated too
24
  * Takes care of hidden elements, link tags and titles
25
  * Translated languages are searchable
26
+ * Buddypress integration
27
 
28
  ***Our goals:***
29
 
160
  5. Widget style selection box, with three basic appearances, flags below (in Hebrew), language selection on the top right and language list on the bottom right.
161
 
162
  == Upgrade Notice ==
163
+ = 0.6.0 =
164
+ Much improved translation interface engine
165
  = 0.5.7 =
166
  Fix for critical bug in 0.5.6
167
  = 0.5.6 =
186
  This version allows sorting of languages within the widget
187
 
188
  == Changelog ==
189
+ = 2010/07/29 - 0.6.0 =
190
+ * Support batch translate which makes translations faster
191
+ * No longer needs to load extra scripts for translations resulting in faster page loads
192
+ * MSN (bing) translator no longer requires a key, just enable this at will
193
+ * Transposh Google Proxy is now included to enable translation for Alpha level languages from Google (5 new languages supported)
194
+ * Allow removing of Transposh logo and backlink according to [terms](http://transposh.org/logoterms)
195
+ * Translate all now uses batch interface for faster operation, and may use both backends
196
+ * Translate all will not try to handle non-translatable languages (such as ones added manually)
197
+ * Fixed typo in settings page (thanks Rogelio)
198
+ * Fixed comment posting bounce to original language (thanks Marko)
199
  = 2010/07/11 - 0.5.7 =
200
  * Fix for critical bug in widget inclusion (thanks [dgrut](http://www.buyacomputer.info/))
201
  = 2010/07/11 - 0.5.6 =
336
  * Fixed IE8 hover quirk in flags widget
337
  * Avoid translating admin pages (even if we can)
338
  = 2009/05/25 - 0.2.2 =
339
+ * Fixed wrong handling of multi-byte chars as terminators (middle dots) which caused a regression bug
340
  = 2009/05/21 - 0.2.1 =
341
  * Fixed unique breaking case in parser (style used within script and not properly terminated) (thanks again Fernanda)
342
  * Added language list mode to widget
transposh.php CHANGED
@@ -5,7 +5,7 @@
5
  Plugin URI: http://transposh.org/
6
  Description: Translation filter for WordPress, After enabling please set languages at the <a href="options-general.php?page=transposh">the options page</a> Want to help? visit our development site at <a href="http://trac.transposh.org/">trac.transposh.org</a>.
7
  Author: Team Transposh
8
- Version: 0.5.7
9
  Author URI: http://transposh.org/
10
  License: GPL (http://www.gnu.org/licenses/gpl.txt)
11
  */
@@ -119,7 +119,8 @@ class transposh_plugin {
119
  if ($this->options->get_enable_url_translate()) {
120
  add_filter('request', array(&$this, 'request_filter'));
121
  }
122
- add_filter('comment_text', array(&$this, 'comment_text_wrap'), 9999); // this is a late filter...
 
123
  add_filter('bp_uri', array(&$this, 'bp_uri_filter')); // buddypress compatability
124
  add_action('init', array(&$this, 'on_init'), 0); // really high priority
125
  add_action('parse_request', array(&$this, 'on_parse_request'));
@@ -185,6 +186,7 @@ class transposh_plugin {
185
  $parse->default_lang = $this->options->is_default_language($this->target_language);
186
  $parse->is_edit_mode = $this->edit_mode;
187
  $parse->is_auto_translate = $this->is_auto_translate_permitted();
 
188
  // TODO - check this!
189
  if (stripos($_SERVER['REQUEST_URI'], '/feed/') !== FALSE) {
190
 
@@ -508,17 +510,19 @@ class transposh_plugin {
508
  wp_localize_script('transposh', 't_jp', array(
509
  'post_url' => $this->post_url,
510
  'plugin_url' => $this->transposh_plugin_url,
511
- 'edit' => ($this->edit_mode ? '1' : ''),
512
  //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
513
  'lang' => $this->target_language,
 
514
  // those two options show if the script can support said engines
515
- 'msn' => (in_array($this->target_language, $GLOBALS['bing_languages']) && $this->options->get_msn_key() ? '1' : ''),
516
- 'google' => (in_array($this->target_language, $GLOBALS['google_languages']) ? '1' : ''),
 
517
  'prefix' => SPAN_PREFIX,
518
- 'msnkey' => $this->options->get_msn_key(),
519
  'preferred' => $this->options->get_preferred_translator(),
520
- 'progress' => $this->edit_mode || $this->options->get_widget_progressbar() ? '1' : '')
521
- // 'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
522
  );
523
 
524
  }
@@ -716,6 +720,20 @@ class transposh_plugin {
716
  add_comment_meta($post_id, 'tp_language', get_language_from_url($_SERVER['HTTP_REFERER'], $this->home_url), true);
717
  }
718
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  /**
720
  * This filter method helps buddypress understand the transposh generated URLs
721
  * @param string $uri The url that was originally received
5
  Plugin URI: http://transposh.org/
6
  Description: Translation filter for WordPress, After enabling please set languages at the <a href="options-general.php?page=transposh">the options page</a> Want to help? visit our development site at <a href="http://trac.transposh.org/">trac.transposh.org</a>.
7
  Author: Team Transposh
8
+ Version: 0.6.0
9
  Author URI: http://transposh.org/
10
  License: GPL (http://www.gnu.org/licenses/gpl.txt)
11
  */
119
  if ($this->options->get_enable_url_translate()) {
120
  add_filter('request', array(&$this, 'request_filter'));
121
  }
122
+ add_filter('comment_post_redirect', array(&$this, 'comment_post_redirect_filter'));
123
+ add_filter('comment_text', array(&$this, 'comment_text_wrap'), 9999); // this is a late filter...
124
  add_filter('bp_uri', array(&$this, 'bp_uri_filter')); // buddypress compatability
125
  add_action('init', array(&$this, 'on_init'), 0); // really high priority
126
  add_action('parse_request', array(&$this, 'on_parse_request'));
186
  $parse->default_lang = $this->options->is_default_language($this->target_language);
187
  $parse->is_edit_mode = $this->edit_mode;
188
  $parse->is_auto_translate = $this->is_auto_translate_permitted();
189
+ $parse->allow_ad = $this->options->get_widget_remove_logo();
190
  // TODO - check this!
191
  if (stripos($_SERVER['REQUEST_URI'], '/feed/') !== FALSE) {
192
 
510
  wp_localize_script('transposh', 't_jp', array(
511
  'post_url' => $this->post_url,
512
  'plugin_url' => $this->transposh_plugin_url,
513
+ 'edit' => ($this->edit_mode ? 1 : ''),
514
  //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
515
  'lang' => $this->target_language,
516
+ //TODO - orig language?
517
  // those two options show if the script can support said engines
518
+ 'msn' => (in_array($this->target_language, $GLOBALS['bing_languages']) ? 1 : ''),
519
+ 'google' => (in_array($this->target_language, $GLOBALS['google_languages']) ? 1 : ''),
520
+ 'tgp' => (function_exists('curl_init') && in_array($this->target_language, $GLOBALS['google_proxied_languages']) ? 1 : ''),
521
  'prefix' => SPAN_PREFIX,
522
+ //'msnkey' => $this->options->get_msn_key(),
523
  'preferred' => $this->options->get_preferred_translator(),
524
+ 'progress' => $this->edit_mode || $this->options->get_widget_progressbar() ? 1 : '')
525
+ // 'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
526
  );
527
 
528
  }
720
  add_comment_meta($post_id, 'tp_language', get_language_from_url($_SERVER['HTTP_REFERER'], $this->home_url), true);
721
  }
722
 
723
+ /**
724
+ * After a user adds a comment, makes sure he gets back to the proper language
725
+ * TODO - check the three other params
726
+ * @param string $url
727
+ * @return string fixed url
728
+ */
729
+ function comment_post_redirect_filter($url) {
730
+ $lang = get_language_from_url($_SERVER['HTTP_REFERER'], $this->home_url);
731
+ if ($lang) {
732
+ $url = rewrite_url_lang_param($url, $this->home_url, $this->enable_permalinks_rewrite, $lang, $this->edit_mode);
733
+ }
734
+ return $url;
735
+ }
736
+
737
  /**
738
  * This filter method helps buddypress understand the transposh generated URLs
739
  * @param string $uri The url that was originally received
wp/transposh_admin.php CHANGED
@@ -34,15 +34,15 @@ class transposh_plugin_admin {
34
 
35
  // constructor of class, PHP4 compatible construction for backward compatibility
36
  function transposh_plugin_admin(&$transposh) {
37
- $this->transposh = &$transposh;
38
- // add filter for WordPress 2.8 changed backend box system !
39
- add_filter('screen_layout_columns', array(&$this, 'on_screen_layout_columns'), 10, 2);
40
- // add some help
41
- add_filter('contextual_help_list', array(&$this, 'on_contextual_help'), 100, 2);
42
- // register callback for admin menu setup
43
- add_action('admin_menu', array(&$this, 'on_admin_menu'));
44
- // register the callback been used if options of page been submitted and needs to be processed
45
- add_action('admin_post_save_transposh', array(&$this, 'on_save_changes'));
46
  }
47
 
48
  /**
@@ -50,289 +50,291 @@ class transposh_plugin_admin {
50
  * Return either "checked" or ""
51
  */
52
  function can_translate($role_name) {
53
- if ($role_name != 'anonymous') {
54
- $role = $GLOBALS['wp_roles']->get_role($role_name);
55
- if (isset($role) && $role->has_cap(TRANSLATOR)) return 'checked="checked"';
56
- }
57
- else
58
- return ($this->transposh->options->get_anonymous_translation()) ? 'checked="checked"' : '';
 
59
  }
60
 
61
  /**
62
  * Handle newly posted admin options.
63
  */
64
  function update_admin_options() {
65
-
66
-
67
- $viewable_langs = array();
68
- $editable_langs = array();
69
-
70
- //update roles and capabilities
71
- foreach ($GLOBALS['wp_roles']->get_names() as $role_name => $something) {
72
- $role = $GLOBALS['wp_roles']->get_role($role_name);
73
- if ($_POST[$role_name] == "1") $role->add_cap(TRANSLATOR);
74
- else $role->remove_cap(TRANSLATOR);
75
- }
76
-
77
- // anonymous needs to be handled differently as it does not have a role
78
- $this->transposh->options->set_anonymous_translation($_POST['anonymous']);
79
-
80
- // first set the default language
81
- list ($langcode, $viewable, $translateable) = explode(",", $_POST['languages'][0]);
82
- $this->transposh->options->set_default_language($langcode);
83
- unset($_POST['languages'][0]);
84
-
85
- // update the list of supported/editable/sortable languages
86
-
87
- foreach ($_POST['languages'] as $code => $lang) {
88
- list ($langcode, $viewable, $translateable) = explode(",", $lang);
89
- $sorted_langs[$langcode] = $langcode;
90
- if ($viewable) {
91
- $viewable_langs[$langcode] = $langcode;
92
- // force that every viewable lang is editable
93
- $editable_langs[$langcode] = $langcode;
94
- }
95
-
96
- if ($translateable) {
97
- $editable_langs[$langcode] = $langcode;
98
- }
99
- }
100
-
101
- $this->transposh->options->set_viewable_langs(implode(',', $viewable_langs));
102
- $this->transposh->options->set_editable_langs(implode(',', $editable_langs));
103
- $this->transposh->options->set_sorted_langs(implode(',', $sorted_langs));
104
-
105
- if ($this->transposh->options->get_enable_permalinks() != $_POST[ENABLE_PERMALINKS]) {
106
- $this->transposh->options->set_enable_permalinks($_POST[ENABLE_PERMALINKS]);
107
- // rewrite rules - refresh. - because we want them set or unset upon this change
108
- add_filter('rewrite_rules_array', 'update_rewrite_rules');
109
- $GLOBALS['wp_rewrite']->flush_rules();
110
- }
111
-
112
- $this->transposh->options->set_enable_footer_scripts($_POST[ENABLE_FOOTER_SCRIPTS]);
113
- $this->transposh->options->set_enable_detect_language($_POST[ENABLE_DETECT_LANG_AND_REDIRECT]);
114
- $this->transposh->options->set_enable_auto_translate($_POST[ENABLE_AUTO_TRANSLATE]);
115
- $this->transposh->options->set_enable_auto_post_translate($_POST[ENABLE_AUTO_POST_TRANSLATE]);
116
- $this->transposh->options->set_enable_default_translate($_POST[ENABLE_DEFAULT_TRANSLATE]);
117
- $this->transposh->options->set_enable_search_translate($_POST[ENABLE_SEARCH_TRANSLATE]);
118
- $this->transposh->options->set_enable_url_translate($_POST[ENABLE_URL_TRANSLATE]);
119
- $this->transposh->options->set_enable_msn_translate($_POST[ENABLE_MSN_TRANSLATE]);
120
- $this->transposh->options->set_preferred_translator($_POST[PREFERRED_TRANSLATOR]);
121
- $this->transposh->options->set_msn_key($_POST[MSN_TRANSLATE_KEY]);
122
- $this->transposh->options->set_transposh_key($_POST[TRANSPOSH_KEY]);
123
-
124
- // handle change of schedule for backup to daily
125
- if ($_POST[TRANSPOSH_BACKUP_SCHEDULE] != $this->transposh->options->get_transposh_backup_schedule()) {
126
- wp_clear_scheduled_hook('transposh_backup_event');
127
- if ($_POST[TRANSPOSH_BACKUP_SCHEDULE] == 1)
128
- wp_schedule_event(time(), 'daily', 'transposh_backup_event');
129
- }
130
- $this->transposh->options->set_transposh_backup_schedule($_POST[TRANSPOSH_BACKUP_SCHEDULE]);
131
-
132
- $this->transposh->options->update_options();
133
  }
134
 
135
  // for WordPress 2.8 we have to tell, that we support 2 columns !
136
  function on_screen_layout_columns($columns, $screen) {
137
- if ($screen == $this->pagehook) {
138
- $columns[$this->pagehook] = 2;
139
- }
140
- return $columns;
141
  }
142
 
143
  //add some help
144
  function on_contextual_help($filterVal, $screen) {
145
- if ($screen == 'settings_page_transposh') {
146
- $filterVal['settings_page_transposh'] = '<p>Transposh makes your blog translatable</p>' .
147
- '<a href="http://transposh.org/">Plugin homepage</a><br/>' .
148
- '<a href="http://transposh.org/faq/">Frequently asked questions</a>';
149
- }
150
- return $filterVal;
151
  }
152
 
153
  // extend the admin menu
154
  function on_admin_menu() {
155
- //add our own option page, you can also add it to different sections or use your own one
156
- $this->pagehook = add_options_page('Transposh control center', 'Transposh', 'manage_options', TRANSPOSH_ADMIN_PAGE_NAME, array(&$this, 'on_show_page'));
157
- // register callback gets call prior your own page gets rendered
158
- add_action('load-' . $this->pagehook, array(&$this, 'on_load_page'));
159
  }
160
 
161
  // will be executed if wordpress core detects this page has to be rendered
162
  function on_load_page() {
163
- //ensure, that the needed javascripts been loaded to allow drag/drop, expand/collapse and hide/show of boxes
164
- wp_enqueue_script('common');
165
- wp_enqueue_script('wp-lists');
166
- wp_enqueue_script('postbox');
167
 
168
- //TODO - make up my mind on using .css flags here (currently no)
169
- //if ($this->transposh->options->get_widget_css_flags())
170
  // wp_enqueue_style("transposh_flags",$this->transposh->transposh_plugin_url."/widgets/flags/tpw_flags.css",array(),TRANSPOSH_PLUGIN_VER);
171
- wp_enqueue_script('jquery-ui-droppable');
172
- wp_enqueue_script('transposh_control', $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_JS . '/transposhcontrol.js', array(), TRANSPOSH_PLUGIN_VER, true);
173
- wp_localize_script('transposh_control', 't_jp', array(
174
- 'post_url' => $this->transposh->post_url/* ,
175
- 'plugin_url' => $this->transposh_plugin_url,
176
- 'edit' => ($this->edit_mode? '1' : ''),
177
- //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
178
- 'lang' => $this->target_language,
179
- // those two options show if the script can support said engines
180
- 'msn' => (in_array($this->target_language,$GLOBALS['bing_languages']) && $this->options->get_msn_key() ? '1' : ''),
181
- 'google' => (in_array($this->target_language,$GLOBALS['google_languages']) ? '1' : ''),
182
- 'prefix' => SPAN_PREFIX,
183
- 'msnkey'=>$this->options->get_msn_key(),
184
- 'preferred'=> $this->options->get_preferred_translator(),
185
- 'progress'=>$this->edit_mode || $this->options->get_widget_progressbar() ? '1' : '') */
186
- // 'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
187
- ));
188
- wp_enqueue_script('google', "http://www.google.com/jsapi", array(), '1', true);
189
- wp_enqueue_script('transposh_admin', $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_JS . '/transposhadmin.js', array(), TRANSPOSH_PLUGIN_VER, true);
190
- wp_enqueue_style('jquery', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css', array(), '1.0');
191
- wp_enqueue_script('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js', array('jquery'), '1.7.2', true);
192
-
193
-
194
- //add several metaboxes now, all metaboxes registered during load page can be switched off/on at "Screen Options" automatically, nothing special to do therefore
195
- add_meta_box('transposh-sidebox-about', 'About this plugin', array(&$this, 'on_sidebox_about_content'), $this->pagehook, 'side', 'core');
196
- add_meta_box('transposh-sidebox-widget', 'Widget settings', array(&$this, 'on_sidebox_widget_content'), $this->pagehook, 'side', 'core');
197
- add_meta_box('transposh-sidebox-news', 'Plugin news', array(&$this, 'on_sidebox_news_content'), $this->pagehook, 'side', 'core');
198
- add_meta_box('transposh-sidebox-stats', 'Plugin stats', array(&$this, 'on_sidebox_stats_content'), $this->pagehook, 'side', 'core');
199
- add_meta_box('transposh-sidebox-translate', 'Translate all', array(&$this, 'on_sidebox_translate_content'), $this->pagehook, 'side', 'core');
200
- add_meta_box('transposh-contentbox-languages', 'Supported languages', array(&$this, 'on_contentbox_languages_content'), $this->pagehook, 'normal', 'core');
201
- add_meta_box('transposh-contentbox-translation', 'Translation settings', array(&$this, 'on_contentbox_translation_content'), $this->pagehook, 'normal', 'core');
202
- add_meta_box('transposh-contentbox-autotranslation', 'Automatic translation settings', array(&$this, 'on_contentbox_auto_translation_content'), $this->pagehook, 'normal', 'core');
203
- add_meta_box('transposh-contentbox-general', 'Generic settings', array(&$this, 'on_contentbox_generic_content'), $this->pagehook, 'normal', 'core');
 
 
 
204
  }
205
 
206
  //executed to show the plugins complete admin page
207
  function on_show_page() {
208
- //we need the global screen column value to beable to have a sidebar in WordPress 2.8
209
- //global $screen_layout_columns;
210
- //add a 3rd content box now for demonstration purpose, boxes added at start of page rendering can't be switched on/off,
211
- //may be needed to ensure that a special box is always available
212
- add_meta_box('transposh-contentbox-community', 'Transposh community features', array(&$this, 'on_contentbox_community_content'), $this->pagehook, 'normal', 'core');
213
- //define some data can be given to each metabox during rendering - not used now
214
- //$data = array('My Data 1', 'My Data 2', 'Available Data 1');
215
-
216
- echo '<div id="transposh-general" class="wrap">';
217
- screen_icon('options-general');
218
-
219
- echo '<h2>Transposh</h2>' .
220
- '<form action="admin-post.php" method="post">';
221
-
222
- wp_nonce_field(TR_NONCE);
223
- wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
224
- wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
225
-
226
- echo '<input type="hidden" name="action" value="save_transposh" />' .
227
- '<div id="poststuff" class="metabox-holder' . ((2 == $GLOBALS['screen_layout_columns']) ? ' has-right-sidebar' : '') . '">' .
228
- '<div id="side-info-column" class="inner-sidebar">';
229
- do_meta_boxes($this->pagehook, 'side', '');
230
-
231
- echo '</div>' .
232
- '<div id="post-body" class="has-sidebar">' .
233
- '<div id="post-body-content" class="has-sidebar-content"> ';
234
-
235
- do_meta_boxes($this->pagehook, 'normal', '');
236
- /* Maybe add static content here later */
237
- //do_meta_boxes($this->pagehook, 'additional', $data);
238
-
239
- echo '<p>' .
240
- '<input type="submit" value="Save Changes" class="button-primary" name="Submit"/>' .
241
- '</p>' .
242
- '</div>' .
243
- '</div>' .
244
- '<br class="clear"/>' .
245
- '</div>' .
246
- '</form>' .
247
- '</div>' .
248
- '<script type="text/javascript">' . "\n" .
249
- '//<![CDATA[' . "\n" .
250
- 'jQuery(document).ready( function($) {';
251
- // close postboxes that should be closed
252
- echo "$('.if-js-closed').removeClass('if-js-closed').addClass('closed');";
253
- // postboxes setup
254
- echo "postboxes.add_postbox_toggles('" . $this->pagehook . "');" .
255
- '}); ' . "\n" .
256
- '//]]>' . "\n" .
257
- '</script>';
258
  }
259
 
260
  // executed if the post arrives initiated by pressing the submit button of form
261
  function on_save_changes() {
262
- //user permission check
263
- if (!current_user_can('manage_options')) wp_die(__('Problems?'));
264
- // cross check the given referer
265
- check_admin_referer(TR_NONCE);
266
 
267
- // process here your on $_POST validation and / or option saving
268
- $this->transposh->widget->transposh_widget_post(FALSE);
269
- $this->update_admin_options();
270
 
271
- // lets redirect the post request into get request (you may add additional params at the url, if you need to show save results
272
- wp_redirect($_POST['_wp_http_referer']);
273
  }
274
 
275
  // below you will find for each registered metabox the callback method, that produces the content inside the boxes
276
  // i did not describe each callback dedicated, what they do can be easily inspected and compare with the admin page displayed
277
 
278
  function on_sidebox_about_content($data) {
279
- echo '<ul style="list-style-type:disc;margin-left:20px;">';
280
- echo '<li><a href="http://transposh.org/">Plugin Homepage</a></li>';
281
- echo '<li><a href="http://transposh.org/redir/newfeature">Suggest a Feature</a></li>';
282
- // support Forum
283
- echo '<li><a href="http://transposh.org/redir/newticket">Report a Bug</a></li>';
284
- // donate with PayPal
285
- echo '</ul>';
286
  }
287
 
288
  function on_sidebox_widget_content($data) {
289
- $this->transposh->widget->transposh_widget_control();
290
  }
291
 
292
  function on_sidebox_news_content($data) {
293
- require_once(ABSPATH . WPINC . '/rss.php');
294
-
295
- // ugly hack copy of RSS because of Unicode chars misprinting
296
- function wp_rss2($url, $num_items = -1) {
297
- if ($rss = fetch_rss($url)) {
298
- echo '<ul>';
299
-
300
- if ($num_items !== -1) {
301
- $rss->items = array_slice($rss->items, 0, $num_items);
302
- }
303
-
304
- foreach ((array) $rss->items as $item) {
305
- printf(
306
- '<li><a href="%1$s" title="%2$s">%3$s</a></li>',
307
- //esc_url( $item['link'] ),
308
- //esc_attr( strip_tags( $item['description'] ) ),
309
- // TODO - check Switched to 2.7 compatability functions
310
- clean_url($item['link']),
311
- attribute_escape(strip_tags($item['description'])),
312
- htmlentities($item['title'], ENT_COMPAT, 'UTF-8')
313
- );
314
- }
315
-
316
- echo '</ul>';
317
- } else {
318
- _e('An error has occurred, which probably means the feed is down. Try again later.');
319
- }
320
- }
321
-
322
- echo '<div style="margin:6px">';
323
- wp_rss2('http://feeds2.feedburner.com/transposh', 5);
324
- echo '</div>';
325
  }
326
 
327
  function on_sidebox_stats_content($data) {
328
- $this->transposh->database->db_stats();
329
  }
330
 
331
  function on_sidebox_translate_content($data) {
332
- echo '<div id="progress_bar_all"></div><div id="tr_translate_title"></div>';
333
- echo '<div id="tr_loading" style="margin: 0 0 10px 0">Translate by clicking the button below</div>';
334
- echo '<a id="transposh-translate" href="' . $this->transposh->post_url . '?translate_all&offset=1" onclick="return false;" class="button">Translate All Now</a><br/>';
335
- //get_posts
336
  }
337
 
338
  /**
@@ -340,8 +342,8 @@ class transposh_plugin_admin {
340
  * @param string $data
341
  */
342
  function on_contentbox_languages_content($data) {
343
- // we need some styles
344
- echo '<style type="text/css">
345
  #sortable { list-style-type: none; margin: 0; padding: 0; }
346
  #sortable li, #default_lang li { margin: 3px 3px 3px 0; padding: 5px; float: left; width: 190px; height: 14px;}
347
  .languages {
@@ -384,41 +386,41 @@ class transposh_plugin_admin {
384
  }
385
  </style>';
386
 
387
- // this is the default language location
388
- list ($langname, $langorigname, $flag) = explode(",", $GLOBALS['languages'][$this->transposh->options->get_default_language()]);
389
- echo '<div id="default_lang" style="overflow:auto;padding-bottom:10px;">Default Language (drag another language here to make it default)';
390
- echo '<ul id="default_list"><li id="' . $this->transposh->options->get_default_language() . '" class="languages">'
391
- . display_flag("{$this->transposh->transposh_plugin_url}/img/flags", $flag, $langorigname, false/* $this->transposh->options->get_widget_css_flags() */)
392
- . '<input type="hidden" name="languages[]" value="' . $this->transposh->options->get_default_language() . '" />'
393
- . '&nbsp;<span class="langname">' . $langorigname . '</span><span class="langname hidden">' . $langname . '</span></li>';
394
- echo '</ul></div>';
395
- // list of languages
396
- echo '<div style="overflow:auto; clear: both;">Available Languages (Click to toggle language state - Drag to sort in the widget)';
397
- echo '<ul id="sortable">';
398
- foreach ($this->transposh->options->get_sorted_langs() as $langcode => $langrecord) {
399
- list ($langname, $langorigname, $flag) = explode(",", $langrecord);
400
- echo '<li id="' . $langcode . '" class="languages ' . ($this->transposh->options->is_viewable_language($langcode) || $this->transposh->options->is_default_language($langcode) ? "active" : "")
401
- . (!$this->transposh->options->is_viewable_language($langcode) && $this->transposh->options->is_editable_language($langcode) ? "translateable" : "") . '"><div style="float:left">'
402
- . display_flag("{$this->transposh->transposh_plugin_url}/img/flags", $flag, false /* $langorigname,$this->transposh->options->get_widget_css_flags() */)
403
- . '<input type="hidden" name="languages[]" value="' . $langcode . ($this->transposh->options->is_viewable_language($langcode) ? ",v" : ",") . ($this->transposh->options->is_viewable_language($langcode) ? ",t" : ",") . '" />'
404
- . '&nbsp;<span class="langname">' . $langorigname . '</span><span class="langname hidden">' . $langname . '</span></div>';
405
- if (in_array($langcode, $GLOBALS['google_languages']))
406
- echo '<img width="16" height="16" alt="g" class="logoicon" title="Language supported by google translate" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/googleicon.png"/>';
407
- if (in_array($langcode, $GLOBALS['bing_languages']))
408
- echo '<img width="16" height="16" alt="b" class="logoicon" title="Language supported by bing translate" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/bingicon.png"/>';
409
- if (in_array($langcode, $GLOBALS['rtl_languages']))
410
- echo '<img width="16" height="16" alt="r" class="logoicon" title="Language is written from right to left" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/rtlicon.png"/>';
411
- echo '</li>';
412
- }
413
- echo "</ul></div>";
414
- // options to play with
415
- echo '<div style="clear: both;">Display options:<br/><ul style="list-style-type: disc; margin-left: 20px;font-size:11px">';
416
- echo '<li><a href="#" id="changename">Toggle names of languages between English and Original</a></li>';
417
- echo '<li><a href="#" id="selectall">Make all languages active</a></li>';
418
- echo '<li><a href="#" id="sortname">Sort by language name</a></li>';
419
- echo '<li><a href="#" id="sortiso">Sort by lSO code</a></li></ul>';
420
- echo 'Legend: Green - active, <span id="yellowcolor"' . ($this->transposh->options->get_anonymous_translation() ? ' class ="hidden"' : '') . '>Yellow - translateable (only translators will see this language), </span>blank - inactive';
421
- echo '</div>';
422
  }
423
 
424
  /**
@@ -427,130 +429,121 @@ class transposh_plugin_admin {
427
  * @return string used for checkboxes
428
  */
429
  private function checked($eval) {
430
- return $eval ? 'checked="checked"' : '';
431
  }
432
 
433
  function on_contentbox_translation_content($data) {
434
- /*
435
- * Insert permissions section in the admin page
436
- */
437
- echo '<h4>Who can translate ?</h4>';
438
- //display known roles and their permission to translate
439
- foreach ($GLOBALS['wp_roles']->get_names() as $role_name => $something) {
440
- echo '<input type="checkbox" value="1" name="' . $role_name . '" ' . $this->can_translate($role_name) .
441
- '/> ' . ucfirst($role_name) . '&nbsp;&nbsp;&nbsp;';
442
- }
443
- //Add our own custom role
444
- echo '<input id="tr_anon" type="checkbox" value="1" name="anonymous" ' . $this->can_translate('anonymous') . '/> Anonymous';
445
-
446
- /*
447
- * Insert the option to enable/disable default language translation.
448
- * Disabled by default.
449
- */
450
- echo '<h4>Enable default language translation</h4>';
451
- echo '<input type="checkbox" value="1" name="' . ENABLE_DEFAULT_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_default_translate()) . '/> ' .
452
- 'Allow translation of default language - useful for sites with more than one major language';
453
-
454
- /**
455
- * Insert the option to enable search in translated languages
456
- * Enabled by default.
457
- * @since 0.3.6
458
- */
459
- echo '<h4>Enable search in translated languages</h4>';
460
- echo '<input type="checkbox" value="1" name="' . ENABLE_SEARCH_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_search_translate()) . '/> ' .
461
- 'Allow search of translated languages, in those languages (and the original language)';
462
-
463
- /**
464
- * Insert the option to enable translation of urls
465
- * Disbaled by default.
466
- * @since 0.5.3
467
- */
468
- echo '<h4>Enable url translation (experimental)</h4>';
469
- echo '<input type="checkbox" value="1" name="' . ENABLE_URL_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_url_translate()) . '/> ' .
470
- 'Allow translation of permalinks and urls';
471
  }
472
 
473
  function on_contentbox_auto_translation_content($data) {
474
 
475
- /*
476
- * Insert the option to enable/disable automatic translation.
477
- * Enabled by default.
478
- */
479
- echo '<h4>Enable automatic translation</h4>';
480
- echo '<input type="checkbox" value="1" name="' . ENABLE_AUTO_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_auto_translate()) . '/> ' .
481
- 'Allow automatic translation of pages';
482
-
483
- /**
484
- * Insert the option to enable/disable automatic translation upon publishing.
485
- * Disabled by default.
486
- * @since 0.3.5 */
487
- echo '<h4>New - Enable automatic translation after posting</h4>';
488
- echo '<input type="checkbox" value="1" name="' . ENABLE_AUTO_POST_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_auto_post_translate()) . '/> ' .
489
- 'Do automatic translation immediately after a post has been published';
490
-
491
- /*
492
- * Insert the option to enable/disable msn translations.
493
- * Disabled by default because an API key is needed.
494
- */
495
- echo '<h4>Support for Bing (MSN) translation</h4>';
496
- echo '<input type="checkbox" value="1" name="' . ENABLE_MSN_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_msn_translate()) . '/> ' .
497
- 'Support MSN (Bing) translator (get key from <a href="http://www.microsofttranslator.com/Dev/Ajax/Default.aspx">here</a>)<br/>' .
498
- 'Key: <input type="text" size="35" class="regular-text" value="' . $this->transposh->options->get_msn_key() . '" id="' . MSN_TRANSLATE_KEY . '" name="' . MSN_TRANSLATE_KEY . '"/>';
499
-
500
- /*
501
- * TODO - Change to v2 API and our key...
502
- */
503
- echo '<h4>Select preferred auto translation engine</h4>';
504
- echo '<label for="' . PREFERRED_TRANSLATOR . '">Translation engine:' .
505
- '<select name="' . PREFERRED_TRANSLATOR . '">' .
506
- '<option value="1"' . ($this->transposh->options->get_preferred_translator() == 1 ? ' selected="selected"' : '') . '>Google</option>' .
507
- '<option value="2"' . ($this->transposh->options->get_preferred_translator() == 2 ? ' selected="selected"' : '') . '>Bing</option>' .
508
- '</select>' .
509
- '</label>';
510
  }
511
 
512
  function on_contentbox_generic_content($data) {
513
- /*
514
- * Insert the option to enable/disable rewrite of perlmalinks.
515
- * When disabled only parameters will be used to identify the current language.
516
- */
517
- echo '<h4>Rewrite URLs</h4>';
518
- echo '<input type="checkbox" value="1" name="' . ENABLE_PERMALINKS . '" ' . $this->checked($this->transposh->options->get_enable_permalinks()) . '/> ' .
519
- 'Rewrite URLs to be search engine friendly, ' .
520
- 'e.g. (http://wordpress.org/<strong>en</strong>). ' .
521
- 'Requires that permalinks will be enabled.';
522
-
523
- /*
524
- * Insert the option to enable/disable pushing of scripts to footer.
525
- * Works on wordpress 2.8 and up
526
- */
527
- if (floatval($GLOBALS['wp_version']) >= 2.8) {
528
- echo '<h4>Add scripts to footer</h4>';
529
- echo '<input type="checkbox" value="1" name="' . ENABLE_FOOTER_SCRIPTS . '" ' . $this->checked($this->transposh->options->get_enable_footer_scripts()) . '/> ' .
530
- 'Push transposh scripts to footer of page instead of header, makes pages load faster. ' .
531
- 'Requires that your theme should have proper footer support.';
532
- }
533
-
534
- /**
535
- * Insert the option to enable/disable language auto-detection
536
- * @since 0.3.8 */
537
- echo '<h4>Auto detect language for users</h4>';
538
- echo '<input type="checkbox" value="1" name="' . ENABLE_DETECT_LANG_AND_REDIRECT . '" ' . $this->checked($this->transposh->options->get_enable_detect_language()) . '/> ' .
539
- 'This enables auto detection of language used by the user as defined in the ACCEPT_LANGUAGES they send. ' .
540
- 'This will redirect the first page accessed in the session to the same page with the detected language.';
541
-
542
- /* WIP2
543
- echo '<a href="http://transposh.org/services/index.php?flags='.$flags.'">Gen sprites</a>'; */
544
  }
545
 
546
  function on_contentbox_community_content($data) {
547
- echo '<h4>Backup service for human translation</h4>';
548
- echo '<input type="radio" value="1" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 1) . '/>Enable daily backup<br/>';
549
- echo '<input type="radio" value="2" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 2) . '/>Enable live backup<br/>';
550
- echo '<input type="radio" value="0" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 0) . '/>Disable backup (Can be run manually by clicking the button below)<br/>';
551
- echo 'Service Key: <input type="text" size="32" class="regular-text" value="' . $this->transposh->options->get_transposh_key() . '" id="' . TRANSPOSH_KEY . '" name="' . TRANSPOSH_KEY . '"/> <a target="_blank" href="http://transposh.org/faq/#restore">How to restore?</a><br/>';
552
- echo '<div id="backup_result"></div>';
553
- echo '<div style="margin:10px 0"><a id="transposh-backup" href="#" class="button">Do Backup Now</a></div>';
554
  }
555
 
556
  }
34
 
35
  // constructor of class, PHP4 compatible construction for backward compatibility
36
  function transposh_plugin_admin(&$transposh) {
37
+ $this->transposh = &$transposh;
38
+ // add filter for WordPress 2.8 changed backend box system !
39
+ add_filter('screen_layout_columns', array(&$this, 'on_screen_layout_columns'), 10, 2);
40
+ // add some help
41
+ add_filter('contextual_help_list', array(&$this, 'on_contextual_help'), 100, 2);
42
+ // register callback for admin menu setup
43
+ add_action('admin_menu', array(&$this, 'on_admin_menu'));
44
+ // register the callback been used if options of page been submitted and needs to be processed
45
+ add_action('admin_post_save_transposh', array(&$this, 'on_save_changes'));
46
  }
47
 
48
  /**
50
  * Return either "checked" or ""
51
  */
52
  function can_translate($role_name) {
53
+ if ($role_name != 'anonymous') {
54
+ $role = $GLOBALS['wp_roles']->get_role($role_name);
55
+ if (isset($role) && $role->has_cap(TRANSLATOR))
56
+ return 'checked="checked"';
57
+ }
58
+ else
59
+ return ($this->transposh->options->get_anonymous_translation()) ? 'checked="checked"' : '';
60
  }
61
 
62
  /**
63
  * Handle newly posted admin options.
64
  */
65
  function update_admin_options() {
66
+
67
+
68
+ $viewable_langs = array();
69
+ $editable_langs = array();
70
+
71
+ //update roles and capabilities
72
+ foreach ($GLOBALS['wp_roles']->get_names() as $role_name => $something) {
73
+ $role = $GLOBALS['wp_roles']->get_role($role_name);
74
+ if ($_POST[$role_name] == "1") $role->add_cap(TRANSLATOR);
75
+ else $role->remove_cap(TRANSLATOR);
76
+ }
77
+
78
+ // anonymous needs to be handled differently as it does not have a role
79
+ $this->transposh->options->set_anonymous_translation($_POST['anonymous']);
80
+
81
+ // first set the default language
82
+ list ($langcode, $viewable, $translateable) = explode(",", $_POST['languages'][0]);
83
+ $this->transposh->options->set_default_language($langcode);
84
+ unset($_POST['languages'][0]);
85
+
86
+ // update the list of supported/editable/sortable languages
87
+
88
+ foreach ($_POST['languages'] as $code => $lang) {
89
+ list ($langcode, $viewable, $translateable) = explode(",", $lang);
90
+ $sorted_langs[$langcode] = $langcode;
91
+ if ($viewable) {
92
+ $viewable_langs[$langcode] = $langcode;
93
+ // force that every viewable lang is editable
94
+ $editable_langs[$langcode] = $langcode;
95
+ }
96
+
97
+ if ($translateable) {
98
+ $editable_langs[$langcode] = $langcode;
99
+ }
100
+ }
101
+
102
+ $this->transposh->options->set_viewable_langs(implode(',', $viewable_langs));
103
+ $this->transposh->options->set_editable_langs(implode(',', $editable_langs));
104
+ $this->transposh->options->set_sorted_langs(implode(',', $sorted_langs));
105
+
106
+ if ($this->transposh->options->get_enable_permalinks() != $_POST[ENABLE_PERMALINKS]) {
107
+ $this->transposh->options->set_enable_permalinks($_POST[ENABLE_PERMALINKS]);
108
+ // rewrite rules - refresh. - because we want them set or unset upon this change
109
+ add_filter('rewrite_rules_array', 'update_rewrite_rules');
110
+ $GLOBALS['wp_rewrite']->flush_rules();
111
+ }
112
+
113
+ $this->transposh->options->set_enable_footer_scripts($_POST[ENABLE_FOOTER_SCRIPTS]);
114
+ $this->transposh->options->set_enable_detect_language($_POST[ENABLE_DETECT_LANG_AND_REDIRECT]);
115
+ $this->transposh->options->set_enable_auto_translate($_POST[ENABLE_AUTO_TRANSLATE]);
116
+ $this->transposh->options->set_enable_auto_post_translate($_POST[ENABLE_AUTO_POST_TRANSLATE]);
117
+ $this->transposh->options->set_enable_default_translate($_POST[ENABLE_DEFAULT_TRANSLATE]);
118
+ $this->transposh->options->set_enable_search_translate($_POST[ENABLE_SEARCH_TRANSLATE]);
119
+ $this->transposh->options->set_enable_url_translate($_POST[ENABLE_URL_TRANSLATE]);
120
+ $this->transposh->options->set_preferred_translator($_POST[PREFERRED_TRANSLATOR]);
121
+ $this->transposh->options->set_transposh_key($_POST[TRANSPOSH_KEY]);
122
+
123
+ // handle change of schedule for backup to daily
124
+ if ($_POST[TRANSPOSH_BACKUP_SCHEDULE] != $this->transposh->options->get_transposh_backup_schedule()) {
125
+ wp_clear_scheduled_hook('transposh_backup_event');
126
+ if ($_POST[TRANSPOSH_BACKUP_SCHEDULE] == 1)
127
+ wp_schedule_event(time(), 'daily', 'transposh_backup_event');
128
+ }
129
+ $this->transposh->options->set_transposh_backup_schedule($_POST[TRANSPOSH_BACKUP_SCHEDULE]);
130
+
131
+ $this->transposh->options->update_options();
 
 
132
  }
133
 
134
  // for WordPress 2.8 we have to tell, that we support 2 columns !
135
  function on_screen_layout_columns($columns, $screen) {
136
+ if ($screen == $this->pagehook) {
137
+ $columns[$this->pagehook] = 2;
138
+ }
139
+ return $columns;
140
  }
141
 
142
  //add some help
143
  function on_contextual_help($filterVal, $screen) {
144
+ if ($screen == 'settings_page_transposh') {
145
+ $filterVal['settings_page_transposh'] = '<p>Transposh makes your blog translatable</p>' .
146
+ '<a href="http://transposh.org/">Plugin homepage</a><br/>' .
147
+ '<a href="http://transposh.org/faq/">Frequently asked questions</a>';
148
+ }
149
+ return $filterVal;
150
  }
151
 
152
  // extend the admin menu
153
  function on_admin_menu() {
154
+ //add our own option page, you can also add it to different sections or use your own one
155
+ $this->pagehook = add_options_page('Transposh control center', 'Transposh', 'manage_options', TRANSPOSH_ADMIN_PAGE_NAME, array(&$this, 'on_show_page'));
156
+ // register callback gets call prior your own page gets rendered
157
+ add_action('load-' . $this->pagehook, array(&$this, 'on_load_page'));
158
  }
159
 
160
  // will be executed if wordpress core detects this page has to be rendered
161
  function on_load_page() {
162
+ //ensure, that the needed javascripts been loaded to allow drag/drop, expand/collapse and hide/show of boxes
163
+ wp_enqueue_script('common');
164
+ wp_enqueue_script('wp-lists');
165
+ wp_enqueue_script('postbox');
166
 
167
+ //TODO - make up my mind on using .css flags here (currently no)
168
+ //if ($this->transposh->options->get_widget_css_flags())
169
  // wp_enqueue_style("transposh_flags",$this->transposh->transposh_plugin_url."/widgets/flags/tpw_flags.css",array(),TRANSPOSH_PLUGIN_VER);
170
+ wp_enqueue_script('jquery-ui-droppable');
171
+ wp_enqueue_script('transposh_control', $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_JS . '/transposhcontrol.js', array(), TRANSPOSH_PLUGIN_VER, true);
172
+ wp_localize_script('transposh_control', 't_jp', array(
173
+ 'post_url' => $this->transposh->post_url,
174
+ //'msn_langs' => json_encode($GLOBALS['bing_languages']),
175
+ //'google_lang' => json_encode($GLOBALS['google_languages']),
176
+ 'preferred' => $this->transposh->options->get_preferred_translator(),
177
+ 'l10n_print_after' => 't_jp.g_langs = ' . json_encode($GLOBALS['google_languages']) . '; t_jp.m_langs = ' . json_encode($GLOBALS['bing_languages']) . ';'/*
178
+ /* ,
179
+ 'plugin_url' => $this->transposh_plugin_url,
180
+ 'edit' => ($this->edit_mode? '1' : ''),
181
+ //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
182
+ 'lang' => $this->target_language,
183
+ // those two options show if the script can support said engines
184
+ 'prefix' => SPAN_PREFIX,
185
+ 'preferred'=> $this->options->get_preferred_translator(),
186
+ 'progress'=>$this->edit_mode || $this->options->get_widget_progressbar() ? '1' : '') */
187
+ // ,'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
188
+ // need to do this because the way wordpress encodes stuff
189
+ ));
190
+ wp_enqueue_script('google', "http://www.google.com/jsapi", array(), '1', true);
191
+ wp_enqueue_script('transposh_admin', $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_JS . '/transposhadmin.js', array(), TRANSPOSH_PLUGIN_VER, true);
192
+ wp_enqueue_style('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/ui-lightness/jquery-ui.css', array(), '1.8.2');
193
+ wp_enqueue_script('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js', array('jquery'), '1.8.2', true);
194
+
195
+
196
+ //add several metaboxes now, all metaboxes registered during load page can be switched off/on at "Screen Options" automatically, nothing special to do therefore
197
+ add_meta_box('transposh-sidebox-about', 'About this plugin', array(&$this, 'on_sidebox_about_content'), $this->pagehook, 'side', 'core');
198
+ add_meta_box('transposh-sidebox-widget', 'Widget settings', array(&$this, 'on_sidebox_widget_content'), $this->pagehook, 'side', 'core');
199
+ add_meta_box('transposh-sidebox-news', 'Plugin news', array(&$this, 'on_sidebox_news_content'), $this->pagehook, 'side', 'core');
200
+ add_meta_box('transposh-sidebox-stats', 'Plugin stats', array(&$this, 'on_sidebox_stats_content'), $this->pagehook, 'side', 'core');
201
+ add_meta_box('transposh-sidebox-translate', 'Translate all', array(&$this, 'on_sidebox_translate_content'), $this->pagehook, 'side', 'core');
202
+ add_meta_box('transposh-contentbox-languages', 'Supported languages', array(&$this, 'on_contentbox_languages_content'), $this->pagehook, 'normal', 'core');
203
+ add_meta_box('transposh-contentbox-translation', 'Translation settings', array(&$this, 'on_contentbox_translation_content'), $this->pagehook, 'normal', 'core');
204
+ add_meta_box('transposh-contentbox-autotranslation', 'Automatic translation settings', array(&$this, 'on_contentbox_auto_translation_content'), $this->pagehook, 'normal', 'core');
205
+ add_meta_box('transposh-contentbox-general', 'Generic settings', array(&$this, 'on_contentbox_generic_content'), $this->pagehook, 'normal', 'core');
206
  }
207
 
208
  //executed to show the plugins complete admin page
209
  function on_show_page() {
210
+ //we need the global screen column value to beable to have a sidebar in WordPress 2.8
211
+ //global $screen_layout_columns;
212
+ //add a 3rd content box now for demonstration purpose, boxes added at start of page rendering can't be switched on/off,
213
+ //may be needed to ensure that a special box is always available
214
+ add_meta_box('transposh-contentbox-community', 'Transposh community features', array(&$this, 'on_contentbox_community_content'), $this->pagehook, 'normal', 'core');
215
+ //define some data can be given to each metabox during rendering - not used now
216
+ //$data = array('My Data 1', 'My Data 2', 'Available Data 1');
217
+
218
+ echo '<div id="transposh-general" class="wrap">';
219
+ screen_icon('options-general');
220
+
221
+ echo '<h2>Transposh</h2>' .
222
+ '<form action="admin-post.php" method="post">';
223
+
224
+ wp_nonce_field(TR_NONCE);
225
+ wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
226
+ wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
227
+
228
+ echo '<input type="hidden" name="action" value="save_transposh" />' .
229
+ '<div id="poststuff" class="metabox-holder' . ((2 == $GLOBALS['screen_layout_columns']) ? ' has-right-sidebar' : '') . '">' .
230
+ '<div id="side-info-column" class="inner-sidebar">';
231
+ do_meta_boxes($this->pagehook, 'side', '');
232
+
233
+ echo '</div>' .
234
+ '<div id="post-body" class="has-sidebar">' .
235
+ '<div id="post-body-content" class="has-sidebar-content"> ';
236
+
237
+ do_meta_boxes($this->pagehook, 'normal', '');
238
+ /* Maybe add static content here later */
239
+ //do_meta_boxes($this->pagehook, 'additional', $data);
240
+
241
+ echo '<p>' .
242
+ '<input type="submit" value="Save Changes" class="button-primary" name="Submit"/>' .
243
+ '</p>' .
244
+ '</div>' .
245
+ '</div>' .
246
+ '<br class="clear"/>' .
247
+ '</div>' .
248
+ '</form>' .
249
+ '</div>' .
250
+ '<script type="text/javascript">' . "\n" .
251
+ '//<![CDATA[' . "\n" .
252
+ 'jQuery(document).ready( function($) {';
253
+ // close postboxes that should be closed
254
+ echo "$('.if-js-closed').removeClass('if-js-closed').addClass('closed');";
255
+ // postboxes setup
256
+ echo "postboxes.add_postbox_toggles('" . $this->pagehook . "');" .
257
+ '}); ' . "\n" .
258
+ '//]]>' . "\n" .
259
+ '</script>';
260
  }
261
 
262
  // executed if the post arrives initiated by pressing the submit button of form
263
  function on_save_changes() {
264
+ //user permission check
265
+ if (!current_user_can('manage_options')) wp_die(__('Problems?'));
266
+ // cross check the given referer
267
+ check_admin_referer(TR_NONCE);
268
 
269
+ // process here your on $_POST validation and / or option saving
270
+ $this->transposh->widget->transposh_widget_post(FALSE);
271
+ $this->update_admin_options();
272
 
273
+ // lets redirect the post request into get request (you may add additional params at the url, if you need to show save results
274
+ wp_redirect($_POST['_wp_http_referer']);
275
  }
276
 
277
  // below you will find for each registered metabox the callback method, that produces the content inside the boxes
278
  // i did not describe each callback dedicated, what they do can be easily inspected and compare with the admin page displayed
279
 
280
  function on_sidebox_about_content($data) {
281
+ echo '<ul style="list-style-type:disc;margin-left:20px;">';
282
+ echo '<li><a href="http://transposh.org/">Plugin Homepage</a></li>';
283
+ echo '<li><a href="http://transposh.org/redir/newfeature">Suggest a Feature</a></li>';
284
+ // support Forum
285
+ echo '<li><a href="http://transposh.org/redir/newticket">Report a Bug</a></li>';
286
+ // donate with PayPal
287
+ echo '</ul>';
288
  }
289
 
290
  function on_sidebox_widget_content($data) {
291
+ $this->transposh->widget->transposh_widget_control();
292
  }
293
 
294
  function on_sidebox_news_content($data) {
295
+ require_once(ABSPATH . WPINC . '/rss.php');
296
+
297
+ // ugly hack copy of RSS because of Unicode chars misprinting
298
+ function wp_rss2($url, $num_items = -1) {
299
+ if ($rss = fetch_rss($url)) {
300
+ echo '<ul>';
301
+
302
+ if ($num_items !== -1) {
303
+ $rss->items = array_slice($rss->items, 0, $num_items);
304
+ }
305
+
306
+ foreach ((array) $rss->items as $item) {
307
+ printf(
308
+ '<li><a href="%1$s" title="%2$s">%3$s</a></li>',
309
+ //esc_url( $item['link'] ),
310
+ //esc_attr( strip_tags( $item['description'] ) ),
311
+ // TODO - check Switched to 2.7 compatability functions
312
+ clean_url($item['link']),
313
+ attribute_escape(strip_tags($item['description'])),
314
+ htmlentities($item['title'], ENT_COMPAT, 'UTF-8')
315
+ );
316
+ }
317
+
318
+ echo '</ul>';
319
+ } else {
320
+ _e('An error has occurred, which probably means the feed is down. Try again later.');
321
+ }
322
+ }
323
+
324
+ echo '<div style="margin:6px">';
325
+ wp_rss2('http://feeds2.feedburner.com/transposh', 5);
326
+ echo '</div>';
327
  }
328
 
329
  function on_sidebox_stats_content($data) {
330
+ $this->transposh->database->db_stats();
331
  }
332
 
333
  function on_sidebox_translate_content($data) {
334
+ echo '<div id="progress_bar_all"></div><div id="tr_translate_title"></div>';
335
+ echo '<div id="tr_loading" style="margin: 0 0 10px 0">Translate by clicking the button below</div>';
336
+ echo '<a id="transposh-translate" href="' . $this->transposh->post_url . '?translate_all&offset=1" onclick="return false;" class="button">Translate All Now</a><br/>';
337
+ //get_posts
338
  }
339
 
340
  /**
342
  * @param string $data
343
  */
344
  function on_contentbox_languages_content($data) {
345
+ // we need some styles
346
+ echo '<style type="text/css">
347
  #sortable { list-style-type: none; margin: 0; padding: 0; }
348
  #sortable li, #default_lang li { margin: 3px 3px 3px 0; padding: 5px; float: left; width: 190px; height: 14px;}
349
  .languages {
386
  }
387
  </style>';
388
 
389
+ // this is the default language location
390
+ list ($langname, $langorigname, $flag) = explode(",", $GLOBALS['languages'][$this->transposh->options->get_default_language()]);
391
+ echo '<div id="default_lang" style="overflow:auto;padding-bottom:10px;">Default Language (drag another language here to make it default)';
392
+ echo '<ul id="default_list"><li id="' . $this->transposh->options->get_default_language() . '" class="languages">'
393
+ . display_flag("{$this->transposh->transposh_plugin_url}/img/flags", $flag, $langorigname, false/* $this->transposh->options->get_widget_css_flags() */)
394
+ . '<input type="hidden" name="languages[]" value="' . $this->transposh->options->get_default_language() . '" />'
395
+ . '&nbsp;<span class="langname">' . $langorigname . '</span><span class="langname hidden">' . $langname . '</span></li>';
396
+ echo '</ul></div>';
397
+ // list of languages
398
+ echo '<div style="overflow:auto; clear: both;">Available Languages (Click to toggle language state - Drag to sort in the widget)';
399
+ echo '<ul id="sortable">';
400
+ foreach ($this->transposh->options->get_sorted_langs() as $langcode => $langrecord) {
401
+ list ($langname, $langorigname, $flag) = explode(",", $langrecord);
402
+ echo '<li id="' . $langcode . '" class="languages ' . ($this->transposh->options->is_viewable_language($langcode) || $this->transposh->options->is_default_language($langcode) ? "active" : "")
403
+ . (!$this->transposh->options->is_viewable_language($langcode) && $this->transposh->options->is_editable_language($langcode) ? "translateable" : "") . '"><div style="float:left">'
404
+ . display_flag("{$this->transposh->transposh_plugin_url}/img/flags", $flag, false /* $langorigname,$this->transposh->options->get_widget_css_flags() */)
405
+ . '<input type="hidden" name="languages[]" value="' . $langcode . ($this->transposh->options->is_viewable_language($langcode) ? ",v" : ",") . ($this->transposh->options->is_viewable_language($langcode) ? ",t" : ",") . '" />'
406
+ . '&nbsp;<span class="langname">' . $langorigname . '</span><span class="langname hidden">' . $langname . '</span></div>';
407
+ if (in_array($langcode, $GLOBALS['google_languages']))
408
+ echo '<img width="16" height="16" alt="g" class="logoicon" title="Language supported by google translate" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/googleicon.png"/>';
409
+ if (in_array($langcode, $GLOBALS['bing_languages']))
410
+ echo '<img width="16" height="16" alt="b" class="logoicon" title="Language supported by bing translate" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/bingicon.png"/>';
411
+ if (in_array($langcode, $GLOBALS['rtl_languages']))
412
+ echo '<img width="16" height="16" alt="r" class="logoicon" title="Language is written from right to left" src="' . $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_IMG . '/rtlicon.png"/>';
413
+ echo '</li>';
414
+ }
415
+ echo "</ul></div>";
416
+ // options to play with
417
+ echo '<div style="clear: both;">Display options:<br/><ul style="list-style-type: disc; margin-left: 20px;font-size:11px">';
418
+ echo '<li><a href="#" id="changename">Toggle names of languages between English and Original</a></li>';
419
+ echo '<li><a href="#" id="selectall">Make all languages active</a></li>';
420
+ echo '<li><a href="#" id="sortname">Sort by language name</a></li>';
421
+ echo '<li><a href="#" id="sortiso">Sort by lSO code</a></li></ul>';
422
+ echo 'Legend: Green - active, <span id="yellowcolor"' . ($this->transposh->options->get_anonymous_translation() ? ' class ="hidden"' : '') . '>Yellow - translateable (only translators will see this language), </span>blank - inactive';
423
+ echo '</div>';
424
  }
425
 
426
  /**
429
  * @return string used for checkboxes
430
  */
431
  private function checked($eval) {
432
+ return $eval ? 'checked="checked"' : '';
433
  }
434
 
435
  function on_contentbox_translation_content($data) {
436
+ /*
437
+ * Insert permissions section in the admin page
438
+ */
439
+ echo '<h4>Who can translate ?</h4>';
440
+ //display known roles and their permission to translate
441
+ foreach ($GLOBALS['wp_roles']->get_names() as $role_name => $something) {
442
+ echo '<input type="checkbox" value="1" name="' . $role_name . '" ' . $this->can_translate($role_name) .
443
+ '/> ' . ucfirst($role_name) . '&nbsp;&nbsp;&nbsp;';
444
+ }
445
+ //Add our own custom role
446
+ echo '<input id="tr_anon" type="checkbox" value="1" name="anonymous" ' . $this->can_translate('anonymous') . '/> Anonymous';
447
+
448
+ /*
449
+ * Insert the option to enable/disable default language translation.
450
+ * Disabled by default.
451
+ */
452
+ echo '<h4>Enable default language translation</h4>';
453
+ echo '<input type="checkbox" value="1" name="' . ENABLE_DEFAULT_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_default_translate()) . '/> ' .
454
+ 'Allow translation of default language - useful for sites with more than one major language';
455
+
456
+ /**
457
+ * Insert the option to enable search in translated languages
458
+ * Enabled by default.
459
+ * @since 0.3.6
460
+ */
461
+ echo '<h4>Enable search in translated languages</h4>';
462
+ echo '<input type="checkbox" value="1" name="' . ENABLE_SEARCH_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_search_translate()) . '/> ' .
463
+ 'Allow search of translated languages, in those languages (and the original language)';
464
+
465
+ /**
466
+ * Insert the option to enable translation of urls
467
+ * Disbaled by default.
468
+ * @since 0.5.3
469
+ */
470
+ echo '<h4>Enable url translation (experimental)</h4>';
471
+ echo '<input type="checkbox" value="1" name="' . ENABLE_URL_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_url_translate()) . '/> ' .
472
+ 'Allow translation of permalinks and urls';
473
  }
474
 
475
  function on_contentbox_auto_translation_content($data) {
476
 
477
+ /*
478
+ * Insert the option to enable/disable automatic translation.
479
+ * Enabled by default.
480
+ */
481
+ echo '<h4>Enable automatic translation</h4>';
482
+ echo '<input type="checkbox" value="1" name="' . ENABLE_AUTO_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_auto_translate()) . '/> ' .
483
+ 'Allow automatic translation of pages';
484
+
485
+ /**
486
+ * Insert the option to enable/disable automatic translation upon publishing.
487
+ * Disabled by default.
488
+ * @since 0.3.5 */
489
+ echo '<h4>New - Enable automatic translation after posting</h4>';
490
+ echo '<input type="checkbox" value="1" name="' . ENABLE_AUTO_POST_TRANSLATE . '" ' . $this->checked($this->transposh->options->get_enable_auto_post_translate()) . '/> ' .
491
+ 'Do automatic translation immediately after a post has been published';
492
+
493
+ /*
494
+ * Choose default translator... TODO (explain better in wiki)
495
+ */
496
+ echo '<h4>Select preferred auto translation engine</h4>';
497
+ echo '<label for="' . PREFERRED_TRANSLATOR . '">Translation engine:' .
498
+ '<select name="' . PREFERRED_TRANSLATOR . '">' .
499
+ '<option value="1"' . ($this->transposh->options->get_preferred_translator() == 1 ? ' selected="selected"' : '') . '>Google</option>' .
500
+ '<option value="2"' . ($this->transposh->options->get_preferred_translator() == 2 ? ' selected="selected"' : '') . '>Bing</option>' .
501
+ '</select>' .
502
+ '</label>';
 
 
 
 
 
 
 
 
 
503
  }
504
 
505
  function on_contentbox_generic_content($data) {
506
+ /*
507
+ * Insert the option to enable/disable rewrite of perlmalinks.
508
+ * When disabled only parameters will be used to identify the current language.
509
+ */
510
+ echo '<h4>Rewrite URLs</h4>';
511
+ echo '<input type="checkbox" value="1" name="' . ENABLE_PERMALINKS . '" ' . $this->checked($this->transposh->options->get_enable_permalinks()) . '/> ' .
512
+ 'Rewrite URLs to be search engine friendly, ' .
513
+ 'e.g. (http://wordpress.org/<strong>en</strong>). ' .
514
+ 'Requires that permalinks will be enabled.';
515
+
516
+ /*
517
+ * Insert the option to enable/disable pushing of scripts to footer.
518
+ * Works on wordpress 2.8 and up
519
+ */
520
+ if (floatval($GLOBALS['wp_version']) >= 2.8) {
521
+ echo '<h4>Add scripts to footer</h4>';
522
+ echo '<input type="checkbox" value="1" name="' . ENABLE_FOOTER_SCRIPTS . '" ' . $this->checked($this->transposh->options->get_enable_footer_scripts()) . '/> ' .
523
+ 'Push transposh scripts to footer of page instead of header, makes pages load faster. ' .
524
+ 'Requires that your theme should have proper footer support.';
525
+ }
526
+
527
+ /**
528
+ * Insert the option to enable/disable language auto-detection
529
+ * @since 0.3.8 */
530
+ echo '<h4>Auto detect language for users</h4>';
531
+ echo '<input type="checkbox" value="1" name="' . ENABLE_DETECT_LANG_AND_REDIRECT . '" ' . $this->checked($this->transposh->options->get_enable_detect_language()) . '/> ' .
532
+ 'This enables auto detection of language used by the user as defined in the ACCEPT_LANGUAGES they send. ' .
533
+ 'This will redirect the first page accessed in the session to the same page with the detected language.';
534
+
535
+ /* WIP2
536
+ echo '<a href="http://transposh.org/services/index.php?flags='.$flags.'">Gen sprites</a>'; */
537
  }
538
 
539
  function on_contentbox_community_content($data) {
540
+ echo '<h4>Backup service for human translation</h4>';
541
+ echo '<input type="radio" value="1" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 1) . '/>Enable daily backup<br/>';
542
+ echo '<input type="radio" value="2" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 2) . '/>Enable live backup<br/>';
543
+ echo '<input type="radio" value="0" name="' . TRANSPOSH_BACKUP_SCHEDULE . '" ' . $this->checked($this->transposh->options->get_transposh_backup_schedule() == 0) . '/>Disable backup (Can be run manually by clicking the button below)<br/>';
544
+ echo 'Service Key: <input type="text" size="32" class="regular-text" value="' . $this->transposh->options->get_transposh_key() . '" id="' . TRANSPOSH_KEY . '" name="' . TRANSPOSH_KEY . '"/> <a target="_blank" href="http://transposh.org/faq/#restore">How to restore?</a><br/>';
545
+ echo '<div id="backup_result"></div>';
546
+ echo '<div style="margin:10px 0"><a id="transposh-backup" href="#" class="button">Do Backup Now</a></div>';
547
  }
548
 
549
  }
wp/transposh_ajax.php CHANGED
@@ -47,45 +47,45 @@ if (file_exists($root . $self . '/wp-load.php')) {
47
  if (isset($_POST['translation_posted'])) {
48
  // supercache invalidation of pages - first lets find if supercache is here
49
  if (function_exists('wp_super_cache_init')) {
50
- //Now, we are actually using the referrer and not the request, with some precautions
51
- $GLOBALS['wp_cache_request_uri'] = substr($_SERVER['HTTP_REFERER'], stripos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) + strlen($_SERVER[''] . $_SERVER['HTTP_HOST']));
52
- $GLOBALS['wp_cache_request_uri'] = preg_replace('/[ <>\'\"\r\n\t\(\)]/', '', str_replace('/index.php', '/', str_replace('..', '', preg_replace("/(\?.*)?$/", '', $GLOBALS['wp_cache_request_uri']))));
53
- // get some supercache variables
54
- extract(wp_super_cache_init());
55
-
56
- // this is hackery for logged in users, a cookie is added to the request somehow and gzip is not correctly set, so we forcefully fix this
57
- if (!$cache_file) {
58
- $GLOBALS['wp_cache_gzip_encoding'] = gzip_accepted();
59
- unset($_COOKIE[key($_COOKIE)]);
60
- extract(wp_super_cache_init());
61
-
62
- }
63
 
64
- $dir = get_current_url_supercache_dir();
65
- // delete possible files that we can figure out, not deleting files for other cookies for example, but will do the trick in most cases
66
- $cache_fname = "{$dir}index.html";
67
-
68
- @unlink($cache_fname);
69
- $cache_fname = "{$dir}index.html.gz";
70
-
71
- @unlink($cache_fname);
72
-
73
- @unlink($cache_file);
74
-
75
- @unlink($meta_pathname);
76
 
77
- // go at edit pages too
78
- $GLOBALS['wp_cache_request_uri'] .="?edit=1";
79
- extract(wp_super_cache_init());
80
-
81
-
82
- @unlink($cache_file);
83
-
84
- @unlink($meta_pathname);
85
  }
86
 
87
  if ($_POST['translation_posted'] == 2) {
88
- $my_transposh_plugin->database->update_translation();
89
  }
90
  }
91
  // getting translation history
@@ -105,9 +105,9 @@ elseif (isset($_GET['tr_cookie'])) {
105
  elseif (isset($_GET['tr_cookie_bck'])) {
106
  setcookie('TR_LNG', get_language_from_url($_SERVER['HTTP_REFERER'], $my_transposh_plugin->home_url), time() + 90 * 24 * 60 * 60, COOKIEPATH, COOKIE_DOMAIN);
107
  if ($_SERVER['HTTP_REFERER']) {
108
- wp_redirect($_SERVER['HTTP_REFERER']);
109
  } else {
110
- wp_redirect($my_transposh_plugin->home_url);
111
  }
112
  }
113
  // Start full translation
@@ -118,6 +118,23 @@ elseif (isset($_GET['translate_all'])) {
118
  if (!current_user_can('edit_post', $page_ids[0])) return;
119
  echo json_encode($page_ids);
120
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  // Start backup on demand
122
  elseif (isset($_GET['backup'])) {
123
  $my_transposh_plugin->run_backup();
47
  if (isset($_POST['translation_posted'])) {
48
  // supercache invalidation of pages - first lets find if supercache is here
49
  if (function_exists('wp_super_cache_init')) {
50
+ //Now, we are actually using the referrer and not the request, with some precautions
51
+ $GLOBALS['wp_cache_request_uri'] = substr($_SERVER['HTTP_REFERER'], stripos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) + strlen($_SERVER[''] . $_SERVER['HTTP_HOST']));
52
+ $GLOBALS['wp_cache_request_uri'] = preg_replace('/[ <>\'\"\r\n\t\(\)]/', '', str_replace('/index.php', '/', str_replace('..', '', preg_replace("/(\?.*)?$/", '', $GLOBALS['wp_cache_request_uri']))));
53
+ // get some supercache variables
54
+ extract(wp_super_cache_init());
55
+
56
+ // this is hackery for logged in users, a cookie is added to the request somehow and gzip is not correctly set, so we forcefully fix this
57
+ if (!$cache_file) {
58
+ $GLOBALS['wp_cache_gzip_encoding'] = gzip_accepted();
59
+ unset($_COOKIE[key($_COOKIE)]);
60
+ extract(wp_super_cache_init());
61
+
62
+ }
63
 
64
+ $dir = get_current_url_supercache_dir();
65
+ // delete possible files that we can figure out, not deleting files for other cookies for example, but will do the trick in most cases
66
+ $cache_fname = "{$dir}index.html";
67
+
68
+ @unlink($cache_fname);
69
+ $cache_fname = "{$dir}index.html.gz";
70
+
71
+ @unlink($cache_fname);
72
+
73
+ @unlink($cache_file);
74
+
75
+ @unlink($meta_pathname);
76
 
77
+ // go at edit pages too
78
+ $GLOBALS['wp_cache_request_uri'] .="?edit=1";
79
+ extract(wp_super_cache_init());
80
+
81
+
82
+ @unlink($cache_file);
83
+
84
+ @unlink($meta_pathname);
85
  }
86
 
87
  if ($_POST['translation_posted'] == 2) {
88
+ $my_transposh_plugin->database->update_translation();
89
  }
90
  }
91
  // getting translation history
105
  elseif (isset($_GET['tr_cookie_bck'])) {
106
  setcookie('TR_LNG', get_language_from_url($_SERVER['HTTP_REFERER'], $my_transposh_plugin->home_url), time() + 90 * 24 * 60 * 60, COOKIEPATH, COOKIE_DOMAIN);
107
  if ($_SERVER['HTTP_REFERER']) {
108
+ wp_redirect($_SERVER['HTTP_REFERER']);
109
  } else {
110
+ wp_redirect($my_transposh_plugin->home_url);
111
  }
112
  }
113
  // Start full translation
118
  if (!current_user_can('edit_post', $page_ids[0])) return;
119
  echo json_encode($page_ids);
120
  }
121
+ // Proxyed translation for google translate
122
+ elseif (isset($_GET['tgp'])) {
123
+ // we need curl for this proxy
124
+ if (!function_exists('curl_init')) return;
125
+ // we want to avoid unneeded work or dos attacks on languages we don't support
126
+ if (!in_array($_GET['tgl'], $google_proxied_languages) || !$my_transposh_plugin->options->is_editable_language($_GET['tgl'])) return;
127
+ $url = 'http://translate.google.com/translate_a/t?client=a&text=' . urlencode($_GET['tgp']) . '&tl=' . $_GET['tgl'] . '&sl=auto';
128
+ $ch = curl_init();
129
+ curl_setopt($ch, CURLOPT_URL, $url);
130
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
131
+ //must set agent for google to respond with utf-8
132
+ curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
133
+ $output = curl_exec($ch);
134
+ curl_close($ch);
135
+ header('Content-type: text/html; charset=utf-8');
136
+ echo $output;
137
+ }
138
  // Start backup on demand
139
  elseif (isset($_GET['backup'])) {
140
  $my_transposh_plugin->run_backup();
wp/transposh_options.php CHANGED
@@ -25,6 +25,10 @@ define("OLD_WIDGET_STYLE", "widget_style");
25
  define("OLD_WIDGET_CSS_FLAGS", "widget_css_flags");
26
  //Wrap widget elements in an unordered list per #63 @since 0.3.7
27
  define("OLD_WIDGET_IN_LIST", "widget_in_list");
 
 
 
 
28
 
29
  //defines are used to avoid typos
30
  //Option defining whether anonymous translation is allowed.
@@ -39,10 +43,6 @@ define("SORTED_LANGS", "sorted_languages");
39
  define("ENABLE_AUTO_TRANSLATE", "enable_autotranslate");
40
  //Option to enable/disable auto translation
41
  define("ENABLE_AUTO_POST_TRANSLATE", "enable_autoposttranslate");
42
- //Option to enable/disable msn translation
43
- define("ENABLE_MSN_TRANSLATE", "enable_msntranslate");
44
- //Option to store the msn API key
45
- define("MSN_TRANSLATE_KEY", "msn_key");
46
  //Option to store translator preference @since 0.4.2
47
  define("PREFERRED_TRANSLATOR", "preferred_translator");
48
  //Option to enable/disable default language translation
@@ -65,6 +65,8 @@ define("WIDGET_FILE", "widget_file");
65
  define("WIDGET_PROGRESSBAR", "widget_progressbar");
66
  //Allows user to set his default language per #63 @since 0.3.8
67
  define("WIDGET_ALLOW_SET_DEFLANG", "widget_allow_set_deflang");
 
 
68
  //Stores the site key to transposh services (backup @since 0.5.0)
69
  define("TRANSPOSH_KEY", "transposh_key");
70
  //Stores the site key to transposh services (backup @since 0.5.0)
@@ -105,6 +107,8 @@ class transposh_plugin_options {
105
  unset($this->options[OLD_WIDGET_CSS_FLAGS]);
106
  unset($this->options[OLD_WIDGET_IN_LIST]);
107
  unset($this->options[OLD_WIDGET_STYLE]);
 
 
108
 
109
  update_option(TRANSPOSH_OPTIONS, $this->options);
110
  }
@@ -138,6 +142,10 @@ class transposh_plugin_options {
138
  return $this->options[WIDGET_PROGRESSBAR];
139
  }
140
 
 
 
 
 
141
  /**
142
  * return file name of the widget used
143
  * @since 0.5.6
@@ -163,10 +171,6 @@ class transposh_plugin_options {
163
  return $this->options[ENABLE_DETECT_LANG_AND_REDIRECT];
164
  }
165
 
166
- function get_enable_msn_translate() {
167
- return $this->options[ENABLE_MSN_TRANSLATE]; // FIX
168
- }
169
-
170
  function get_enable_default_translate() {
171
  return $this->options[ENABLE_DEFAULT_TRANSLATE];
172
  }
@@ -191,12 +195,8 @@ class transposh_plugin_options {
191
  return $this->options[ENABLE_AUTO_POST_TRANSLATE];
192
  }
193
 
194
- function get_msn_key() {
195
- return $this->options[MSN_TRANSLATE_KEY];
196
- }
197
-
198
  function get_preferred_translator() {
199
- // default is google (2 is msn)
200
  if (!isset($this->options[PREFERRED_TRANSLATOR])) return 1;
201
  return $this->options[PREFERRED_TRANSLATOR];
202
  }
@@ -259,6 +259,11 @@ class transposh_plugin_options {
259
  $this->set_value($val, $this->options[WIDGET_PROGRESSBAR]);
260
  }
261
 
 
 
 
 
 
262
  /**
263
  * Set the widget file used
264
  * @since 0.5.6
@@ -288,11 +293,6 @@ class transposh_plugin_options {
288
  $this->set_value($val, $this->options[ENABLE_FOOTER_SCRIPTS]);
289
  }
290
 
291
- function set_enable_msn_translate($val) {
292
- $val = ($val) ? 1 : 0;
293
- $this->set_value($val, $this->options[ENABLE_MSN_TRANSLATE]); // FIX
294
- }
295
-
296
  function set_enable_default_translate($val) {
297
  $val = ($val) ? 1 : 0;
298
  $this->set_value($val, $this->options[ENABLE_DEFAULT_TRANSLATE]);
@@ -318,10 +318,6 @@ class transposh_plugin_options {
318
  $this->set_value($val, $this->options[ENABLE_AUTO_POST_TRANSLATE]);
319
  }
320
 
321
- function set_msn_key($val) {
322
- $this->set_value($val, $this->options[MSN_TRANSLATE_KEY]);
323
- }
324
-
325
  function set_preferred_translator($val) {
326
  $this->set_value($val, $this->options[PREFERRED_TRANSLATOR]);
327
  }
25
  define("OLD_WIDGET_CSS_FLAGS", "widget_css_flags");
26
  //Wrap widget elements in an unordered list per #63 @since 0.3.7
27
  define("OLD_WIDGET_IN_LIST", "widget_in_list");
28
+ //Option to enable/disable msn translation
29
+ define("OLD_ENABLE_MSN_TRANSLATE", "enable_msntranslate");
30
+ //Option to store the msn API key
31
+ define("OLD_MSN_TRANSLATE_KEY", "msn_key");
32
 
33
  //defines are used to avoid typos
34
  //Option defining whether anonymous translation is allowed.
43
  define("ENABLE_AUTO_TRANSLATE", "enable_autotranslate");
44
  //Option to enable/disable auto translation
45
  define("ENABLE_AUTO_POST_TRANSLATE", "enable_autoposttranslate");
 
 
 
 
46
  //Option to store translator preference @since 0.4.2
47
  define("PREFERRED_TRANSLATOR", "preferred_translator");
48
  //Option to enable/disable default language translation
65
  define("WIDGET_PROGRESSBAR", "widget_progressbar");
66
  //Allows user to set his default language per #63 @since 0.3.8
67
  define("WIDGET_ALLOW_SET_DEFLANG", "widget_allow_set_deflang");
68
+ //Allows removing of transposh logo in exchange for an ad @since 0.6.0
69
+ define("WIDGET_REMOVE_LOGO_FOR_AD", "widget_remove_logo");
70
  //Stores the site key to transposh services (backup @since 0.5.0)
71
  define("TRANSPOSH_KEY", "transposh_key");
72
  //Stores the site key to transposh services (backup @since 0.5.0)
107
  unset($this->options[OLD_WIDGET_CSS_FLAGS]);
108
  unset($this->options[OLD_WIDGET_IN_LIST]);
109
  unset($this->options[OLD_WIDGET_STYLE]);
110
+ unset($this->options[OLD_MSN_TRANSLATE_KEY]);
111
+ unset($this->options[OLD_ENABLE_MSN_TRANSLATE]);
112
 
113
  update_option(TRANSPOSH_OPTIONS, $this->options);
114
  }
142
  return $this->options[WIDGET_PROGRESSBAR];
143
  }
144
 
145
+ function get_widget_remove_logo() {
146
+ return $this->options[WIDGET_REMOVE_LOGO_FOR_AD];
147
+ }
148
+
149
  /**
150
  * return file name of the widget used
151
  * @since 0.5.6
171
  return $this->options[ENABLE_DETECT_LANG_AND_REDIRECT];
172
  }
173
 
 
 
 
 
174
  function get_enable_default_translate() {
175
  return $this->options[ENABLE_DEFAULT_TRANSLATE];
176
  }
195
  return $this->options[ENABLE_AUTO_POST_TRANSLATE];
196
  }
197
 
 
 
 
 
198
  function get_preferred_translator() {
199
+ // default is google(1) (2 is msn)
200
  if (!isset($this->options[PREFERRED_TRANSLATOR])) return 1;
201
  return $this->options[PREFERRED_TRANSLATOR];
202
  }
259
  $this->set_value($val, $this->options[WIDGET_PROGRESSBAR]);
260
  }
261
 
262
+ function set_widget_remove_logo($val) {
263
+ $val = ($val) ? 1 : 0;
264
+ $this->set_value($val, $this->options[WIDGET_REMOVE_LOGO_FOR_AD]);
265
+ }
266
+
267
  /**
268
  * Set the widget file used
269
  * @since 0.5.6
293
  $this->set_value($val, $this->options[ENABLE_FOOTER_SCRIPTS]);
294
  }
295
 
 
 
 
 
 
296
  function set_enable_default_translate($val) {
297
  $val = ($val) ? 1 : 0;
298
  $this->set_value($val, $this->options[ENABLE_DEFAULT_TRANSLATE]);
318
  $this->set_value($val, $this->options[ENABLE_AUTO_POST_TRANSLATE]);
319
  }
320
 
 
 
 
 
321
  function set_preferred_translator($val) {
322
  $this->set_value($val, $this->options[PREFERRED_TRANSLATOR]);
323
  }
wp/transposh_postpublish.php CHANGED
@@ -38,13 +38,13 @@ class transposh_postpublish {
38
  * @param transposh_plugin $transposh
39
  */
40
  function transposh_postpublish(&$transposh) {
41
- $this->transposh = &$transposh;
42
- // we'll only do something if so configured to do
43
- if ($this->transposh->options->get_enable_auto_post_translate()) {
44
- add_action('edit_post', array(&$this, 'on_edit'));
45
- // add_action('publish_post',array(&$this, 'on_publish'));
46
- add_action('admin_menu', array(&$this, 'on_admin_menu'));
47
- }
48
  }
49
 
50
  /**
@@ -52,35 +52,30 @@ class transposh_postpublish {
52
  */
53
  function on_admin_menu() {
54
  //add our metabox to the post and pubish pages
55
-
56
- add_meta_box('transposh_postpublish', 'Transposh', array(&$this, "transposh_postpublish_box"), 'post', 'side', 'core');
57
- add_meta_box('transposh_postpublish', 'Transposh', array(&$this, "transposh_postpublish_box"), 'page', 'side', 'core');
58
- if ($_GET['justedited']) {
59
- wp_enqueue_script("google", "http://www.google.com/jsapi", array(), '1', true);
60
- wp_enqueue_script("transposh", "{$this->transposh->transposh_plugin_url}/js/transposhadmin.js", array("jquery"), TRANSPOSH_PLUGIN_VER, true);
61
- wp_localize_script("transposh", "t_jp", array(
62
- 'post_url' => $this->transposh->post_url,
63
- 'post' => $_GET['post'],
64
- 'msnkey' => $this->transposh->options->get_msn_key(),
65
- 'msn_langs' => json_encode($GLOBALS['bing_languages']),
66
- 'google_lang' => json_encode($GLOBALS['google_languages']),
67
- 'preferred' => $this->transposh->options->get_preferred_translator()/* ,
68
- 'plugin_url' => $this->transposh_plugin_url,
69
- 'edit' => ($this->edit_mode? '1' : ''),
70
- //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
71
- 'lang' => $this->target_language,
72
- // those two options show if the script can support said engines
73
- 'prefix' => SPAN_PREFIX,
74
-
75
- 'progress'=>$this->edit_mode || $this->options->get_widget_progressbar() ? '1' : '') */
76
  // 'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
77
- ));
78
- wp_enqueue_style("jquery", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css", array(), '1.0');
79
- wp_enqueue_script("jqueryui", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js", array("jquery"), '1.7.2', true);
80
- /* if ($this->transposh->options->get_enable_msn_translate() && $this->transposh->options->get_msn_key()) {
81
- wp_enqueue_script("mstranslate","http://api.microsofttranslator.com/V1/Ajax.svc/Embed?appId=".$this->transposh->options->get_msn_key(),array(),'1',true);
82
- } */
83
- }
84
  }
85
 
86
  /**
@@ -88,80 +83,83 @@ class transposh_postpublish {
88
  * @param int $postID
89
  */
90
  function get_post_phrases($postID) {
91
- // Some security, to avoid others from seeing private posts
92
- if (!current_user_can('edit_post', $postID)) return;
93
- $post = get_post($postID);
94
- // Display filters
95
- $title = apply_filters('the_title', $post->post_title);
96
- $content = apply_filters('the_content', $post->post_content);
97
- // TODO - grab phrases from rss excerpt
98
- //$output = get_the_excerpt();
99
- // echo apply_filters('the_excerpt_rss', $output);
100
- //TODO - get comments text
101
-
102
- $parser = new parser();
103
- $phrases = $parser->get_phrases_list($content);
104
- $phrases2 = $parser->get_phrases_list($title);
105
-
106
- // Merge the two arrays for traversing
107
- $phrases = array_merge($phrases, $phrases2);
108
-
109
- // Add pharses from permalink
110
- if ($this->transposh->options->get_enable_url_translate()) {
111
- $permalink = get_permalink($postID);
112
- $permalink = substr($permalink, strlen($this->transposh->home_url) + 1);
113
- $parts = explode('/', $permalink);
114
- foreach ($parts as $part) {
115
- if (!$part || is_numeric($part)) continue;
116
- $part = str_replace('-', ' ', $part);
117
- $phrases[] = $part;
118
- }
119
- }
120
-
121
- foreach ($phrases as $key) {
122
- foreach (explode(',', $this->transposh->options->get_editable_langs()) as $lang) {
123
- // if this isn't the default language or we specifically allow default language translation, we will seek this out...
124
- // as we don't normally want to auto-translate the default language
125
- if (!$this->transposh->options->is_default_language($lang) || $this->transposh->options->get_enable_default_translate()) {
126
- list($translation, $source) = $this->transposh->database->fetch_translation($key, $lang);
127
- if (!$translation) {
128
- // p stands for phrases, l stands for languages, t is token
129
- if (!is_array($json['p'][$key]['l'])) {
130
- $json['p'][$key]['l'] = array();
131
- }
132
- array_push($json['p'][$key]['l'], $lang);
133
- }
134
- }
135
- }
136
- // only if a languages list was created we'll need to translate this
137
- if (is_array($json['p'][$key]['l'])) {
138
- $json['p'][$key]['t'] = base64_url_encode($key);
139
- $json['length']++;
140
- }
141
- }
142
-
143
- // add the title
144
- // if ($json['length'])
145
- $json['posttitle'] = $title;
146
-
147
- // the header helps with debugging
148
- header("Content-type: text/javascript");
149
- echo json_encode($json);
 
 
 
150
  }
151
 
152
  /**
153
  * This is the box that appears on the side
154
  */
155
  function transposh_postpublish_box() {
156
- // the nonce will help double translation if time has passed
157
- if ($_GET['justedited'] && wp_verify_nonce($_GET['justedited']))
158
- $this->just_published = true;
159
-
160
- if ($this->just_published) {
161
- echo '<div id="tr_loading">Publication happened - loading phrases list...</div>';
162
- } else {
163
- echo 'Waiting for publication';
164
- }
165
  }
166
 
167
  /**
@@ -169,7 +167,7 @@ class transposh_postpublish {
169
  * @param int $postID
170
  */
171
  function on_edit($postID) {
172
- add_filter('wp_redirect', array(&$this, 'inform_published'));
173
  }
174
 
175
  /**
@@ -178,7 +176,7 @@ class transposh_postpublish {
178
  * @return string redirected URL
179
  */
180
  function inform_published($url) {
181
- return add_query_arg('justedited', wp_create_nonce(), $url);
182
  }
183
 
184
  }
38
  * @param transposh_plugin $transposh
39
  */
40
  function transposh_postpublish(&$transposh) {
41
+ $this->transposh = &$transposh;
42
+ // we'll only do something if so configured to do
43
+ if ($this->transposh->options->get_enable_auto_post_translate()) {
44
+ add_action('edit_post', array(&$this, 'on_edit'));
45
+ // add_action('publish_post',array(&$this, 'on_publish'));
46
+ add_action('admin_menu', array(&$this, 'on_admin_menu'));
47
+ }
48
  }
49
 
50
  /**
52
  */
53
  function on_admin_menu() {
54
  //add our metabox to the post and pubish pages
55
+
56
+ add_meta_box('transposh_postpublish', 'Transposh', array(&$this, "transposh_postpublish_box"), 'post', 'side', 'core');
57
+ add_meta_box('transposh_postpublish', 'Transposh', array(&$this, "transposh_postpublish_box"), 'page', 'side', 'core');
58
+ if ($_GET['justedited']) {
59
+ //wp_enqueue_script("google", "http://www.google.com/jsapi", array(), '1', true);
60
+ wp_enqueue_script("transposh", $this->transposh->transposh_plugin_url . '/' . TRANSPOSH_DIR_JS . '/transposhadmin.js', array('jquery'), TRANSPOSH_PLUGIN_VER, true);
61
+ wp_localize_script("transposh", "t_jp", array(
62
+ 'post_url' => $this->transposh->post_url,
63
+ 'post' => $_GET['post'],
64
+ 'preferred' => $this->transposh->options->get_preferred_translator(),
65
+ 'l10n_print_after' => 't_jp.g_langs = ' . json_encode($GLOBALS['google_languages']) . '; t_jp.m_langs = ' . json_encode($GLOBALS['bing_languages']) . ';'/*
66
+ 'plugin_url' => $this->transposh_plugin_url,
67
+ 'edit' => ($this->edit_mode? '1' : ''),
68
+ //'rtl' => (in_array ($this->target_language, $GLOBALS['rtl_languages'])? 'true' : ''),
69
+ 'lang' => $this->target_language,
70
+ // those two options show if the script can support said engines
71
+ 'prefix' => SPAN_PREFIX,
72
+
73
+ 'progress'=>$this->edit_mode || $this->options->get_widget_progressbar() ? '1' : '') */
 
 
74
  // 'l10n_print_after' => 'try{convertEntities(inlineEditL10n);}catch(e){};'
75
+ ));
76
+ wp_enqueue_style('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/ui-lightness/jquery-ui.css', array(), '1.8.2');
77
+ wp_enqueue_script('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js', array('jquery'), '1.8.2', true);
78
+ }
 
 
 
79
  }
80
 
81
  /**
83
  * @param int $postID
84
  */
85
  function get_post_phrases($postID) {
86
+ // Some security, to avoid others from seeing private posts
87
+ if (!current_user_can('edit_post', $postID)) return;
88
+ $post = get_post($postID);
89
+ // Display filters
90
+ $title = apply_filters('the_title', $post->post_title);
91
+ $content = apply_filters('the_content', $post->post_content);
92
+ // TODO - grab phrases from rss excerpt
93
+ //$output = get_the_excerpt();
94
+ // echo apply_filters('the_excerpt_rss', $output);
95
+ //TODO - get comments text
96
+
97
+ $parser = new parser();
98
+ $phrases = $parser->get_phrases_list($content);
99
+ $phrases2 = $parser->get_phrases_list($title);
100
+
101
+ // Merge the two arrays for traversing
102
+ $phrases = array_merge($phrases, $phrases2);
103
+
104
+ // Add pharses from permalink
105
+ if ($this->transposh->options->get_enable_url_translate()) {
106
+ $permalink = get_permalink($postID);
107
+ $permalink = substr($permalink, strlen($this->transposh->home_url) + 1);
108
+ $parts = explode('/', $permalink);
109
+ foreach ($parts as $part) {
110
+ if (!$part || is_numeric($part)) continue;
111
+ $part = str_replace('-', ' ', $part);
112
+ $phrases[] = $part;
113
+ }
114
+ }
115
+
116
+ foreach ($phrases as $key) {
117
+ foreach (explode(',', $this->transposh->options->get_editable_langs()) as $lang) {
118
+ // if this isn't the default language or we specifically allow default language translation, we will seek this out...
119
+ // as we don't normally want to auto-translate the default language -FIX THIS to include only correct stuff, how?
120
+ if (!$this->transposh->options->is_default_language($lang) || $this->transposh->options->get_enable_default_translate()) {
121
+ // There is no point in returning phrases, languages pairs that cannot be translated
122
+ if (in_array($lang, $GLOBALS['bing_languages']) || in_array($lang, $GLOBALS['google_languages'])) {
123
+ list($translation, $source) = $this->transposh->database->fetch_translation($key, $lang);
124
+ if (!$translation) {
125
+ // p stands for phrases, l stands for languages, t is token
126
+ if (!is_array($json['p'][$key]['l'])) {
127
+ $json['p'][$key]['l'] = array();
128
+ }
129
+ array_push($json['p'][$key]['l'], $lang);
130
+ }
131
+ }
132
+ }
133
+ }
134
+ // only if a languages list was created we'll need to translate this
135
+ if (is_array($json['p'][$key]['l'])) {
136
+ $json['p'][$key]['t'] = base64_url_encode($key);
137
+ $json['length']++;
138
+ }
139
+ }
140
+
141
+ // add the title
142
+ // if ($json['length'])
143
+ $json['posttitle'] = $title;
144
+
145
+ // the header helps with debugging
146
+ header("Content-type: text/javascript");
147
+ echo json_encode($json);
148
  }
149
 
150
  /**
151
  * This is the box that appears on the side
152
  */
153
  function transposh_postpublish_box() {
154
+ // the nonce will help double translation if time has passed
155
+ if ($_GET['justedited'] && wp_verify_nonce($_GET['justedited']))
156
+ $this->just_published = true;
157
+
158
+ if ($this->just_published) {
159
+ echo '<div id="tr_loading">Publication happened - loading phrases list...</div>';
160
+ } else {
161
+ echo 'Waiting for publication';
162
+ }
163
  }
164
 
165
  /**
167
  * @param int $postID
168
  */
169
  function on_edit($postID) {
170
+ add_filter('wp_redirect', array(&$this, 'inform_published'));
171
  }
172
 
173
  /**
176
  * @return string redirected URL
177
  */
178
  function inform_published($url) {
179
+ return add_query_arg('justedited', wp_create_nonce(), $url);
180
  }
181
 
182
  }
wp/transposh_widget.php CHANGED
@@ -35,123 +35,123 @@ class transposh_plugin_widget {
35
 
36
  //constructor of class, PHP4 compatible construction for backward compatibility
37
  function transposh_plugin_widget(&$transposh) {
38
- //Register callback for WordPress events
39
- $this->transposh = &$transposh;
40
- add_action('init', array(&$this, 'init_transposh'), 1);
41
- add_action('widgets_init', array(&$this, 'transposh_widget_init'));
42
  }
43
 
44
  /**
45
  * Intercept init calls to see if it was posted by the widget.
46
  */
47
  function init_transposh() {
48
- if (isset($_POST['transposh_widget_posted'])) {
49
-
50
-
51
- $ref = getenv('HTTP_REFERER');
52
- $lang = $_POST[LANG_PARAM];
53
- if ($lang == '') {
54
- $lang = get_language_from_url($_SERVER['HTTP_REFERER'], $this->transposh->home_url);
55
- }
56
- if ($lang == $this->transposh->options->get_default_language() || $lang == "none")
57
- $lang = '';
58
-
59
-
60
- // first, we might need to get the original url back
61
- if ($this->transposh->options->get_enable_url_translate()) {
62
- $ref = get_original_url($ref, $this->transposh->home_url, get_language_from_url($ref, $this->transposh->home_url), array($this->transposh->database, 'fetch_original'));
63
- }
64
-
65
- //remove existing language settings.
66
- $ref = cleanup_url($ref, $this->transposh->home_url);
67
-
68
-
69
- if ($lang && $this->transposh->options->get_enable_url_translate()) {
70
- // and then, we might have to translate it
71
- $ref = translate_url($ref, $this->transposh->home_url, $lang, array(&$this->transposh->database, 'fetch_translation'));
72
- $ref = str_replace(array('%2F', '%3A', '%3B', '%3F', '%3D', '%26'), array('/', ':', ';', '?', '=', '&'), urlencode($ref));
73
-
74
- }
75
- $ref = rewrite_url_lang_param($ref, $this->transposh->home_url, $this->transposh->enable_permalinks_rewrite, $lang, $_POST[EDIT_PARAM]);
76
-
77
-
78
-
79
- wp_redirect($ref);
80
- exit;
81
- }
82
  }
83
 
84
  /**
85
  * Register the widget.
86
  */
87
  function transposh_widget_init() {
88
-
89
- if (!function_exists('register_sidebar_widget')) {
90
- return;
91
- }
92
 
93
- // Register widget
94
- register_sidebar_widget(array('Transposh', 'widgets'), array(&$this, 'transposh_widget'));
95
 
96
- // Register widget control
97
- register_widget_control("Transposh", array(&$this, 'transposh_widget_control'));
98
 
99
- // Register callback for widget's css and js
100
- add_action('wp_print_styles', array(&$this, 'add_transposh_widget_css'));
101
- add_action('wp_print_scripts', array(&$this, 'add_transposh_widget_js'));
102
  }
103
 
104
  /**
105
  * Loads the widget code
106
  */
107
  function load_widget() {
108
- // avoid dual loadings
109
- if ($this->base_widget_file_name) return;
110
-
111
- $file = $this->transposh->options->get_widget_file();
112
- $widget_src = $this->transposh->transposh_plugin_dir . TRANSPOSH_DIR_WIDGETS . '/' . $file;
113
- if ($file && file_exists($widget_src)) {
114
- include_once $widget_src;
115
- } else {
116
- $file = 'tpw_default.php';
117
- include_once $this->transposh->transposh_plugin_dir . TRANSPOSH_DIR_WIDGETS . '/' . $file;
118
- }
119
- $this->base_widget_file_name = substr($file, 0, -4);
120
  }
121
 
122
  /**
123
  * Add custom css, i.e. transposh_widget.css, flags now override widget
124
  */
125
  function add_transposh_widget_css() { //TODO ! goway
126
- $this->load_widget();
127
-
128
- if (function_exists(tp_widget_css)) {
129
- tp_widget_css();
130
- } else {
131
- $widget_css = TRANSPOSH_DIR_WIDGETS.'/'.$this->base_widget_file_name . ".css";
132
- if (file_exists($this->transposh->transposh_plugin_dir . $widget_css )) {
133
- wp_enqueue_style('transposh_widget', $this->transposh->transposh_plugin_url.'/'.$widget_css, '', TRANSPOSH_PLUGIN_VER);
134
- }
135
- }
136
-
137
-
138
  }
139
 
140
  /**
141
  * Add custom css, i.e. transposh_widget.css, flags now override widget
142
  */
143
  function add_transposh_widget_js() { //TODO ! goway
144
- $this->load_widget();
145
-
146
- if (function_exists(tp_widget_js)) {
147
- tp_widget_js();
148
- } else {
149
- $widget_js = TRANSPOSH_DIR_WIDGETS.'/'.$this->base_widget_file_name . ".js";
150
- if (file_exists($this->transposh->transposh_plugin_dir . $widget_js )) {
151
- wp_enqueue_script('transposh_widget', $this->transposh->transposh_plugin_url.'/'.$widget_js, '', TRANSPOSH_PLUGIN_VER);
152
- }
153
- }
154
-
155
  }
156
 
157
  /**
@@ -159,192 +159,200 @@ class transposh_plugin_widget {
159
  * @param array $args Contains such as $before_widget, $after_widget, $before_title, $after_title, etc
160
  */
161
  function transposh_widget($args) {
162
- $this->load_widget();
163
-
164
- // hmmm, this should actually prepare all vars needed, include the correct widget and send the vars to that function,
165
- $calc_url = false; // By default, avoid calculating the urls
166
- if (function_exists(tp_widget_needs_post_url))
167
- $calc_url = tp_widget_needs_post_url();
168
-
169
- $widget_args = array();
170
- $page_url = $_SERVER['REQUEST_URI'];
171
-
172
- //remove any language identifier and find the "clean" url, used for posting and calculating urls if needed
173
- $clean_page_url = cleanup_url($page_url, $this->transposh->home_url, true);
174
- // we need this if we are using url translations
175
- if ($this->transposh->options->get_enable_url_translate() && $calc_url) {
176
- $clean_page_url = get_original_url($clean_page_url, '', $this->transposh->target_language, array($this->transposh->database, 'fetch_original'));
177
- }
178
-
179
-
180
- // loop on the languages
181
- foreach ($this->transposh->options->get_sorted_langs() as $code => $langrecord) {
182
- list ($langname, $language, $flag) = explode(',', $langrecord);
183
-
184
- // Only send languages which are viewable or (editable and the user is a translator)
185
- if ($this->transposh->options->is_viewable_language($code) ||
186
- ($this->transposh->options->is_editable_language($code) && $this->transposh->is_translator()) ||
187
- ($this->transposh->options->is_default_language($code))) {
188
- if ($this->transposh->options->get_enable_url_translate() && $calc_url) {
189
- $page_url = translate_url($clean_page_url, '', $code, array(&$this->transposh->database, 'fetch_translation'));
190
- } else {
191
- $page_url = $clean_page_url;
192
- }
193
- // clean $code in default lanaguge
194
- if ($calc_url)
195
- $page_url = rewrite_url_lang_param($page_url, $this->transposh->home_url, $this->transposh->enable_permalinks_rewrite, ($code == $this->transposh->options->get_default_language()) ? '' : $code, $this->transposh->edit_mode);
196
- $widget_args[] = array(
197
- 'lang' => $langname,
198
- 'langorig' => $language,
199
- 'flag' => $flag,
200
- 'isocode' => $code,
201
- 'url' => $page_url,
202
- 'active' => ($this->transposh->target_language == $code));
203
- }
204
- }
205
- // at this point the widget args are ready
206
-
207
-
208
-
209
- // extract args given by wordpress
210
- extract($args);
211
-
212
-
213
- // widget default title
214
- echo $before_widget . $before_title . __('Translation') . $after_title;
215
-
216
- // the widget is inside a form used for posting a language change or edit request
217
- echo '<form id="tp_form" action="' . $clean_page_url . '" method="post">';
218
-
219
- // actually run the external widget code
220
- tp_widget_do($widget_args);
221
-
222
- //at least one language showing - add the edit box if applicable
223
- if (!empty($widget_args)) {
224
- // this is the set default language line
225
- if ($this->transposh->options->get_widget_allow_set_default_language()) {
226
- If ((isset($_COOKIE['TR_LNG']) && $_COOKIE['TR_LNG'] != $this->transposh->target_language) || (!isset($_COOKIE['TR_LNG']) && !$this->transposh->options->is_default_language($this->transposh->target_language))) {
227
- echo '<a id="' . SPAN_PREFIX . 'setdeflang" onClick="return false;" href="' . $this->transposh->post_url . '?tr_cookie_bck">Set as default language</a><br/>';
228
- }
229
- }
230
- // add the edit checkbox only for translators for languages marked as editable
231
- if ($this->transposh->is_editing_permitted()) {
232
- echo '<input type="checkbox" name="' . EDIT_PARAM . '" value="1" ' .
233
- ($this->transposh->edit_mode ? 'checked="checked"' : '') .
234
- ' onclick="this.form.submit();"/>&nbsp;Edit Translation';
235
- }
236
-
237
- echo '<input type="hidden" name="transposh_widget_posted" value="1"/>';
238
- } else {
239
- //no languages configured - error message
240
- echo '<p>No languages available for display. Check the Transposh settings (Admin).</p>';
241
- }
242
-
243
- echo "</form>";
244
-
245
- // Now this is a comment for those wishing to remove our logo (tplogo.png) and link (transposh.org) from the widget
246
- // first - according to the gpl, you may do so - but since the code has changed - please make in available under the gpl
247
- // second - we did invest a lot of time and effort into this, and the link is a way to help us grow and show your appreciation, if it
248
- // upsets you, feel more than free to move this link somewhere else on your page, such as the footer etc.
249
- // third - feel free to write your own widget, the translation core will work
250
- // forth - you can ask for permission, with a good reason, if you contributed to the code - it's a good enough reason :)
251
- // last - if you just delete the following line, it means that you have little respect to the whole copyright thing, which as far as we
252
- // understand means that by doing so - you are giving everybody else the right to do the same and use your work without any attribution
253
- $plugpath = parse_url($this->transposh->transposh_plugin_url, PHP_URL_PATH);
254
-
255
- echo '<div id="' . SPAN_PREFIX . 'credit">by <a href="http://tran' . 'sposh.org"><img class="' . NO_TRANSLATE_CLASS . '" height="16" width="16" src="' .
256
- $plugpath . '/img/tplog' . 'o.png" style="padding:1px;border:0px" title="Transposh" alt="Transposh"/></a></div>';
257
- echo $after_widget;
 
 
 
 
 
258
  }
259
 
260
  function transposh_widget_post($save = true) {
261
-
262
-
263
- $this->transposh->options->set_widget_file($_POST[WIDGET_FILE]);
264
- $this->transposh->options->set_widget_progressbar($_POST[WIDGET_PROGRESSBAR]);
265
- $this->transposh->options->set_widget_allow_set_default_language($_POST[WIDGET_ALLOW_SET_DEFLANG]);
266
- if ($save) $this->transposh->options->update_options();
267
- // Avoid coming here twice...
268
- unset($_POST['transposh-submit']);
 
269
  }
270
 
271
  /**
272
  * Inspired (and used code) from the get_plugins function of wordpress
273
  */
274
  function get_widgets($widget_folder = '') {
275
- get_plugins();
276
-
277
- $tp_widgets = array();
278
- $widget_root = $this->transposh->transposh_plugin_dir . "widgets";
279
- if (!empty($widget_folder)) $widget_root .= $widget_folder;
280
-
281
- // Files in wp-content/widgets directory
282
- $widgets_dir = @opendir($widget_root);
283
- $widget_files = array();
284
- if ($widgets_dir) {
285
- while (($file = readdir($widgets_dir) ) !== false) {
286
- if (substr($file, 0, 1) == '.') continue;
287
- if (is_dir($widget_root . '/' . $file)) {
288
- $widgets_subdir = @ opendir($widget_root . '/' . $file);
289
- if ($widgets_subdir) {
290
- while (($subfile = readdir($widgets_subdir) ) !== false) {
291
- if (substr($subfile, 0, 1) == '.') continue;
292
- if (substr($subfile, 0, 4) == TRANSPOSH_WIDGET_PREFIX && substr($subfile, -4) == '.php')
293
- $widget_files[] = "$file/$subfile";
294
- }
295
- }
296
- }
297
- if (substr($file, 0, 4) == TRANSPOSH_WIDGET_PREFIX && substr($file, -4) == '.php')
298
- $widget_files[] = $file;
299
- }
300
- } else {
301
- return $tp_widgets;
302
- }
303
-
304
- @closedir($widgets_dir);
305
- @closedir($widgets_subdir);
306
-
307
- if (empty($widget_files)) return $tp_widgets;
308
-
309
- foreach ($widget_files as $widget_file) {
310
- if (!is_readable("$widget_root/$widget_file")) continue;
311
-
312
- $widget_data = get_plugin_data("$widget_root/$widget_file", false, false); //Do not apply markup/translate as it'll be cached.
313
-
314
- if (empty($widget_data['Name'])) continue;
315
-
316
- $tp_widgets[plugin_basename($widget_file)] = $widget_data;
317
- }
318
-
319
- uasort($tp_widgets, create_function('$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );'));
320
-
321
- return $tp_widgets;
322
  }
323
 
324
  /**
325
  * This is the widget control, allowing the selection of presentation type.
326
  */
327
  function transposh_widget_control() {
328
- if (isset($_POST['transposh-submit'])) $this->transposh_widget_post();
329
-
330
- $widgets = $this->get_widgets();
331
-
332
- echo '<p><label for="' . WIDGET_FILE . '">Style:<br />' .
333
- '<select id="transposh-style" name="' . WIDGET_FILE . '">';
334
- foreach ($widgets as $file => $widget) {
335
-
336
- $selected = ($this->transposh->options->get_widget_file() == $file) ? ' selected="selected"' : '';
337
- echo "<option value=\"$file\"$selected>{$widget['Name']}</option>";
338
- }
339
- echo '</select>' .
340
- '</label></p>' .
341
- '<p><label for="transposh-progress">Effects:</label><br/>' .
342
- '<input type="checkbox" id="' . WIDGET_PROGRESSBAR . '" name="' . WIDGET_PROGRESSBAR . '"' . ($this->transposh->options->get_widget_progressbar() ? ' checked="checked"' : '') . '/>' .
343
- '<span style="border-bottom: 1px dotted #333; cursor: help; margin-left: 4px" title="Show progress bar when a client triggers automatic translation">Show progress bar</span><br/>' .
344
- '<input type="checkbox" id="' . WIDGET_ALLOW_SET_DEFLANG . '" name="' . WIDGET_ALLOW_SET_DEFLANG . '"' . ($this->transposh->options->get_widget_allow_set_default_language() ? ' checked="checked"' : '') . '/>' .
345
- '<span style="border-bottom: 1px dotted #333; cursor: help; margin-left: 4px" title="Widget will allow setting this language as user default.">Allow user to set current language as default</span><br/>' .
346
- '</p>' .
347
- '<input type="hidden" name="transposh-submit" id="transposh-submit" value="1"/>';
 
 
348
  }
349
 
350
  }
35
 
36
  //constructor of class, PHP4 compatible construction for backward compatibility
37
  function transposh_plugin_widget(&$transposh) {
38
+ //Register callback for WordPress events
39
+ $this->transposh = &$transposh;
40
+ add_action('init', array(&$this, 'init_transposh'), 1);
41
+ add_action('widgets_init', array(&$this, 'transposh_widget_init'));
42
  }
43
 
44
  /**
45
  * Intercept init calls to see if it was posted by the widget.
46
  */
47
  function init_transposh() {
48
+ if (isset($_POST['transposh_widget_posted'])) {
49
+
50
+
51
+ $ref = getenv('HTTP_REFERER');
52
+ $lang = $_POST[LANG_PARAM];
53
+ if ($lang == '') {
54
+ $lang = get_language_from_url($_SERVER['HTTP_REFERER'], $this->transposh->home_url);
55
+ }
56
+ if ($lang == $this->transposh->options->get_default_language() || $lang == "none")
57
+ $lang = '';
58
+
59
+
60
+ // first, we might need to get the original url back
61
+ if ($this->transposh->options->get_enable_url_translate()) {
62
+ $ref = get_original_url($ref, $this->transposh->home_url, get_language_from_url($ref, $this->transposh->home_url), array($this->transposh->database, 'fetch_original'));
63
+ }
64
+
65
+ //remove existing language settings.
66
+ $ref = cleanup_url($ref, $this->transposh->home_url);
67
+
68
+
69
+ if ($lang && $this->transposh->options->get_enable_url_translate()) {
70
+ // and then, we might have to translate it
71
+ $ref = translate_url($ref, $this->transposh->home_url, $lang, array(&$this->transposh->database, 'fetch_translation'));
72
+ $ref = str_replace(array('%2F', '%3A', '%3B', '%3F', '%3D', '%26'), array('/', ':', ';', '?', '=', '&'), urlencode($ref));
73
+
74
+ }
75
+ $ref = rewrite_url_lang_param($ref, $this->transposh->home_url, $this->transposh->enable_permalinks_rewrite, $lang, $_POST[EDIT_PARAM]);
76
+
77
+
78
+
79
+ wp_redirect($ref);
80
+ exit;
81
+ }
82
  }
83
 
84
  /**
85
  * Register the widget.
86
  */
87
  function transposh_widget_init() {
88
+
89
+ if (!function_exists('register_sidebar_widget')) {
90
+ return;
91
+ }
92
 
93
+ // Register widget
94
+ register_sidebar_widget(array('Transposh', 'widgets'), array(&$this, 'transposh_widget'));
95
 
96
+ // Register widget control
97
+ register_widget_control("Transposh", array(&$this, 'transposh_widget_control'));
98
 
99
+ // Register callback for widget's css and js
100
+ add_action('wp_print_styles', array(&$this, 'add_transposh_widget_css'));
101
+ add_action('wp_print_scripts', array(&$this, 'add_transposh_widget_js'));
102
  }
103
 
104
  /**
105
  * Loads the widget code
106
  */
107
  function load_widget() {
108
+ // avoid dual loadings
109
+ if ($this->base_widget_file_name) return;
110
+
111
+ $file = $this->transposh->options->get_widget_file();
112
+ $widget_src = $this->transposh->transposh_plugin_dir . TRANSPOSH_DIR_WIDGETS . '/' . $file;
113
+ if ($file && file_exists($widget_src)) {
114
+ include_once $widget_src;
115
+ } else {
116
+ $file = 'tpw_default.php';
117
+ include_once $this->transposh->transposh_plugin_dir . TRANSPOSH_DIR_WIDGETS . '/' . $file;
118
+ }
119
+ $this->base_widget_file_name = substr($file, 0, -4);
120
  }
121
 
122
  /**
123
  * Add custom css, i.e. transposh_widget.css, flags now override widget
124
  */
125
  function add_transposh_widget_css() { //TODO ! goway
126
+ $this->load_widget();
127
+
128
+ if (function_exists(tp_widget_css)) {
129
+ tp_widget_css();
130
+ } else {
131
+ $widget_css = TRANSPOSH_DIR_WIDGETS . '/' . $this->base_widget_file_name . ".css";
132
+ if (file_exists($this->transposh->transposh_plugin_dir . $widget_css)) {
133
+ wp_enqueue_style('transposh_widget', $this->transposh->transposh_plugin_url . '/' . $widget_css, '', TRANSPOSH_PLUGIN_VER);
134
+ }
135
+ }
136
+
137
+
138
  }
139
 
140
  /**
141
  * Add custom css, i.e. transposh_widget.css, flags now override widget
142
  */
143
  function add_transposh_widget_js() { //TODO ! goway
144
+ $this->load_widget();
145
+
146
+ if (function_exists(tp_widget_js)) {
147
+ tp_widget_js();
148
+ } else {
149
+ $widget_js = TRANSPOSH_DIR_WIDGETS . '/' . $this->base_widget_file_name . ".js";
150
+ if (file_exists($this->transposh->transposh_plugin_dir . $widget_js)) {
151
+ wp_enqueue_script('transposh_widget', $this->transposh->transposh_plugin_url . '/' . $widget_js, '', TRANSPOSH_PLUGIN_VER);
152
+ }
153
+ }
154
+
155
  }
156
 
157
  /**
159
  * @param array $args Contains such as $before_widget, $after_widget, $before_title, $after_title, etc
160
  */
161
  function transposh_widget($args) {
162
+ $this->load_widget();
163
+
164
+ // hmmm, this should actually prepare all vars needed, include the correct widget and send the vars to that function,
165
+ $calc_url = false; // By default, avoid calculating the urls
166
+ if (function_exists(tp_widget_needs_post_url))
167
+ $calc_url = tp_widget_needs_post_url();
168
+
169
+ $widget_args = array();
170
+ $page_url = $_SERVER['REQUEST_URI'];
171
+
172
+ //remove any language identifier and find the "clean" url, used for posting and calculating urls if needed
173
+ $clean_page_url = cleanup_url($page_url, $this->transposh->home_url, true);
174
+ // we need this if we are using url translations
175
+ if ($this->transposh->options->get_enable_url_translate() && $calc_url) {
176
+ $clean_page_url = get_original_url($clean_page_url, '', $this->transposh->target_language, array($this->transposh->database, 'fetch_original'));
177
+ }
178
+
179
+
180
+ // loop on the languages
181
+ foreach ($this->transposh->options->get_sorted_langs() as $code => $langrecord) {
182
+ list ($langname, $language, $flag) = explode(',', $langrecord);
183
+
184
+ // Only send languages which are viewable or (editable and the user is a translator)
185
+ if ($this->transposh->options->is_viewable_language($code) ||
186
+ ($this->transposh->options->is_editable_language($code) && $this->transposh->is_translator()) ||
187
+ ($this->transposh->options->is_default_language($code))) {
188
+ if ($this->transposh->options->get_enable_url_translate() && $calc_url) {
189
+ $page_url = translate_url($clean_page_url, '', $code, array(&$this->transposh->database, 'fetch_translation'));
190
+ } else {
191
+ $page_url = $clean_page_url;
192
+ }
193
+ // clean $code in default lanaguge
194
+ if ($calc_url)
195
+ $page_url = rewrite_url_lang_param($page_url, $this->transposh->home_url, $this->transposh->enable_permalinks_rewrite, ($code == $this->transposh->options->get_default_language()) ? '' : $code, $this->transposh->edit_mode);
196
+ $widget_args[] = array(
197
+ 'lang' => $langname,
198
+ 'langorig' => $language,
199
+ 'flag' => $flag,
200
+ 'isocode' => $code,
201
+ 'url' => $page_url,
202
+ 'active' => ($this->transposh->target_language == $code));
203
+ }
204
+ }
205
+ // at this point the widget args are ready
206
+
207
+
208
+
209
+ // extract args given by wordpress
210
+ extract($args);
211
+
212
+
213
+ // widget default title
214
+ echo $before_widget . $before_title . __('Translation') . $after_title;
215
+
216
+ // the widget is inside a form used for posting a language change or edit request
217
+ echo '<form id="tp_form" action="' . $clean_page_url . '" method="post">';
218
+
219
+ // actually run the external widget code
220
+ tp_widget_do($widget_args);
221
+
222
+ //at least one language showing - add the edit box if applicable
223
+ if (!empty($widget_args)) {
224
+ // this is the set default language line
225
+ if ($this->transposh->options->get_widget_allow_set_default_language()) {
226
+ If ((isset($_COOKIE['TR_LNG']) && $_COOKIE['TR_LNG'] != $this->transposh->target_language) || (!isset($_COOKIE['TR_LNG']) && !$this->transposh->options->is_default_language($this->transposh->target_language))) {
227
+ echo '<a id="' . SPAN_PREFIX . 'setdeflang" onClick="return false;" href="' . $this->transposh->post_url . '?tr_cookie_bck">Set as default language</a><br/>';
228
+ }
229
+ }
230
+ // add the edit checkbox only for translators for languages marked as editable
231
+ if ($this->transposh->is_editing_permitted()) {
232
+ echo '<input type="checkbox" name="' . EDIT_PARAM . '" value="1" ' .
233
+ ($this->transposh->edit_mode ? 'checked="checked"' : '') .
234
+ ' onclick="this.form.submit();"/>&nbsp;Edit Translation';
235
+ }
236
+
237
+ echo '<input type="hidden" name="transposh_widget_posted" value="1"/>';
238
+ } else {
239
+ //no languages configured - error message
240
+ echo '<p>No languages available for display. Check the Transposh settings (Admin).</p>';
241
+ }
242
+
243
+ echo "</form>";
244
+
245
+ // Now this is a comment for those wishing to remove our logo (tplogo.png) and link (transposh.org) from the widget
246
+ // first - according to the gpl, you may do so - but since the code has changed - please make in available under the gpl
247
+ // second - we did invest a lot of time and effort into this, and the link is a way to help us grow and show your appreciation, if it
248
+ // upsets you, feel more than free to move this link somewhere else on your page, such as the footer etc.
249
+ // third - feel free to write your own widget, the translation core will work
250
+ // forth - you can ask for permission, with a good reason, if you contributed to the code - it's a good enough reason :)
251
+ // fifth - if you just delete the following line, it means that you have little respect to the whole copyright thing, which as far as we
252
+ // understand means that by doing so - you are giving everybody else the right to do the same and use your work without any attribution
253
+ // last - you can now remove the logo in exchange to a few percentage of ad and affiliate revenues on your pages, isn't that better?
254
+ $plugpath = parse_url($this->transposh->transposh_plugin_url, PHP_URL_PATH);
255
+
256
+ echo '<div id="' . SPAN_PREFIX . 'credit">';
257
+ if (!$this->transposh->options->get_widget_remove_logo()) {
258
+ echo 'by <a href="http://tran' . 'sposh.org"><img class="' . NO_TRANSLATE_CLASS . '" height="16" width="16" src="' .
259
+ $plugpath . '/img/tplog' . 'o.png" style="padding:1px;border:0px" title="Transposh" alt="Transposh"/></a>';
260
+ }
261
+ echo '</div>';
262
+ echo $after_widget;
263
  }
264
 
265
  function transposh_widget_post($save = true) {
266
+
267
+
268
+ $this->transposh->options->set_widget_file($_POST[WIDGET_FILE]);
269
+ $this->transposh->options->set_widget_progressbar($_POST[WIDGET_PROGRESSBAR]);
270
+ $this->transposh->options->set_widget_allow_set_default_language($_POST[WIDGET_ALLOW_SET_DEFLANG]);
271
+ $this->transposh->options->set_widget_remove_logo($_POST[WIDGET_REMOVE_LOGO_FOR_AD]);
272
+ if ($save) $this->transposh->options->update_options();
273
+ // Avoid coming here twice...
274
+ unset($_POST['transposh-submit']);
275
  }
276
 
277
  /**
278
  * Inspired (and used code) from the get_plugins function of wordpress
279
  */
280
  function get_widgets($widget_folder = '') {
281
+ get_plugins();
282
+
283
+ $tp_widgets = array();
284
+ $widget_root = $this->transposh->transposh_plugin_dir . "widgets";
285
+ if (!empty($widget_folder)) $widget_root .= $widget_folder;
286
+
287
+ // Files in wp-content/widgets directory
288
+ $widgets_dir = @opendir($widget_root);
289
+ $widget_files = array();
290
+ if ($widgets_dir) {
291
+ while (($file = readdir($widgets_dir) ) !== false) {
292
+ if (substr($file, 0, 1) == '.') continue;
293
+ if (is_dir($widget_root . '/' . $file)) {
294
+ $widgets_subdir = @ opendir($widget_root . '/' . $file);
295
+ if ($widgets_subdir) {
296
+ while (($subfile = readdir($widgets_subdir) ) !== false) {
297
+ if (substr($subfile, 0, 1) == '.') continue;
298
+ if (substr($subfile, 0, 4) == TRANSPOSH_WIDGET_PREFIX && substr($subfile, -4) == '.php')
299
+ $widget_files[] = "$file/$subfile";
300
+ }
301
+ }
302
+ }
303
+ if (substr($file, 0, 4) == TRANSPOSH_WIDGET_PREFIX && substr($file, -4) == '.php')
304
+ $widget_files[] = $file;
305
+ }
306
+ } else {
307
+ return $tp_widgets;
308
+ }
309
+
310
+ @closedir($widgets_dir);
311
+ @closedir($widgets_subdir);
312
+
313
+ if (empty($widget_files)) return $tp_widgets;
314
+
315
+ foreach ($widget_files as $widget_file) {
316
+ if (!is_readable("$widget_root/$widget_file")) continue;
317
+
318
+ $widget_data = get_plugin_data("$widget_root/$widget_file", false, false); //Do not apply markup/translate as it'll be cached.
319
+
320
+ if (empty($widget_data['Name'])) continue;
321
+
322
+ $tp_widgets[plugin_basename($widget_file)] = $widget_data;
323
+ }
324
+
325
+ uasort($tp_widgets, create_function('$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );'));
326
+
327
+ return $tp_widgets;
328
  }
329
 
330
  /**
331
  * This is the widget control, allowing the selection of presentation type.
332
  */
333
  function transposh_widget_control() {
334
+ if (isset($_POST['transposh-submit'])) $this->transposh_widget_post();
335
+
336
+ $widgets = $this->get_widgets();
337
+
338
+ echo '<p><label for="' . WIDGET_FILE . '">Style:<br />' .
339
+ '<select id="transposh-style" name="' . WIDGET_FILE . '">';
340
+ foreach ($widgets as $file => $widget) {
341
+
342
+ $selected = ($this->transposh->options->get_widget_file() == $file) ? ' selected="selected"' : '';
343
+ echo "<option value=\"$file\"$selected>{$widget['Name']}</option>";
344
+ }
345
+ echo '</select>' .
346
+ '</label></p>' .
347
+ '<p><label for="transposh-progress">Effects:</label><br/>' .
348
+ '<input type="checkbox" id="' . WIDGET_PROGRESSBAR . '" name="' . WIDGET_PROGRESSBAR . '"' . ($this->transposh->options->get_widget_progressbar() ? ' checked="checked"' : '') . '/>' .
349
+ '<span style="border-bottom: 1px dotted #333; cursor: help; margin-left: 4px" title="Show progress bar when a client triggers automatic translation">Show progress bar</span><br/>' .
350
+ '<input type="checkbox" id="' . WIDGET_ALLOW_SET_DEFLANG . '" name="' . WIDGET_ALLOW_SET_DEFLANG . '"' . ($this->transposh->options->get_widget_allow_set_default_language() ? ' checked="checked"' : '') . '/>' .
351
+ '<span style="border-bottom: 1px dotted #333; cursor: help; margin-left: 4px" title="Widget will allow setting this language as user default.">Allow user to set current language as default</span><br/>' .
352
+ '<input type="checkbox" id="' . WIDGET_REMOVE_LOGO_FOR_AD . '" name="' . WIDGET_REMOVE_LOGO_FOR_AD . '"' . ($this->transposh->options->get_widget_remove_logo() ? ' checked="checked"' : '') . '/>' .
353
+ '<span style="border-bottom: 1px dotted #333; cursor: help; margin-left: 4px" title="Transposh logo will be eliminated from widget.">Remove transposh logo (see <a href="http://transposh.org/logoterms">terms</a>)</span><br/>' .
354
+ '</p>' .
355
+ '<input type="hidden" name="transposh-submit" id="transposh-submit" value="1"/>';
356
  }
357
 
358
  }