Version Description
Download this release
Release Info
Developer | oferwald |
Plugin | Transposh WordPress Translation |
Version | 0.0.3 |
Comparing to | |
See all releases |
Code changes from version 0.0.2 to 0.0.3
- js/transposh.js +12 -2
- parser.php +639 -502
- readme.txt +6 -3
- transposh.php +119 -90
- transposh_widget.php +7 -8
js/transposh.js
CHANGED
@@ -44,7 +44,17 @@ function hint(original)
|
|
44 |
TEXTFONTCLASS,'oltxtD',
|
45 |
AUTOSTATUS,WRAP);
|
46 |
}
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
//Open translation dialog
|
49 |
function translate_dialog(original, trans, lang, post_url, segment_id)
|
50 |
{
|
@@ -59,7 +69,7 @@ var dialog = ''+
|
|
59 |
'<input type="hidden" id="tr_original" name="original" value="' + escape(original) +'">' +
|
60 |
'<input type="hidden" id="tr_lang" name="lang" value="'+lang+'">' +
|
61 |
'<input type="hidden" name="translation_posted" value= "1">' +
|
62 |
-
'<p><input type="submit" value="Translate"
|
63 |
('<\/div><\/form>');
|
64 |
|
65 |
display_dialog(caption, dialog);
|
44 |
TEXTFONTCLASS,'oltxtD',
|
45 |
AUTOSTATUS,WRAP);
|
46 |
}
|
47 |
+
|
48 |
+
// fetch translation from google translate...
|
49 |
+
function getgt(lang)
|
50 |
+
{
|
51 |
+
google.language.translate($("#tr_original_unescaped").text(), "", lang, function(result) {
|
52 |
+
if (!result.error) {
|
53 |
+
$("#tr_translation").attr('value',result.translation);
|
54 |
+
}
|
55 |
+
});
|
56 |
+
}
|
57 |
+
|
58 |
//Open translation dialog
|
59 |
function translate_dialog(original, trans, lang, post_url, segment_id)
|
60 |
{
|
69 |
'<input type="hidden" id="tr_original" name="original" value="' + escape(original) +'">' +
|
70 |
'<input type="hidden" id="tr_lang" name="lang" value="'+lang+'">' +
|
71 |
'<input type="hidden" name="translation_posted" value= "1">' +
|
72 |
+
'<p><input onclick="getgt(\''+lang+'\')" type="button" value="Get Suggestion!"/> <input type="submit" value="Translate"/><\/p>' +
|
73 |
('<\/div><\/form>');
|
74 |
|
75 |
display_dialog(caption, dialog);
|
parser.php
CHANGED
@@ -20,31 +20,31 @@
|
|
20 |
* Contains the core functionality of the html parser. I.e. break into translation segments,
|
21 |
* fetch translation and update the translated page.
|
22 |
* This file should include only general purpose parser functionality while using callbacks
|
23 |
-
* to obtain WorkdPress specific capabilities, e.g. db access.
|
24 |
*/
|
25 |
|
26 |
|
27 |
require_once("constants.php");
|
28 |
|
29 |
-
//The language to which the current page will be translated to.
|
30 |
$lang;
|
31 |
-
|
32 |
//The html page which starts contains the content being translated
|
33 |
$page;
|
34 |
-
|
35 |
//Marks the current position of the translation process within the page
|
36 |
$pos = 0;
|
37 |
|
38 |
//Contains the stack of tag in the current position within the page
|
39 |
$tags_list = array();
|
40 |
|
41 |
-
//The translated html page
|
42 |
$tr_page;
|
43 |
-
|
44 |
-
//Points to the last character that have been copied from the original to the translated page.
|
45 |
$tr_mark = 0;
|
46 |
|
47 |
-
//Is the current use is in edit mode.
|
48 |
$is_edit_mode = FALSE;
|
49 |
|
50 |
//Segment identifier within tags (span/img) mainly for use by js code on the client
|
@@ -53,128 +53,134 @@ $segment_id = 0;
|
|
53 |
//Is current position within the body tag
|
54 |
$is_in_body = FALSE;
|
55 |
|
|
|
|
|
|
|
56 |
/*
|
57 |
* Parse the html page into tags, identify translateable string which
|
58 |
-
* will be translated.
|
59 |
*/
|
60 |
function process_html()
|
61 |
{
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
|
154 |
/*
|
155 |
* Determine if the specified element should be skipped. If so the position
|
156 |
* is moved past end of tag.
|
157 |
-
* Return TRUE if element is skipped otherwise FALSE.
|
158 |
*/
|
159 |
function should_skip_element(&$element)
|
160 |
{
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
}
|
179 |
|
180 |
/*
|
@@ -183,26 +189,28 @@ function should_skip_element(&$element)
|
|
183 |
*/
|
184 |
function process_tag_init(&$element, $start, $end)
|
185 |
{
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
|
|
|
|
206 |
}
|
207 |
|
208 |
|
@@ -213,55 +221,55 @@ function process_tag_init(&$element, $start, $end)
|
|
213 |
*/
|
214 |
function process_span_or_div_tag(&$element, $start, $end)
|
215 |
{
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
}
|
233 |
|
234 |
|
235 |
/*
|
236 |
-
* Process html tag. Set the direction for rtl languages.
|
237 |
*
|
238 |
*/
|
239 |
function process_html_tag($start, $end)
|
240 |
{
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
}
|
266 |
|
267 |
|
@@ -271,33 +279,40 @@ function process_html_tag($start, $end)
|
|
271 |
*/
|
272 |
function process_tag_termination(&$element)
|
273 |
{
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
}
|
278 |
|
279 |
|
280 |
/*
|
281 |
-
* Return the element id within the current tag.
|
282 |
*/
|
283 |
function get_element()
|
284 |
{
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
}
|
302 |
|
303 |
/*
|
@@ -305,60 +320,60 @@ function get_element()
|
|
305 |
* end position within the buffer.
|
306 |
* Returns the string containing the attribute if available otherwise NULL.
|
307 |
* In addition the start and end position are moved to boundaries of the
|
308 |
-
* attribute's value.
|
309 |
*/
|
310 |
function get_attribute(&$start, &$end, $id)
|
311 |
{
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
}
|
363 |
|
364 |
/*
|
@@ -368,48 +383,120 @@ function get_attribute(&$start, &$end, $id)
|
|
368 |
*/
|
369 |
function process_current_tag()
|
370 |
{
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
411 |
}
|
412 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
413 |
|
414 |
/*
|
415 |
* Determine if the current position in buffer is a sentence breaker, e.g. '.' or ',' .
|
@@ -418,68 +505,72 @@ function process_current_tag()
|
|
418 |
*/
|
419 |
function is_sentence_breaker($position)
|
420 |
{
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
|
|
|
|
|
|
444 |
}
|
445 |
|
446 |
/*
|
447 |
* Determines if the current position marks the begining of an html
|
448 |
* entity. E.g &
|
449 |
-
* Return 0 if not an html entity otherwise return the position past this
|
450 |
-
*
|
451 |
*
|
452 |
*/
|
453 |
-
function is_html_entity($position)
|
454 |
{
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
|
|
483 |
}
|
484 |
|
485 |
|
@@ -492,15 +583,15 @@ function is_html_entity($position)
|
|
492 |
|
493 |
function is_a_to_z_character($position)
|
494 |
{
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
}
|
505 |
|
506 |
/*
|
@@ -509,119 +600,165 @@ function is_a_to_z_character($position)
|
|
509 |
*/
|
510 |
function is_digit($position)
|
511 |
{
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
}
|
521 |
-
|
522 |
/*
|
523 |
-
* Determine if the current position in buffer is a white space.
|
524 |
* return TRUE if current position marks a white space otherwise FALSE.
|
525 |
-
*/
|
526 |
function is_white_space($position)
|
527 |
{
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
}
|
538 |
|
539 |
/*
|
540 |
* Skip within buffer past unreadable characters , i.e. white space
|
541 |
* and characters considred to be a sentence breaker. Staring from the specified
|
542 |
-
* position going either forward or backward.
|
543 |
-
* param forward - indicate direction going either backward of forward.
|
544 |
*/
|
545 |
function skip_unreadable_chars(&$index, $forward=TRUE)
|
546 |
{
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
}
|
564 |
|
565 |
/*
|
566 |
* Skip within buffer past white space characters , Staring from the specified
|
567 |
-
* position going either forward or backward.
|
568 |
-
* param forward - indicate direction going either backward of forward.
|
569 |
*/
|
570 |
function skip_white_space(&$index, $forward=TRUE)
|
571 |
{
|
572 |
-
|
573 |
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
|
585 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
}
|
587 |
|
|
|
588 |
/**
|
589 |
* Translate the text between the given start position and the current
|
590 |
-
* position (pos) within the buffer.
|
591 |
*/
|
592 |
function translate_text($start)
|
593 |
{
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
}
|
626 |
|
627 |
/*
|
@@ -633,46 +770,46 @@ function translate_text($start)
|
|
633 |
*/
|
634 |
function insert_translation(&$original_text, &$translated_text, $start, $end)
|
635 |
{
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
}
|
677 |
|
678 |
|
@@ -683,17 +820,17 @@ function insert_translation(&$original_text, &$translated_text, $start, $end)
|
|
683 |
*/
|
684 |
function scrub_text(&$text)
|
685 |
{
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
|
693 |
-
|
694 |
-
|
695 |
|
696 |
-
|
697 |
}
|
698 |
|
699 |
|
@@ -703,29 +840,29 @@ function scrub_text(&$text)
|
|
703 |
* back in buffer.
|
704 |
* param start - marks the starting position of the replaced string in the original page.
|
705 |
* param end - marks the end position of the replaced string in the original page.
|
706 |
-
|
707 |
* param translated_text - text to be inserted.
|
708 |
*/
|
709 |
function update_translated_page($start, $end, $translated_text)
|
710 |
{
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
}
|
730 |
|
731 |
?>
|
20 |
* Contains the core functionality of the html parser. I.e. break into translation segments,
|
21 |
* fetch translation and update the translated page.
|
22 |
* This file should include only general purpose parser functionality while using callbacks
|
23 |
+
* to obtain WorkdPress specific capabilities, e.g. db access.
|
24 |
*/
|
25 |
|
26 |
|
27 |
require_once("constants.php");
|
28 |
|
29 |
+
//The language to which the current page will be translated to.
|
30 |
$lang;
|
31 |
+
|
32 |
//The html page which starts contains the content being translated
|
33 |
$page;
|
34 |
+
|
35 |
//Marks the current position of the translation process within the page
|
36 |
$pos = 0;
|
37 |
|
38 |
//Contains the stack of tag in the current position within the page
|
39 |
$tags_list = array();
|
40 |
|
41 |
+
//The translated html page
|
42 |
$tr_page;
|
43 |
+
|
44 |
+
//Points to the last character that have been copied from the original to the translated page.
|
45 |
$tr_mark = 0;
|
46 |
|
47 |
+
//Is the current use is in edit mode.
|
48 |
$is_edit_mode = FALSE;
|
49 |
|
50 |
//Segment identifier within tags (span/img) mainly for use by js code on the client
|
53 |
//Is current position within the body tag
|
54 |
$is_in_body = FALSE;
|
55 |
|
56 |
+
//Is current position within the channel tag, i.e. RSS feed
|
57 |
+
$is_in_channel = FALSE;
|
58 |
+
|
59 |
/*
|
60 |
* Parse the html page into tags, identify translateable string which
|
61 |
+
* will be translated.
|
62 |
*/
|
63 |
function process_html()
|
64 |
{
|
65 |
+
|
66 |
+
|
67 |
+
global $page, $tr_page, $pos, $tags_list, $lang;
|
68 |
+
$no_translate = 0;
|
69 |
+
$page_length = strlen($page);
|
70 |
+
|
71 |
+
while($pos < $page_length)
|
72 |
+
{
|
73 |
+
//find beginning of next tag
|
74 |
+
$pos = strpos($page, '<', $pos);
|
75 |
+
if($pos === FALSE)
|
76 |
+
{
|
77 |
+
//
|
78 |
+
break;
|
79 |
+
}
|
80 |
+
$pos++;
|
81 |
+
|
82 |
+
//Get the element identifying this tag
|
83 |
+
$element = get_element();
|
84 |
+
|
85 |
+
if(should_skip_element($element))
|
86 |
+
{
|
87 |
+
|
88 |
+
//do nothing
|
89 |
+
}
|
90 |
+
else if($element == '![CDATA[')
|
91 |
+
{
|
92 |
+
process_cdata_section();
|
93 |
+
}
|
94 |
+
else
|
95 |
+
{
|
96 |
+
//Mark tag start position
|
97 |
+
$tag_start = $pos;
|
98 |
+
$pos = strpos($page, '>', $pos);
|
99 |
+
|
100 |
+
//Mark tag end position
|
101 |
+
$tag_end = $pos;
|
102 |
+
|
103 |
+
if($page[$pos-1] == '/')
|
104 |
+
{
|
105 |
+
//single line tag - no need to update tags list
|
106 |
+
process_tag_init($element, $tag_start, $tag_end);
|
107 |
+
}
|
108 |
+
else if($element[0] != '/')
|
109 |
+
{
|
110 |
+
if(!$no_translate)
|
111 |
+
{
|
112 |
+
process_tag_init($element, $tag_start, $tag_end);
|
113 |
+
}
|
114 |
+
|
115 |
+
$tags_list[] = $element;
|
116 |
+
|
117 |
+
//Look for the no translate class
|
118 |
+
if(stripos($element, NO_TRANSLATE_CLASS) !== FALSE)
|
119 |
+
{
|
120 |
+
$no_translate++;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
else
|
124 |
+
{
|
125 |
+
$popped_element = array_pop($tags_list);
|
126 |
+
if(!$no_translate)
|
127 |
+
{
|
128 |
+
process_tag_termination($element);
|
129 |
+
}
|
130 |
+
|
131 |
+
//Look for the no translate class
|
132 |
+
if(stripos($popped_element, NO_TRANSLATE_CLASS) !== FALSE)
|
133 |
+
{
|
134 |
+
$no_translate--;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
$pos++;
|
139 |
+
|
140 |
+
//skip processing while enclosed within a tag marked by no_translate
|
141 |
+
if(!$no_translate)
|
142 |
+
{
|
143 |
+
process_current_tag();
|
144 |
+
}
|
145 |
+
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
if(strlen($tr_page) > 0)
|
150 |
+
{
|
151 |
+
//Some translation has been taken place. Complete the translated
|
152 |
+
//page up to the full contents of the original page.
|
153 |
+
update_translated_page(strlen($page), -1, "");
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
}
|
158 |
|
159 |
|
160 |
/*
|
161 |
* Determine if the specified element should be skipped. If so the position
|
162 |
* is moved past end of tag.
|
163 |
+
* Return TRUE if element is skipped otherwise FALSE.
|
164 |
*/
|
165 |
function should_skip_element(&$element)
|
166 |
{
|
167 |
+
global $page, $pos;
|
168 |
+
$rc = TRUE;
|
169 |
+
|
170 |
+
if(strncmp($element, "!DOCTYPE", 8) == 0)
|
171 |
+
{
|
172 |
+
$pos = strpos($page, '>', $pos);
|
173 |
+
}
|
174 |
+
else if(strncmp($element, "!--", 3) == 0)
|
175 |
+
{
|
176 |
+
$pos = strpos($page, '-->', $pos);
|
177 |
+
}
|
178 |
+
else
|
179 |
+
{
|
180 |
+
$rc = FALSE;
|
181 |
+
}
|
182 |
+
|
183 |
+
return $rc;
|
184 |
}
|
185 |
|
186 |
/*
|
189 |
*/
|
190 |
function process_tag_init(&$element, $start, $end)
|
191 |
{
|
192 |
+
switch ($element)
|
193 |
+
{
|
194 |
+
case 'a':
|
195 |
+
process_anchor_tag($start, $end);
|
196 |
+
break;
|
197 |
+
case 'div' :
|
198 |
+
case 'span':
|
199 |
+
process_span_or_div_tag($element, $start, $end);
|
200 |
+
break;
|
201 |
+
case 'html':
|
202 |
+
process_html_tag($start, $end);
|
203 |
+
break;
|
204 |
+
case 'body':
|
205 |
+
global $is_in_body;
|
206 |
+
$is_in_body = TRUE;
|
207 |
+
break;
|
208 |
+
case 'channel':
|
209 |
+
global $is_in_channel;
|
210 |
+
$is_in_channel = TRUE;
|
211 |
+
break;
|
212 |
+
}
|
213 |
+
|
214 |
}
|
215 |
|
216 |
|
221 |
*/
|
222 |
function process_span_or_div_tag(&$element, $start, $end)
|
223 |
{
|
224 |
+
|
225 |
+
$cls = get_attribute($start, $end, 'class');
|
226 |
+
|
227 |
+
if($cls == NULL)
|
228 |
+
{
|
229 |
+
return;
|
230 |
+
}
|
231 |
+
|
232 |
+
//Look for the no translate class
|
233 |
+
if(stripos($cls, NO_TRANSLATE_CLASS) === FALSE)
|
234 |
+
{
|
235 |
+
return;
|
236 |
+
}
|
237 |
+
|
238 |
+
//Mark the element as not translatable
|
239 |
+
$element .= "." . NO_TRANSLATE_CLASS;
|
240 |
}
|
241 |
|
242 |
|
243 |
/*
|
244 |
+
* Process html tag. Set the direction for rtl languages.
|
245 |
*
|
246 |
*/
|
247 |
function process_html_tag($start, $end)
|
248 |
{
|
249 |
+
global $lang, $rtl_languages;
|
250 |
+
|
251 |
+
if(!(in_array ($lang, $rtl_languages)))
|
252 |
+
{
|
253 |
+
return;
|
254 |
+
}
|
255 |
+
|
256 |
+
$dir = get_attribute($start, $end, 'dir');
|
257 |
+
|
258 |
+
if($dir == NULL)
|
259 |
+
{
|
260 |
+
|
261 |
+
//attribute does not exist - add it
|
262 |
+
update_translated_page($end, -1, 'dir="rtl"');
|
263 |
+
}
|
264 |
+
else
|
265 |
+
{
|
266 |
+
$dir = 'rtl';
|
267 |
+
|
268 |
+
//rewrite url in translated page
|
269 |
+
update_translated_page($start, $end, $dir);
|
270 |
+
|
271 |
+
}
|
272 |
+
|
273 |
}
|
274 |
|
275 |
|
279 |
*/
|
280 |
function process_tag_termination(&$element)
|
281 |
{
|
282 |
+
global $pos, $tags_list, $page;
|
283 |
+
|
284 |
+
|
285 |
}
|
286 |
|
287 |
|
288 |
/*
|
289 |
+
* Return the element id within the current tag.
|
290 |
*/
|
291 |
function get_element()
|
292 |
{
|
293 |
+
global $page, $pos;
|
294 |
+
|
295 |
+
|
296 |
+
skip_white_space();
|
297 |
+
|
298 |
+
$start = $pos;
|
299 |
+
|
300 |
+
//check first for a character data section - treat it like an element
|
301 |
+
if(is_word('![CDATA['))
|
302 |
+
{
|
303 |
+
$pos += 8; //skip to end of ![CDATA[
|
304 |
+
}
|
305 |
+
else
|
306 |
+
{
|
307 |
+
//keep scanning till the first white space or the '>' mark
|
308 |
+
while($pos < strlen($page) && !is_white_space($pos) && $page[$pos] != '>')
|
309 |
+
{
|
310 |
+
$pos++;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
|
315 |
+
return substr($page,$start, $pos - $start);
|
316 |
}
|
317 |
|
318 |
/*
|
320 |
* end position within the buffer.
|
321 |
* Returns the string containing the attribute if available otherwise NULL.
|
322 |
* In addition the start and end position are moved to boundaries of the
|
323 |
+
* attribute's value.
|
324 |
*/
|
325 |
function get_attribute(&$start, &$end, $id)
|
326 |
{
|
327 |
+
global $page;
|
328 |
+
|
329 |
+
//look for the id within the given limits.
|
330 |
+
while($start < $end)
|
331 |
+
{
|
332 |
+
$index = 0;
|
333 |
+
|
334 |
+
while($start < $end && $page[$start + $index] == $id[$index]
|
335 |
+
&& $index < strlen($id))
|
336 |
+
{
|
337 |
+
$index++;
|
338 |
+
}
|
339 |
+
|
340 |
+
if($index == strlen($id))
|
341 |
+
{
|
342 |
+
//we have match
|
343 |
+
break;
|
344 |
+
}
|
345 |
+
|
346 |
+
$start++;
|
347 |
+
}
|
348 |
+
|
349 |
+
if($start == $end)
|
350 |
+
{
|
351 |
+
return NULL;
|
352 |
+
}
|
353 |
+
|
354 |
+
//look for the " or ' marking start of attribute's value
|
355 |
+
while($start < $end && $page[$start] != '"' && $page[$start] != "'")
|
356 |
+
{
|
357 |
+
$start++;
|
358 |
+
}
|
359 |
+
|
360 |
+
$start++;
|
361 |
+
if($start >= $end)
|
362 |
+
{
|
363 |
+
return NULL;
|
364 |
+
}
|
365 |
+
|
366 |
+
$tmp = $start + 1;
|
367 |
+
//look for the " or ' marking the end of attribute's value
|
368 |
+
while($tmp < $end && $page[$tmp] != '"' && $page[$tmp] != "'")
|
369 |
+
{
|
370 |
+
$tmp++;
|
371 |
+
}
|
372 |
+
|
373 |
+
$end = $tmp - 1;
|
374 |
+
|
375 |
+
|
376 |
+
return substr($page, $start, $end - $start + 1);
|
377 |
}
|
378 |
|
379 |
/*
|
383 |
*/
|
384 |
function process_current_tag()
|
385 |
{
|
386 |
+
global $page, $pos;
|
387 |
+
|
388 |
+
|
389 |
+
|
390 |
+
//translate only known elements within the body or channel
|
391 |
+
if(is_translatable_section())
|
392 |
+
{
|
393 |
+
skip_white_space();
|
394 |
+
$start = $pos;
|
395 |
+
$page_length = strlen($page);
|
396 |
+
|
397 |
+
// Indicates if the html entity should break into a new translation segment.
|
398 |
+
$is_breaker = FALSE;
|
399 |
+
|
400 |
+
while($pos < $page_length && $page[$pos] != '<')
|
401 |
+
{
|
402 |
+
//will break translation unit when one of the following characters is reached: .,
|
403 |
+
if(($end_of_entity = is_html_entity($pos, $is_breaker)))
|
404 |
+
{
|
405 |
+
//Check if should break - value has been set by the is_html_entity function
|
406 |
+
if($is_breaker)
|
407 |
+
{
|
408 |
+
translate_text($start);
|
409 |
+
$start = $end_of_entity;
|
410 |
+
}
|
411 |
+
|
412 |
+
//skip past entity
|
413 |
+
$pos = $end_of_entity;
|
414 |
+
}
|
415 |
+
else if(is_sentence_breaker($pos))
|
416 |
+
{
|
417 |
+
translate_text($start);
|
418 |
+
$pos++;
|
419 |
+
$start = $pos;
|
420 |
+
}
|
421 |
+
else
|
422 |
+
{
|
423 |
+
$pos++;
|
424 |
+
}
|
425 |
+
}
|
426 |
+
|
427 |
+
if($pos > $start)
|
428 |
+
{
|
429 |
+
translate_text($start);
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
}
|
434 |
+
|
435 |
+
|
436 |
+
/*
|
437 |
+
* Translate the content of a cdata section. For now we only expect to handle it
|
438 |
+
* within RSS feeds.
|
439 |
+
*/
|
440 |
+
function process_cdata_section()
|
441 |
+
{
|
442 |
+
global $page, $pos;
|
443 |
+
|
444 |
+
|
445 |
+
|
446 |
+
//translate only known elements within rss feeds
|
447 |
+
if(is_translatable_section())
|
448 |
+
{
|
449 |
+
skip_white_space();
|
450 |
+
$start = $pos;
|
451 |
+
$page_length = strlen($page);
|
452 |
+
|
453 |
+
while($pos < $page_length && !is_word(']]>'))
|
454 |
+
{
|
455 |
+
//will break translation unit when one of the following characters is reached: .,
|
456 |
+
if(is_sentence_breaker($pos) ||
|
457 |
+
$page[$pos] == '<' || $page[$pos] == '>') //only in cdata the < > are valid breakers as well
|
458 |
+
{
|
459 |
+
translate_text($start);
|
460 |
+
$pos++;
|
461 |
+
$start = $pos;
|
462 |
+
}
|
463 |
+
else
|
464 |
+
{
|
465 |
+
$pos++;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
if($pos > $start)
|
470 |
+
{
|
471 |
+
translate_text($start);
|
472 |
+
}
|
473 |
+
}
|
474 |
+
|
475 |
}
|
476 |
|
477 |
+
/**
|
478 |
+
* Determines position in page marks a transaltable tag in html page or rss feed section.
|
479 |
+
* Return TRUE if should be translated otherwise FALSE.
|
480 |
+
*/
|
481 |
+
function is_translatable_section()
|
482 |
+
{
|
483 |
+
global $tags_list, $is_in_channel, $is_in_body;
|
484 |
+
$rc = FALSE;
|
485 |
+
$current_tag = end($tags_list);
|
486 |
+
|
487 |
+
if($is_in_body || $current_tag == 'title')
|
488 |
+
{
|
489 |
+
$rc = TRUE;
|
490 |
+
}
|
491 |
+
else if($is_in_channel &&
|
492 |
+
($current_tag == 'title' || $current_tag == 'description' || $current_tag == 'category'))
|
493 |
+
{
|
494 |
+
$rc = TRUE;
|
495 |
+
}
|
496 |
+
|
497 |
+
|
498 |
+
return $rc;
|
499 |
+
}
|
500 |
|
501 |
/*
|
502 |
* Determine if the current position in buffer is a sentence breaker, e.g. '.' or ',' .
|
505 |
*/
|
506 |
function is_sentence_breaker($position)
|
507 |
{
|
508 |
+
global $page;
|
509 |
+
$rc = FALSE;
|
510 |
+
|
511 |
+
if($page[$position] == '.' || $page[$position] == '-')
|
512 |
+
{
|
513 |
+
//Only break if the next character is a white space,
|
514 |
+
//in order to avoid breaks on cases like this: (hello world.)
|
515 |
+
if(is_white_space($position + 1) || $page[$position + 1] == '<')
|
516 |
+
{
|
517 |
+
$rc = TRUE;
|
518 |
+
}
|
519 |
+
}
|
520 |
+
else if($page[$position] == ',' || $page[$position] == '?' ||
|
521 |
+
$page[$position] == '(' || $page[$position] == ')' ||
|
522 |
+
$page[$position] == '[' || $page[$position] == ']' ||
|
523 |
+
$page[$position] == '"' || $page[$position] == '!' ||
|
524 |
+
$page[$position] == ':' || $page[$position] == '|' ||
|
525 |
+
$page[$position] == ';' ||
|
526 |
+
//break on numbers but not like: 3rd, 4th
|
527 |
+
(is_digit($position) && !is_a_to_z_character($position+1)))
|
528 |
+
{
|
529 |
+
//break the sentence into segments regardless of the next character.
|
530 |
+
$rc = TRUE;
|
531 |
+
}
|
532 |
+
|
533 |
+
return $rc;
|
534 |
}
|
535 |
|
536 |
/*
|
537 |
* Determines if the current position marks the begining of an html
|
538 |
* entity. E.g &
|
539 |
+
* Return 0 if not an html entity otherwise return the position past this entity. In addition
|
540 |
+
* the $is_breaker will be set to TRUE if entity should break translation into a new segment.
|
541 |
*
|
542 |
*/
|
543 |
+
function is_html_entity($position, &$is_breaker)
|
544 |
{
|
545 |
+
global $page;
|
546 |
+
$is_breaker = FALSE;
|
547 |
+
if($page[$position] == "&" )
|
548 |
+
{
|
549 |
+
$end_pos = $position + 1;
|
550 |
+
|
551 |
+
while($page[$end_pos] == "#" ||
|
552 |
+
is_digit($end_pos) || is_a_to_z_character($end_pos))
|
553 |
+
{
|
554 |
+
$end_pos++;
|
555 |
+
}
|
556 |
+
|
557 |
+
if($page[$end_pos] == ';')
|
558 |
+
{
|
559 |
+
$entity = substr($page, $position, $end_pos - $position + 1);
|
560 |
+
|
561 |
+
//Don't break on ` so for our use we don't consider it an entity
|
562 |
+
//e.g. Jack`s apple
|
563 |
+
if(!($entity == "’" || $entity == "'" || $entity == "'"))
|
564 |
+
{
|
565 |
+
$is_breaker = TRUE;
|
566 |
+
}
|
567 |
+
|
568 |
+
//It is an html entity.
|
569 |
+
return $end_pos + 1;
|
570 |
+
}
|
571 |
+
}
|
572 |
+
|
573 |
+
return 0;
|
574 |
}
|
575 |
|
576 |
|
583 |
|
584 |
function is_a_to_z_character($position)
|
585 |
{
|
586 |
+
global $page;
|
587 |
+
|
588 |
+
if(($page[$position] >= 'a' && $page[$position] <= 'z') ||
|
589 |
+
($page[$position] >= 'A' && $page[$position] <= 'Z'))
|
590 |
+
{
|
591 |
+
return TRUE;
|
592 |
+
}
|
593 |
+
|
594 |
+
return FALSE;
|
595 |
}
|
596 |
|
597 |
/*
|
600 |
*/
|
601 |
function is_digit($position)
|
602 |
{
|
603 |
+
global $page;
|
604 |
+
|
605 |
+
if($page[$position] >= '0' && $page[$position] <= '9')
|
606 |
+
{
|
607 |
+
return TRUE;
|
608 |
+
}
|
609 |
+
|
610 |
+
return FALSE;
|
611 |
}
|
612 |
+
|
613 |
/*
|
614 |
+
* Determine if the current position in buffer is a white space.
|
615 |
* return TRUE if current position marks a white space otherwise FALSE.
|
616 |
+
*/
|
617 |
function is_white_space($position)
|
618 |
{
|
619 |
+
global $page;
|
620 |
+
|
621 |
+
if($page[$position] == " " || $page[$position] == "" ||
|
622 |
+
$page[$position] == "\t" || $page[$position] == "\r" ||
|
623 |
+
$page[$position] == "\n" || $page[$position] == "\x0B" ||
|
624 |
+
$page[$position] == "\0")
|
625 |
+
{
|
626 |
+
return TRUE;
|
627 |
+
}
|
628 |
}
|
629 |
|
630 |
/*
|
631 |
* Skip within buffer past unreadable characters , i.e. white space
|
632 |
* and characters considred to be a sentence breaker. Staring from the specified
|
633 |
+
* position going either forward or backward.
|
634 |
+
* param forward - indicate direction going either backward of forward.
|
635 |
*/
|
636 |
function skip_unreadable_chars(&$index, $forward=TRUE)
|
637 |
{
|
638 |
+
global $page, $pos;
|
639 |
+
|
640 |
+
if(!isset($index))
|
641 |
+
{
|
642 |
+
//use $pos as the default position if not specified otherwise
|
643 |
+
$index = &$pos;
|
644 |
+
}
|
645 |
+
$start = $index;
|
646 |
+
|
647 |
+
while($index < strlen($page) && $index > 0 &&
|
648 |
+
(is_white_space($index) || is_sentence_breaker($index)))
|
649 |
+
{
|
650 |
+
($forward ? $index++ : $index--);
|
651 |
+
}
|
652 |
+
|
653 |
+
return $index;
|
654 |
}
|
655 |
|
656 |
/*
|
657 |
* Skip within buffer past white space characters , Staring from the specified
|
658 |
+
* position going either forward or backward.
|
659 |
+
* param forward - indicate direction going either backward of forward.
|
660 |
*/
|
661 |
function skip_white_space(&$index, $forward=TRUE)
|
662 |
{
|
663 |
+
global $page, $pos;
|
664 |
|
665 |
+
if(!isset($index))
|
666 |
+
{
|
667 |
+
//use $pos as the default position if not specified otherwise
|
668 |
+
$index = &$pos;
|
669 |
+
}
|
670 |
|
671 |
+
while($index < strlen($page) && $index > 0 && is_white_space($index))
|
672 |
+
{
|
673 |
+
($forward ? $index++ : $index--);
|
674 |
+
}
|
675 |
|
676 |
+
return $index;
|
677 |
+
}
|
678 |
+
|
679 |
+
|
680 |
+
/*
|
681 |
+
* Check within page buffer position for the given word.
|
682 |
+
* param word The word to look for.
|
683 |
+
* param index1 Optional position within the page buffer, if not available then the current
|
684 |
+
* position ($pos) is used.
|
685 |
+
* Return TRUE if the word matches otherwise FALSE
|
686 |
+
*/
|
687 |
+
function is_word($word, $index1)
|
688 |
+
{
|
689 |
+
global $page, $pos;
|
690 |
+
$rc = FALSE;
|
691 |
+
|
692 |
+
if(!isset($index1))
|
693 |
+
{
|
694 |
+
//use $pos as the default position if not specified otherwise
|
695 |
+
$index1 = $pos;
|
696 |
+
}
|
697 |
+
|
698 |
+
$index2 = 0; //position within word
|
699 |
+
$word_len = strlen($word);
|
700 |
+
$page_length = strlen($page);
|
701 |
+
|
702 |
+
while($index1 < $page_length && $index2 < $word_len)
|
703 |
+
{
|
704 |
+
if($page[$index1] == $word[$index2])
|
705 |
+
{
|
706 |
+
$index1++;
|
707 |
+
$index2++;
|
708 |
+
}
|
709 |
+
else
|
710 |
+
{
|
711 |
+
break;
|
712 |
+
}
|
713 |
+
}
|
714 |
+
|
715 |
+
//check if we have full match
|
716 |
+
if($index2 == $word_len)
|
717 |
+
{
|
718 |
+
$rc = TRUE;
|
719 |
+
}
|
720 |
+
|
721 |
+
return $rc;
|
722 |
}
|
723 |
|
724 |
+
|
725 |
/**
|
726 |
* Translate the text between the given start position and the current
|
727 |
+
* position (pos) within the buffer.
|
728 |
*/
|
729 |
function translate_text($start)
|
730 |
{
|
731 |
+
|
732 |
+
global $page, $pos, $is_edit_mode;
|
733 |
+
|
734 |
+
//trim white space from the start position going forward
|
735 |
+
skip_white_space($start);
|
736 |
+
|
737 |
+
//Set the end position of the string to one back from current position
|
738 |
+
//(i.e. current position points to '<' or a breaker '.') and then trim
|
739 |
+
//white space from the right backwards
|
740 |
+
$end = $pos - 1;
|
741 |
+
$end = skip_white_space($end, $forward=FALSE);
|
742 |
+
|
743 |
+
if($start >= $end)
|
744 |
+
{
|
745 |
+
//empty string - nothing to do
|
746 |
+
return;
|
747 |
+
}
|
748 |
+
|
749 |
+
$original_text = substr($page, $start, $end - $start + 1);
|
750 |
+
|
751 |
+
//Cleanup and prepare text
|
752 |
+
$original_text = scrub_text($original_text);
|
753 |
+
if($original_text == NULL)
|
754 |
+
{
|
755 |
+
//nothing left from the text
|
756 |
+
return;
|
757 |
+
}
|
758 |
+
|
759 |
+
$translated_text = fetch_translation($original_text);
|
760 |
+
|
761 |
+
insert_translation($original_text, $translated_text, $start, $end);
|
762 |
}
|
763 |
|
764 |
/*
|
770 |
*/
|
771 |
function insert_translation(&$original_text, &$translated_text, $start, $end)
|
772 |
{
|
773 |
+
global $segment_id, $is_edit_mode, $tags_list;
|
774 |
+
|
775 |
+
$is_translated = FALSE;
|
776 |
+
|
777 |
+
if(!$is_edit_mode || !in_array('body', $tags_list))
|
778 |
+
{
|
779 |
+
if($translated_text != NULL)
|
780 |
+
{
|
781 |
+
update_translated_page($start, $end, $translated_text);
|
782 |
+
}
|
783 |
+
}
|
784 |
+
else
|
785 |
+
{
|
786 |
+
$span = "<span id=\"" . SPAN_PREFIX . "$segment_id\">";
|
787 |
+
|
788 |
+
if($translated_text == NULL)
|
789 |
+
{
|
790 |
+
$span .= $original_text . '</span>';
|
791 |
+
}
|
792 |
+
else
|
793 |
+
{
|
794 |
+
$span .= $translated_text . "</span>";
|
795 |
+
$is_translated = TRUE;
|
796 |
+
}
|
797 |
+
|
798 |
+
//Insert text (either original or translated) marked by a <span>
|
799 |
+
update_translated_page($start, $end, $span);
|
800 |
+
|
801 |
+
|
802 |
+
//Insert image to allow editing this segment
|
803 |
+
$img = get_img_tag($original_text, $translated_text, $segment_id, $is_translated);
|
804 |
+
update_translated_page($end + 1, - 1, $img);
|
805 |
+
|
806 |
+
//Increment only after both text and image are generated so they
|
807 |
+
//will be the same for each translated segement
|
808 |
+
$segment_id++;
|
809 |
+
|
810 |
+
}
|
811 |
+
|
812 |
+
|
813 |
}
|
814 |
|
815 |
|
820 |
*/
|
821 |
function scrub_text(&$text)
|
822 |
{
|
823 |
+
//skip strings like without any readable characters (i.e. ".")
|
824 |
+
//Todo: need a broader defintion for non-ascii characters as well
|
825 |
+
if(preg_match("/^[.?!|\(\)\[\],0-9]+$/", $text))
|
826 |
+
{
|
827 |
+
return NULL;
|
828 |
+
}
|
829 |
|
830 |
+
//replace multi space chars with a single space
|
831 |
+
$text = preg_replace("/\s\s+/", " ", $text);
|
832 |
|
833 |
+
return $text;
|
834 |
}
|
835 |
|
836 |
|
840 |
* back in buffer.
|
841 |
* param start - marks the starting position of the replaced string in the original page.
|
842 |
* param end - marks the end position of the replaced string in the original page.
|
843 |
+
Use -1 to do insert instead of replace.
|
844 |
* param translated_text - text to be inserted.
|
845 |
*/
|
846 |
function update_translated_page($start, $end, $translated_text)
|
847 |
{
|
848 |
+
global $page, $tr_page, $tr_mark;
|
849 |
+
|
850 |
+
//Bring the translated up to date up to the start position.
|
851 |
+
while($tr_mark < $start)
|
852 |
+
{
|
853 |
+
$tr_page .= $page[$tr_mark++];
|
854 |
+
}
|
855 |
+
|
856 |
+
$tr_page .= $translated_text;
|
857 |
+
|
858 |
+
if($end > $start)
|
859 |
+
{
|
860 |
+
//Move mark to correlate the posistion between the two pages.
|
861 |
+
//Only do this when some content has been replaced, i.e. not
|
862 |
+
//an insert.
|
863 |
+
$tr_mark = $end + 1;
|
864 |
+
}
|
865 |
+
|
866 |
}
|
867 |
|
868 |
?>
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: http://transposh.org/
|
|
4 |
Tags: translation, widget, filter, bilingual, multilingual, transposh, language, RTL, Hebrew, Spanish, French, Russian, crowdsourcing, context, wiki
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.7.1
|
7 |
-
Stable tag: 0.0.
|
8 |
|
9 |
Transposh filter allows in context quick translation of websites, it allows you to crowd-source the translation to your users
|
10 |
|
@@ -71,8 +71,11 @@ harnessed to get your message out to more people. Future versions will give more
|
|
71 |
|
72 |
== Release notes ==
|
73 |
|
74 |
-
*
|
|
|
|
|
|
|
75 |
* Fixed bug with hard coded plugin path (thanks [Atomboy](http://politicalnewsblogs.com/))
|
76 |
* Support for AJAX replacement of content using jQuery
|
77 |
-
*
|
78 |
* Initial release
|
4 |
Tags: translation, widget, filter, bilingual, multilingual, transposh, language, RTL, Hebrew, Spanish, French, Russian, crowdsourcing, context, wiki
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.7.1
|
7 |
+
Stable tag: 0.0.3
|
8 |
|
9 |
Transposh filter allows in context quick translation of websites, it allows you to crowd-source the translation to your users
|
10 |
|
71 |
|
72 |
== Release notes ==
|
73 |
|
74 |
+
* 2009/03/07 - 0.0.3
|
75 |
+
* Added ability to get suggestions from Google Translate
|
76 |
+
* Improved support for RSS feeds translation
|
77 |
+
* 2009/03/01 - 0.0.2
|
78 |
* Fixed bug with hard coded plugin path (thanks [Atomboy](http://politicalnewsblogs.com/))
|
79 |
* Support for AJAX replacement of content using jQuery
|
80 |
+
* 2009/02/28 - 0.0.1
|
81 |
* Initial release
|
transposh.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Plugin URI: http://transposh.org/#
|
5 |
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>.
|
6 |
Author: Team Transposh
|
7 |
-
Version: 0.0.
|
8 |
Author URI: http://transposh.org/
|
9 |
License: GPL (http://www.gnu.org/licenses/gpl.txt)
|
10 |
*/
|
@@ -61,7 +61,7 @@ $home_url_quoted;
|
|
61 |
|
62 |
//The url pointing to the base of the plugin
|
63 |
$plugin_url;
|
64 |
-
|
65 |
//Error message displayed for the admin in case of failure
|
66 |
$admin_msg;
|
67 |
|
@@ -69,20 +69,20 @@ $admin_msg;
|
|
69 |
/*
|
70 |
* Called when the buffer containing the original page is flused. Triggers the
|
71 |
* translation process.
|
72 |
-
*
|
73 |
-
*/
|
74 |
function process_page(&$buffer) {
|
75 |
-
|
76 |
global $wp_query, $tr_page, $page, $pos, $lang, $plugin_url, $is_edit_mode, $wpdb,
|
77 |
$table_name;
|
78 |
-
|
79 |
$start_time = microtime(TRUE);
|
80 |
-
|
81 |
if (!isset($wp_query->query_vars[LANG_PARAM]))
|
82 |
{
|
83 |
//No language code - avoid further processing.
|
84 |
return $buffer;
|
85 |
-
|
86 |
}
|
87 |
|
88 |
$lang = $wp_query->query_vars[LANG_PARAM];
|
@@ -93,8 +93,8 @@ function process_page(&$buffer) {
|
|
93 |
|
94 |
return $buffer;
|
95 |
}
|
96 |
-
|
97 |
-
|
98 |
$page = $buffer;
|
99 |
|
100 |
|
@@ -104,36 +104,36 @@ function process_page(&$buffer) {
|
|
104 |
//Verify that the current language is editable and that the
|
105 |
//user has the required permissions
|
106 |
$editable_langs = get_option(EDITABLE_LANGS);
|
107 |
-
|
108 |
if(is_translator() && strstr($editable_langs, $lang))
|
109 |
{
|
110 |
$is_edit_mode = TRUE;
|
111 |
}
|
112 |
-
|
113 |
}
|
|
|
114 |
|
115 |
-
|
116 |
-
|
117 |
//translate the entire page
|
118 |
process_html();
|
119 |
-
|
120 |
$end_time = microtime(TRUE);
|
121 |
|
122 |
|
123 |
-
|
124 |
//return the translated page unless it is empty, othewise return the original
|
125 |
return (strlen($tr_page) > 0 ? $tr_page : $page);
|
126 |
}
|
127 |
|
128 |
/*
|
129 |
* Fix links on the page. href needs to be modified to include
|
130 |
-
* lang specifier and editing mode.
|
131 |
*
|
132 |
*/
|
133 |
function process_anchor_tag($start, $end)
|
134 |
{
|
135 |
global $home_url, $home_url_quoted, $lang, $is_edit_mode, $wp_rewrite;
|
136 |
-
|
137 |
$href = get_attribute($start, $end, 'href');
|
138 |
|
139 |
if($href == NULL)
|
@@ -148,11 +148,11 @@ function process_anchor_tag($start, $end)
|
|
148 |
}
|
149 |
|
150 |
$use_params = FALSE;
|
151 |
-
|
152 |
-
//Only use params if permalinks are not enabled.
|
153 |
//don't fix links pointing to real files as it will cause that the
|
154 |
//web server will not be able to locate them
|
155 |
-
if(!$wp_rewrite->using_permalinks() ||
|
156 |
stripos($href, '/wp-admin') !== FALSE ||
|
157 |
stripos($href, '/wp-content') !== FALSE ||
|
158 |
stripos($href, '/wp-login') !== FALSE ||
|
@@ -170,7 +170,7 @@ function process_anchor_tag($start, $end)
|
|
170 |
|
171 |
|
172 |
/*
|
173 |
-
* Update the given url to include language params.
|
174 |
* param url - the original url to rewrite
|
175 |
* param lang - language code
|
176 |
* param is_edit - is running in edit mode.
|
@@ -185,11 +185,11 @@ function rewrite_url_lang_param($url, $lang, $is_edit, $use_params_only)
|
|
185 |
//override the use only params - admin configured system to not touch permalinks
|
186 |
$use_params_only = TRUE;
|
187 |
}
|
188 |
-
|
189 |
if($is_edit)
|
190 |
{
|
191 |
$params = EDIT_PARAM . '=1&';
|
192 |
-
|
193 |
}
|
194 |
|
195 |
if($use_params_only)
|
@@ -209,7 +209,7 @@ function rewrite_url_lang_param($url, $lang, $is_edit, $use_params_only)
|
|
209 |
|
210 |
//Cleanup extra &
|
211 |
$url = preg_replace("/&&+/", "&", $url);
|
212 |
-
|
213 |
//Cleanup extra ?
|
214 |
$url = preg_replace("/\?\?+/", "?", $url);
|
215 |
}
|
@@ -218,36 +218,37 @@ function rewrite_url_lang_param($url, $lang, $is_edit, $use_params_only)
|
|
218 |
}
|
219 |
|
220 |
/*
|
221 |
-
* Fetch translation from db or cache.
|
222 |
* Returns the translated string or NULL if not available.
|
223 |
*/
|
224 |
function fetch_translation($original)
|
225 |
{
|
226 |
global $wpdb, $lang, $table_name;
|
227 |
$translated = NULL;
|
228 |
-
|
229 |
|
230 |
if(ENABLE_APC && function_exists('apc_fetch'))
|
231 |
{
|
232 |
$cached = apc_fetch($original . $lang, $rc);
|
233 |
if($rc === TRUE)
|
234 |
{
|
235 |
-
|
|
|
236 |
}
|
237 |
}
|
238 |
-
|
239 |
-
$query = "SELECT * FROM $table_name WHERE original = '$original' and lang = '$lang' ";
|
240 |
$row = $wpdb->get_row($query);
|
241 |
-
|
242 |
if($row !== FALSE)
|
243 |
{
|
244 |
$translated = $row->translated;
|
245 |
$translated = stripslashes($translated);
|
246 |
-
|
247 |
|
248 |
}
|
249 |
-
|
250 |
-
|
251 |
if(ENABLE_APC && function_exists('apc_store'))
|
252 |
{
|
253 |
//If we don't have translation still we want to have it in cache
|
@@ -256,7 +257,7 @@ function fetch_translation($original)
|
|
256 |
{
|
257 |
$cache_entry = "";
|
258 |
}
|
259 |
-
|
260 |
//update cache
|
261 |
$rc = apc_store($original . $lang, $cache_entry, 3600);
|
262 |
if($rc === TRUE)
|
@@ -264,7 +265,7 @@ function fetch_translation($original)
|
|
264 |
|
265 |
}
|
266 |
}
|
267 |
-
|
268 |
|
269 |
return $translated;
|
270 |
}
|
@@ -276,10 +277,19 @@ function fetch_translation($original)
|
|
276 |
*/
|
277 |
function insert_javascript_includes()
|
278 |
{
|
279 |
-
global $plugin_url;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
280 |
|
|
|
281 |
$overlib_dir = "$plugin_url/js/overlibmws";
|
282 |
-
|
283 |
$js = "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws.js\"></script>";
|
284 |
$js .= "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws_filter.js\"></script>";
|
285 |
$js .= "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws_modal.js\"></script>";
|
@@ -289,6 +299,8 @@ function insert_javascript_includes()
|
|
289 |
|
290 |
$js .= "\n<script type=\"text/javascript\" src=\"$plugin_url/js/transposh.js\"></script>\n";
|
291 |
$js .= "\n<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></script>\n";
|
|
|
|
|
292 |
|
293 |
echo $js;
|
294 |
}
|
@@ -296,7 +308,7 @@ function insert_javascript_includes()
|
|
296 |
|
297 |
/*
|
298 |
* Return the img tag that will added to enable editing a translatable
|
299 |
-
* item on the page.
|
300 |
* param segement_id The id (number) identifying this segment. Needs to be
|
301 |
placed within the img tag for use on client side operation (jquery)
|
302 |
*/
|
@@ -304,8 +316,8 @@ function get_img_tag($original, $translation, $segment_id, $is_translated = FALS
|
|
304 |
{
|
305 |
global $plugin_url, $lang, $home_url;
|
306 |
$url = $home_url . '/index.php';
|
307 |
-
|
308 |
-
//For use in javascript, make the following changes:
|
309 |
//1. Add slashes to escape the inner text
|
310 |
//2. Convert the html special characters
|
311 |
//The browser will take decode step 2 and pass it to the js engine which decode step 1 - a bit tricky
|
@@ -317,11 +329,11 @@ function get_img_tag($original, $translation, $segment_id, $is_translated = FALS
|
|
317 |
$add_img = "_fix";
|
318 |
}
|
319 |
|
320 |
-
$img = "<img src=\"$plugin_url/translate$add_img.png\" alt=\"translate\" id=\"" . IMG_PREFIX . "$segment_id\"
|
321 |
-
onclick=\"translate_dialog('$original','$translation','$lang','$url', '$segment_id'); return false;\"
|
322 |
-
onmouseover=\"hint('$original'); return true;\"
|
323 |
onmouseout=\"nd()\" />";
|
324 |
-
|
325 |
return $img;
|
326 |
}
|
327 |
|
@@ -345,8 +357,8 @@ function transposh_css()
|
|
345 |
{
|
346 |
return;
|
347 |
}
|
348 |
-
|
349 |
-
//include the transposh.css
|
350 |
echo "<link rel=\"stylesheet\" href=\"$plugin_url/transposh.css\" type=\"text/css\" />";
|
351 |
|
352 |
|
@@ -358,10 +370,10 @@ function transposh_css()
|
|
358 |
function init_global_vars()
|
359 |
{
|
360 |
global $home_url, $home_url_quoted, $plugin_url, $table_name, $wpdb;
|
361 |
-
|
362 |
$home_url = get_option('home');
|
363 |
$local_dir = preg_replace("/.*\//", "", dirname(__FILE__));
|
364 |
-
|
365 |
$plugin_url= $home_url . "/wp-content/plugins/$local_dir";
|
366 |
$home_url_quoted = preg_quote($home_url);
|
367 |
$home_url_quoted = preg_replace("/\//", "\\/", $home_url_quoted);
|
@@ -371,18 +383,18 @@ function init_global_vars()
|
|
371 |
|
372 |
|
373 |
/*
|
374 |
-
* A new translation has been posted, update the translation database.
|
375 |
*
|
376 |
*/
|
377 |
function update_translation()
|
378 |
{
|
379 |
global $wpdb, $table_name;
|
380 |
-
|
381 |
$ref=getenv('HTTP_REFERER');
|
382 |
$original = $_POST['original'];
|
383 |
$translation = $_POST['translation'];
|
384 |
$lang = $_POST['lang'];
|
385 |
-
|
386 |
if(!isset($original) || !isset($translation) || !isset($lang))
|
387 |
{
|
388 |
logger("Enter " . __FILE__ . " missing params: $original , $translation, $lang," .
|
@@ -396,10 +408,10 @@ function update_translation()
|
|
396 |
|
397 |
}
|
398 |
|
399 |
-
//Decode & remove already escaped character to avoid double escaping
|
400 |
$original = $wpdb->escape(stripslashes(urldecode($original)));
|
401 |
$translation = $wpdb->escape(htmlspecialchars(stripslashes(urldecode($translation))));
|
402 |
-
|
403 |
$update = "REPLACE INTO $table_name (original, translated, lang)
|
404 |
VALUES ('" . $original . "','" . $translation . "','" . $lang . "')";
|
405 |
|
@@ -454,7 +466,7 @@ function update_transaction_log(&$original, &$translation, &$lang)
|
|
454 |
{
|
455 |
|
456 |
}
|
457 |
-
|
458 |
}
|
459 |
|
460 |
|
@@ -466,7 +478,7 @@ function update_transaction_log(&$original, &$translation, &$lang)
|
|
466 |
function get_default_lang()
|
467 |
{
|
468 |
global $languages;
|
469 |
-
|
470 |
$default = get_option(DEFAULT_LANG);
|
471 |
if(!$languages[$default])
|
472 |
{
|
@@ -499,7 +511,7 @@ function on_init()
|
|
499 |
|
500 |
|
501 |
/*
|
502 |
-
* Page generation completed - flush buffer.
|
503 |
*/
|
504 |
function on_shutdown()
|
505 |
{
|
@@ -519,20 +531,20 @@ function update_rewrite_rules($rules){
|
|
519 |
|
520 |
return $rule;
|
521 |
}
|
522 |
-
|
523 |
$newRules = array();
|
524 |
$lang_prefix="([a-z]{2,2}(\-[a-z]{2,2})?)/";
|
525 |
|
526 |
$lang_parameter= "&" . LANG_PARAM . '=$matches[1]';
|
527 |
|
528 |
-
//catch the root url
|
529 |
$newRules[$lang_prefix."?$"] = "index.php?lang=\$matches[1]";
|
530 |
|
531 |
|
532 |
foreach ($rules as $key=>$value) {
|
533 |
$original_key = $key;
|
534 |
$original_value = $value;
|
535 |
-
|
536 |
$key = $lang_prefix . $key;
|
537 |
|
538 |
//Shift existing matches[i] two step forward as we pushed new elements
|
@@ -543,9 +555,9 @@ function update_rewrite_rules($rules){
|
|
543 |
}
|
544 |
|
545 |
$value .= $lang_parameter;
|
|
|
546 |
|
547 |
-
|
548 |
-
|
549 |
|
550 |
$newRules[$key] = $value;
|
551 |
$newRules[$original_key] = $original_value;
|
@@ -570,10 +582,10 @@ function parameter_queryvars($qvars)
|
|
570 |
|
571 |
|
572 |
/*
|
573 |
-
* Setup the translation database.
|
574 |
*
|
575 |
*/
|
576 |
-
function setup_db()
|
577 |
{
|
578 |
|
579 |
global $wpdb;
|
@@ -583,13 +595,13 @@ function setup_db()
|
|
583 |
|
584 |
if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
|
585 |
{
|
586 |
-
|
587 |
$sql = "CREATE TABLE " . $table_name . " (original VARCHAR(256) NOT NULL,
|
588 |
lang CHAR(5) NOT NULL,
|
589 |
translated VARCHAR(256),
|
590 |
PRIMARY KEY (original, lang)) ";
|
591 |
-
|
592 |
-
|
593 |
dbDelta($sql);
|
594 |
|
595 |
//Verify that newly created table is ready for use.
|
@@ -597,14 +609,14 @@ function setup_db()
|
|
597 |
"VALUES ('Hello','Hi There','zz')";
|
598 |
|
599 |
$result = $wpdb->query($insert);
|
600 |
-
|
601 |
if($result === FALSE)
|
602 |
{
|
603 |
-
|
604 |
}
|
605 |
else
|
606 |
{
|
607 |
-
|
608 |
add_option(TRANSPOSH_DB_VERSION, DB_VERSION);
|
609 |
}
|
610 |
}
|
@@ -613,18 +625,18 @@ function setup_db()
|
|
613 |
|
614 |
if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
|
615 |
{
|
616 |
-
|
617 |
$sql = "CREATE TABLE " . $table_name . " (original VARCHAR(256) NOT NULL,
|
618 |
lang CHAR(5) NOT NULL,
|
619 |
translated VARCHAR(256),
|
620 |
translated_by VARCHAR(15),
|
621 |
timestamp TIMESTAMP,
|
622 |
PRIMARY KEY (original, lang, timestamp)) ";
|
623 |
-
|
624 |
-
|
625 |
dbDelta($sql);
|
626 |
}
|
627 |
-
|
628 |
|
629 |
}
|
630 |
|
@@ -644,16 +656,16 @@ function is_translator()
|
|
644 |
|
645 |
if(get_option(ANONYMOUS_TRANSLATION))
|
646 |
{
|
647 |
-
//if anonymous translation is allowed - let anyone enjoy it
|
648 |
return TRUE;
|
649 |
}
|
650 |
-
|
651 |
return FALSE;
|
652 |
}
|
653 |
-
|
654 |
|
655 |
/*
|
656 |
-
* Plugin activated.
|
657 |
*
|
658 |
*/
|
659 |
function plugin_activate()
|
@@ -665,7 +677,7 @@ function plugin_activate()
|
|
665 |
|
666 |
add_filter('rewrite_rules_array', 'update_rewrite_rules');
|
667 |
$wp_rewrite->flush_rules();
|
668 |
-
|
669 |
|
670 |
}
|
671 |
|
@@ -680,24 +692,24 @@ function plugin_deactivate(){
|
|
680 |
|
681 |
remove_filter('rewrite_rules_array', 'update_rewrite_rules');
|
682 |
$wp_rewrite->flush_rules();
|
683 |
-
|
684 |
|
685 |
}
|
686 |
|
687 |
/*
|
688 |
-
* Callback from admin_notices - display error message to the admin.
|
689 |
*
|
690 |
*/
|
691 |
function plugin_install_error()
|
692 |
{
|
693 |
global $admin_msg;
|
694 |
|
695 |
-
|
696 |
echo '<div class="updated"><p>';
|
697 |
echo 'Error has occured in the installation process of the translation plugin: <br>';
|
698 |
-
|
699 |
echo $admin_msg;
|
700 |
-
|
701 |
if (function_exists('deactivate_plugins') ) {
|
702 |
deactivate_plugins("transposh/translate.php", "translate.php");
|
703 |
echo '<br> This plugin has been automatically deactivated.';
|
@@ -710,7 +722,7 @@ function plugin_install_error()
|
|
710 |
/*
|
711 |
* Callback when all plugins have been loaded. Serves as the location
|
712 |
* to check that the plugin loaded successfully else trigger notification
|
713 |
-
* to the admin and deactivate plugin.
|
714 |
*
|
715 |
*/
|
716 |
function plugin_loaded()
|
@@ -721,7 +733,7 @@ function plugin_loaded()
|
|
721 |
if (get_option(TRANSPOSH_DB_VERSION) == NULL)
|
722 |
{
|
723 |
$admin_msg = "Failed to locate the translation table <em> " . TRANSLATIONS_TABLE . "</em> in local database. <br>";
|
724 |
-
|
725 |
|
726 |
//Some error occured - notify admin and deactivate plugin
|
727 |
add_action('admin_notices', 'plugin_install_error');
|
@@ -732,14 +744,31 @@ function plugin_loaded()
|
|
732 |
if ($db_version != DB_VERSION)
|
733 |
{
|
734 |
$admin_msg = "Translation database version ($db_version) is not comptabile with this plugin (". DB_VERSION . ") <br>";
|
735 |
-
|
736 |
|
737 |
//Some error occured - notify admin and deactivate plugin
|
738 |
add_action('admin_notices', 'plugin_install_error');
|
739 |
}
|
740 |
}
|
741 |
|
742 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
743 |
add_action('wp_head', 'add_custom_css');
|
744 |
add_filter('query_vars', 'parameter_queryvars' );
|
745 |
|
@@ -747,6 +776,6 @@ add_action('init', 'on_init');
|
|
747 |
add_action('shutdown', 'on_shutdown');
|
748 |
|
749 |
add_action( 'plugins_loaded', 'plugin_loaded');
|
750 |
-
|
751 |
-
|
752 |
?>
|
4 |
Plugin URI: http://transposh.org/#
|
5 |
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>.
|
6 |
Author: Team Transposh
|
7 |
+
Version: 0.0.3
|
8 |
Author URI: http://transposh.org/
|
9 |
License: GPL (http://www.gnu.org/licenses/gpl.txt)
|
10 |
*/
|
61 |
|
62 |
//The url pointing to the base of the plugin
|
63 |
$plugin_url;
|
64 |
+
|
65 |
//Error message displayed for the admin in case of failure
|
66 |
$admin_msg;
|
67 |
|
69 |
/*
|
70 |
* Called when the buffer containing the original page is flused. Triggers the
|
71 |
* translation process.
|
72 |
+
*
|
73 |
+
*/
|
74 |
function process_page(&$buffer) {
|
75 |
+
|
76 |
global $wp_query, $tr_page, $page, $pos, $lang, $plugin_url, $is_edit_mode, $wpdb,
|
77 |
$table_name;
|
78 |
+
|
79 |
$start_time = microtime(TRUE);
|
80 |
+
|
81 |
if (!isset($wp_query->query_vars[LANG_PARAM]))
|
82 |
{
|
83 |
//No language code - avoid further processing.
|
84 |
return $buffer;
|
85 |
+
|
86 |
}
|
87 |
|
88 |
$lang = $wp_query->query_vars[LANG_PARAM];
|
93 |
|
94 |
return $buffer;
|
95 |
}
|
96 |
+
|
97 |
+
|
98 |
$page = $buffer;
|
99 |
|
100 |
|
104 |
//Verify that the current language is editable and that the
|
105 |
//user has the required permissions
|
106 |
$editable_langs = get_option(EDITABLE_LANGS);
|
107 |
+
|
108 |
if(is_translator() && strstr($editable_langs, $lang))
|
109 |
{
|
110 |
$is_edit_mode = TRUE;
|
111 |
}
|
112 |
+
|
113 |
}
|
114 |
+
|
115 |
|
116 |
+
|
|
|
117 |
//translate the entire page
|
118 |
process_html();
|
119 |
+
|
120 |
$end_time = microtime(TRUE);
|
121 |
|
122 |
|
123 |
+
|
124 |
//return the translated page unless it is empty, othewise return the original
|
125 |
return (strlen($tr_page) > 0 ? $tr_page : $page);
|
126 |
}
|
127 |
|
128 |
/*
|
129 |
* Fix links on the page. href needs to be modified to include
|
130 |
+
* lang specifier and editing mode.
|
131 |
*
|
132 |
*/
|
133 |
function process_anchor_tag($start, $end)
|
134 |
{
|
135 |
global $home_url, $home_url_quoted, $lang, $is_edit_mode, $wp_rewrite;
|
136 |
+
|
137 |
$href = get_attribute($start, $end, 'href');
|
138 |
|
139 |
if($href == NULL)
|
148 |
}
|
149 |
|
150 |
$use_params = FALSE;
|
151 |
+
|
152 |
+
//Only use params if permalinks are not enabled.
|
153 |
//don't fix links pointing to real files as it will cause that the
|
154 |
//web server will not be able to locate them
|
155 |
+
if(!$wp_rewrite->using_permalinks() ||
|
156 |
stripos($href, '/wp-admin') !== FALSE ||
|
157 |
stripos($href, '/wp-content') !== FALSE ||
|
158 |
stripos($href, '/wp-login') !== FALSE ||
|
170 |
|
171 |
|
172 |
/*
|
173 |
+
* Update the given url to include language params.
|
174 |
* param url - the original url to rewrite
|
175 |
* param lang - language code
|
176 |
* param is_edit - is running in edit mode.
|
185 |
//override the use only params - admin configured system to not touch permalinks
|
186 |
$use_params_only = TRUE;
|
187 |
}
|
188 |
+
|
189 |
if($is_edit)
|
190 |
{
|
191 |
$params = EDIT_PARAM . '=1&';
|
192 |
+
|
193 |
}
|
194 |
|
195 |
if($use_params_only)
|
209 |
|
210 |
//Cleanup extra &
|
211 |
$url = preg_replace("/&&+/", "&", $url);
|
212 |
+
|
213 |
//Cleanup extra ?
|
214 |
$url = preg_replace("/\?\?+/", "?", $url);
|
215 |
}
|
218 |
}
|
219 |
|
220 |
/*
|
221 |
+
* Fetch translation from db or cache.
|
222 |
* Returns the translated string or NULL if not available.
|
223 |
*/
|
224 |
function fetch_translation($original)
|
225 |
{
|
226 |
global $wpdb, $lang, $table_name;
|
227 |
$translated = NULL;
|
228 |
+
|
229 |
|
230 |
if(ENABLE_APC && function_exists('apc_fetch'))
|
231 |
{
|
232 |
$cached = apc_fetch($original . $lang, $rc);
|
233 |
if($rc === TRUE)
|
234 |
{
|
235 |
+
|
236 |
+
return $cached;
|
237 |
}
|
238 |
}
|
239 |
+
|
240 |
+
$query = "SELECT * FROM $table_name WHERE original = '$original' and lang = '$lang' ";
|
241 |
$row = $wpdb->get_row($query);
|
242 |
+
|
243 |
if($row !== FALSE)
|
244 |
{
|
245 |
$translated = $row->translated;
|
246 |
$translated = stripslashes($translated);
|
247 |
+
|
248 |
|
249 |
}
|
250 |
+
|
251 |
+
|
252 |
if(ENABLE_APC && function_exists('apc_store'))
|
253 |
{
|
254 |
//If we don't have translation still we want to have it in cache
|
257 |
{
|
258 |
$cache_entry = "";
|
259 |
}
|
260 |
+
|
261 |
//update cache
|
262 |
$rc = apc_store($original . $lang, $cache_entry, 3600);
|
263 |
if($rc === TRUE)
|
265 |
|
266 |
}
|
267 |
}
|
268 |
+
|
269 |
|
270 |
return $translated;
|
271 |
}
|
277 |
*/
|
278 |
function insert_javascript_includes()
|
279 |
{
|
280 |
+
global $plugin_url, $wp_query;
|
281 |
+
|
282 |
+
if (!($wp_query->query_vars[EDIT_PARAM] == "1" ||
|
283 |
+
$wp_query->query_vars[EDIT_PARAM] == "true"))
|
284 |
+
{
|
285 |
+
//check permission later - for now just make sure we don't load the
|
286 |
+
//js code when it is not needed
|
287 |
+
return;
|
288 |
+
}
|
289 |
|
290 |
+
|
291 |
$overlib_dir = "$plugin_url/js/overlibmws";
|
292 |
+
|
293 |
$js = "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws.js\"></script>";
|
294 |
$js .= "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws_filter.js\"></script>";
|
295 |
$js .= "\n<script type=\"text/javascript\" src=\"$overlib_dir/overlibmws_modal.js\"></script>";
|
299 |
|
300 |
$js .= "\n<script type=\"text/javascript\" src=\"$plugin_url/js/transposh.js\"></script>\n";
|
301 |
$js .= "\n<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></script>\n";
|
302 |
+
$js .= "\n<script type=\"text/javascript\" src=\"http://www.google.com/jsapi\"></script>\n";
|
303 |
+
$js .= "\n<script type=\"text/javascript\">google.load(\"language\", \"1\");</script>\n";
|
304 |
|
305 |
echo $js;
|
306 |
}
|
308 |
|
309 |
/*
|
310 |
* Return the img tag that will added to enable editing a translatable
|
311 |
+
* item on the page.
|
312 |
* param segement_id The id (number) identifying this segment. Needs to be
|
313 |
placed within the img tag for use on client side operation (jquery)
|
314 |
*/
|
316 |
{
|
317 |
global $plugin_url, $lang, $home_url;
|
318 |
$url = $home_url . '/index.php';
|
319 |
+
|
320 |
+
//For use in javascript, make the following changes:
|
321 |
//1. Add slashes to escape the inner text
|
322 |
//2. Convert the html special characters
|
323 |
//The browser will take decode step 2 and pass it to the js engine which decode step 1 - a bit tricky
|
329 |
$add_img = "_fix";
|
330 |
}
|
331 |
|
332 |
+
$img = "<img src=\"$plugin_url/translate$add_img.png\" alt=\"translate\" id=\"" . IMG_PREFIX . "$segment_id\"
|
333 |
+
onclick=\"translate_dialog('$original','$translation','$lang','$url', '$segment_id'); return false;\"
|
334 |
+
onmouseover=\"hint('$original'); return true;\"
|
335 |
onmouseout=\"nd()\" />";
|
336 |
+
|
337 |
return $img;
|
338 |
}
|
339 |
|
357 |
{
|
358 |
return;
|
359 |
}
|
360 |
+
|
361 |
+
//include the transposh.css
|
362 |
echo "<link rel=\"stylesheet\" href=\"$plugin_url/transposh.css\" type=\"text/css\" />";
|
363 |
|
364 |
|
370 |
function init_global_vars()
|
371 |
{
|
372 |
global $home_url, $home_url_quoted, $plugin_url, $table_name, $wpdb;
|
373 |
+
|
374 |
$home_url = get_option('home');
|
375 |
$local_dir = preg_replace("/.*\//", "", dirname(__FILE__));
|
376 |
+
|
377 |
$plugin_url= $home_url . "/wp-content/plugins/$local_dir";
|
378 |
$home_url_quoted = preg_quote($home_url);
|
379 |
$home_url_quoted = preg_replace("/\//", "\\/", $home_url_quoted);
|
383 |
|
384 |
|
385 |
/*
|
386 |
+
* A new translation has been posted, update the translation database.
|
387 |
*
|
388 |
*/
|
389 |
function update_translation()
|
390 |
{
|
391 |
global $wpdb, $table_name;
|
392 |
+
|
393 |
$ref=getenv('HTTP_REFERER');
|
394 |
$original = $_POST['original'];
|
395 |
$translation = $_POST['translation'];
|
396 |
$lang = $_POST['lang'];
|
397 |
+
|
398 |
if(!isset($original) || !isset($translation) || !isset($lang))
|
399 |
{
|
400 |
logger("Enter " . __FILE__ . " missing params: $original , $translation, $lang," .
|
408 |
|
409 |
}
|
410 |
|
411 |
+
//Decode & remove already escaped character to avoid double escaping
|
412 |
$original = $wpdb->escape(stripslashes(urldecode($original)));
|
413 |
$translation = $wpdb->escape(htmlspecialchars(stripslashes(urldecode($translation))));
|
414 |
+
|
415 |
$update = "REPLACE INTO $table_name (original, translated, lang)
|
416 |
VALUES ('" . $original . "','" . $translation . "','" . $lang . "')";
|
417 |
|
466 |
{
|
467 |
|
468 |
}
|
469 |
+
|
470 |
}
|
471 |
|
472 |
|
478 |
function get_default_lang()
|
479 |
{
|
480 |
global $languages;
|
481 |
+
|
482 |
$default = get_option(DEFAULT_LANG);
|
483 |
if(!$languages[$default])
|
484 |
{
|
511 |
|
512 |
|
513 |
/*
|
514 |
+
* Page generation completed - flush buffer.
|
515 |
*/
|
516 |
function on_shutdown()
|
517 |
{
|
531 |
|
532 |
return $rule;
|
533 |
}
|
534 |
+
|
535 |
$newRules = array();
|
536 |
$lang_prefix="([a-z]{2,2}(\-[a-z]{2,2})?)/";
|
537 |
|
538 |
$lang_parameter= "&" . LANG_PARAM . '=$matches[1]';
|
539 |
|
540 |
+
//catch the root url
|
541 |
$newRules[$lang_prefix."?$"] = "index.php?lang=\$matches[1]";
|
542 |
|
543 |
|
544 |
foreach ($rules as $key=>$value) {
|
545 |
$original_key = $key;
|
546 |
$original_value = $value;
|
547 |
+
|
548 |
$key = $lang_prefix . $key;
|
549 |
|
550 |
//Shift existing matches[i] two step forward as we pushed new elements
|
555 |
}
|
556 |
|
557 |
$value .= $lang_parameter;
|
558 |
+
|
559 |
|
560 |
+
|
|
|
561 |
|
562 |
$newRules[$key] = $value;
|
563 |
$newRules[$original_key] = $original_value;
|
582 |
|
583 |
|
584 |
/*
|
585 |
+
* Setup the translation database.
|
586 |
*
|
587 |
*/
|
588 |
+
function setup_db()
|
589 |
{
|
590 |
|
591 |
global $wpdb;
|
595 |
|
596 |
if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
|
597 |
{
|
598 |
+
|
599 |
$sql = "CREATE TABLE " . $table_name . " (original VARCHAR(256) NOT NULL,
|
600 |
lang CHAR(5) NOT NULL,
|
601 |
translated VARCHAR(256),
|
602 |
PRIMARY KEY (original, lang)) ";
|
603 |
+
|
604 |
+
|
605 |
dbDelta($sql);
|
606 |
|
607 |
//Verify that newly created table is ready for use.
|
609 |
"VALUES ('Hello','Hi There','zz')";
|
610 |
|
611 |
$result = $wpdb->query($insert);
|
612 |
+
|
613 |
if($result === FALSE)
|
614 |
{
|
615 |
+
|
616 |
}
|
617 |
else
|
618 |
{
|
619 |
+
|
620 |
add_option(TRANSPOSH_DB_VERSION, DB_VERSION);
|
621 |
}
|
622 |
}
|
625 |
|
626 |
if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
|
627 |
{
|
628 |
+
|
629 |
$sql = "CREATE TABLE " . $table_name . " (original VARCHAR(256) NOT NULL,
|
630 |
lang CHAR(5) NOT NULL,
|
631 |
translated VARCHAR(256),
|
632 |
translated_by VARCHAR(15),
|
633 |
timestamp TIMESTAMP,
|
634 |
PRIMARY KEY (original, lang, timestamp)) ";
|
635 |
+
|
636 |
+
|
637 |
dbDelta($sql);
|
638 |
}
|
639 |
+
|
640 |
|
641 |
}
|
642 |
|
656 |
|
657 |
if(get_option(ANONYMOUS_TRANSLATION))
|
658 |
{
|
659 |
+
//if anonymous translation is allowed - let anyone enjoy it
|
660 |
return TRUE;
|
661 |
}
|
662 |
+
|
663 |
return FALSE;
|
664 |
}
|
665 |
+
|
666 |
|
667 |
/*
|
668 |
+
* Plugin activated.
|
669 |
*
|
670 |
*/
|
671 |
function plugin_activate()
|
677 |
|
678 |
add_filter('rewrite_rules_array', 'update_rewrite_rules');
|
679 |
$wp_rewrite->flush_rules();
|
680 |
+
|
681 |
|
682 |
}
|
683 |
|
692 |
|
693 |
remove_filter('rewrite_rules_array', 'update_rewrite_rules');
|
694 |
$wp_rewrite->flush_rules();
|
695 |
+
|
696 |
|
697 |
}
|
698 |
|
699 |
/*
|
700 |
+
* Callback from admin_notices - display error message to the admin.
|
701 |
*
|
702 |
*/
|
703 |
function plugin_install_error()
|
704 |
{
|
705 |
global $admin_msg;
|
706 |
|
707 |
+
|
708 |
echo '<div class="updated"><p>';
|
709 |
echo 'Error has occured in the installation process of the translation plugin: <br>';
|
710 |
+
|
711 |
echo $admin_msg;
|
712 |
+
|
713 |
if (function_exists('deactivate_plugins') ) {
|
714 |
deactivate_plugins("transposh/translate.php", "translate.php");
|
715 |
echo '<br> This plugin has been automatically deactivated.';
|
722 |
/*
|
723 |
* Callback when all plugins have been loaded. Serves as the location
|
724 |
* to check that the plugin loaded successfully else trigger notification
|
725 |
+
* to the admin and deactivate plugin.
|
726 |
*
|
727 |
*/
|
728 |
function plugin_loaded()
|
733 |
if (get_option(TRANSPOSH_DB_VERSION) == NULL)
|
734 |
{
|
735 |
$admin_msg = "Failed to locate the translation table <em> " . TRANSLATIONS_TABLE . "</em> in local database. <br>";
|
736 |
+
|
737 |
|
738 |
//Some error occured - notify admin and deactivate plugin
|
739 |
add_action('admin_notices', 'plugin_install_error');
|
744 |
if ($db_version != DB_VERSION)
|
745 |
{
|
746 |
$admin_msg = "Translation database version ($db_version) is not comptabile with this plugin (". DB_VERSION . ") <br>";
|
747 |
+
|
748 |
|
749 |
//Some error occured - notify admin and deactivate plugin
|
750 |
add_action('admin_notices', 'plugin_install_error');
|
751 |
}
|
752 |
}
|
753 |
|
754 |
+
/*
|
755 |
+
* Gets the plugin name to be used in activation/decativation hooks.
|
756 |
+
* Keep only the file name and its containing directory. Don't use the full
|
757 |
+
* path as it will break when using symbollic links.
|
758 |
+
*/
|
759 |
+
function get_plugin_name()
|
760 |
+
{
|
761 |
+
$file = __FILE__;
|
762 |
+
$file = str_replace('\\','/',$file); // sanitize for Win32 installs
|
763 |
+
$file = preg_replace('|/+|','/', $file); // remove any duplicate slash
|
764 |
+
|
765 |
+
//keep only the file name and its parent directory
|
766 |
+
$file = preg_replace('/.*(\/[^\/]+\/[^\/]+)$/', '$1', $file);
|
767 |
+
|
768 |
+
return $file;
|
769 |
+
}
|
770 |
+
|
771 |
+
//Register callbacks
|
772 |
add_action('wp_head', 'add_custom_css');
|
773 |
add_filter('query_vars', 'parameter_queryvars' );
|
774 |
|
776 |
add_action('shutdown', 'on_shutdown');
|
777 |
|
778 |
add_action( 'plugins_loaded', 'plugin_loaded');
|
779 |
+
register_activation_hook(get_plugin_name(), 'plugin_activate');
|
780 |
+
register_deactivation_hook(get_plugin_name(),'plugin_deactivate');
|
781 |
?>
|
transposh_widget.php
CHANGED
@@ -101,13 +101,12 @@ function transposh_widget($args)
|
|
101 |
$is_showing_languages = FALSE;
|
102 |
|
103 |
echo $before_widget . $before_title . __(no_translate("Transposh")) . $after_title;
|
104 |
-
|
105 |
-
|
106 |
switch ($options['style']) {
|
107 |
case 1: // flags
|
108 |
//keep the flags in the same direction regardless of the overall page direction
|
109 |
-
echo "<div
|
110 |
-
|
111 |
global $plugin_url;
|
112 |
$using_permalinks = $wp_rewrite->using_permalinks();
|
113 |
|
@@ -130,7 +129,6 @@ function transposh_widget($args)
|
|
130 |
$is_showing_languages = TRUE;
|
131 |
}
|
132 |
}
|
133 |
-
|
134 |
echo "</div>";
|
135 |
|
136 |
// this is the form for the edit...
|
@@ -140,6 +138,7 @@ function transposh_widget($args)
|
|
140 |
default: // language list
|
141 |
|
142 |
echo "<form action=\"$page_url\" method=\"post\">";
|
|
|
143 |
echo "<select name=\"lang\" id=\"lang\" onchange=\"Javascript:this.form.submit();\">";
|
144 |
echo "<option value=\"none\">[Language]</option>";
|
145 |
|
@@ -152,11 +151,12 @@ function transposh_widget($args)
|
|
152 |
($is_translator && strstr($editable_langs, $code)))
|
153 |
{
|
154 |
$is_selected = ($lang == $code ? "selected=\"selected\"" : "" );
|
155 |
-
echo "<option value=\"$code\" $is_selected>" .
|
156 |
$is_showing_languages = TRUE;
|
157 |
}
|
158 |
}
|
159 |
echo "</select><br/>";
|
|
|
160 |
}
|
161 |
|
162 |
|
@@ -168,7 +168,7 @@ function transposh_widget($args)
|
|
168 |
{
|
169 |
echo "<input type=\"checkbox\" name=\"" . EDIT_PARAM . "\" value=\"1\"" .
|
170 |
($is_edit ? "checked=\"1\"" : "0") .
|
171 |
-
"\" onClick=\"this.form.submit();\"
|
172 |
}
|
173 |
|
174 |
echo "<input type=\"hidden\" name=\"transposh_widget_posted\" value=\"1\"/>";
|
@@ -180,7 +180,6 @@ function transposh_widget($args)
|
|
180 |
}
|
181 |
|
182 |
echo "</form>";
|
183 |
-
echo "</span>"; // the no_translate for the widget
|
184 |
|
185 |
echo $after_widget;
|
186 |
}
|
101 |
$is_showing_languages = FALSE;
|
102 |
|
103 |
echo $before_widget . $before_title . __(no_translate("Transposh")) . $after_title;
|
104 |
+
|
|
|
105 |
switch ($options['style']) {
|
106 |
case 1: // flags
|
107 |
//keep the flags in the same direction regardless of the overall page direction
|
108 |
+
echo "<div style=\"text-align: left;\" class=\"" . NO_TRANSLATE_CLASS . "\" >";
|
109 |
+
|
110 |
global $plugin_url;
|
111 |
$using_permalinks = $wp_rewrite->using_permalinks();
|
112 |
|
129 |
$is_showing_languages = TRUE;
|
130 |
}
|
131 |
}
|
|
|
132 |
echo "</div>";
|
133 |
|
134 |
// this is the form for the edit...
|
138 |
default: // language list
|
139 |
|
140 |
echo "<form action=\"$page_url\" method=\"post\">";
|
141 |
+
echo "<span class=\"" . NO_TRANSLATE_CLASS . "\" >";
|
142 |
echo "<select name=\"lang\" id=\"lang\" onchange=\"Javascript:this.form.submit();\">";
|
143 |
echo "<option value=\"none\">[Language]</option>";
|
144 |
|
151 |
($is_translator && strstr($editable_langs, $code)))
|
152 |
{
|
153 |
$is_selected = ($lang == $code ? "selected=\"selected\"" : "" );
|
154 |
+
echo "<option value=\"$code\" $is_selected>" . $language . "</option>";
|
155 |
$is_showing_languages = TRUE;
|
156 |
}
|
157 |
}
|
158 |
echo "</select><br/>";
|
159 |
+
echo "</span>"; // the no_translate for the language list
|
160 |
}
|
161 |
|
162 |
|
168 |
{
|
169 |
echo "<input type=\"checkbox\" name=\"" . EDIT_PARAM . "\" value=\"1\"" .
|
170 |
($is_edit ? "checked=\"1\"" : "0") .
|
171 |
+
"\" onClick=\"this.form.submit();\"/> Edit Translation";
|
172 |
}
|
173 |
|
174 |
echo "<input type=\"hidden\" name=\"transposh_widget_posted\" value=\"1\"/>";
|
180 |
}
|
181 |
|
182 |
echo "</form>";
|
|
|
183 |
|
184 |
echo $after_widget;
|
185 |
}
|