<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[GlotPress][787] trunk: Google Translate is now a plugin that only shows when the user defines the constant 'GP_GOOGLE_TRANSLATE_KEY'.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="https://glotpress.trac.wordpress.org/changeset/787">787</a></dd>
<dt>Author</dt> <dd>markoheijnen</dd>
<dt>Date</dt> <dd>2013-07-02 19:55:35 +0000 (Tue, 02 Jul 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Google Translate is now a plugin that only shows when the user defines the constant 'GP_GOOGLE_TRANSLATE_KEY'. Props vanillalounge and juanramondiaz. Fixes 170</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkgpincludesassetsloaderphp">trunk/gp-includes/assets-loader.php</a></li>
<li><a href="#trunkgpincludesroutestranslationphp">trunk/gp-includes/routes/translation.php</a></li>
<li><a href="#trunkgpincludestemplatephp">trunk/gp-includes/template.php</a></li>
<li><a href="#trunkgpsettingsphp">trunk/gp-settings.php</a></li>
<li><a href="#trunkgptemplateshelperfunctionsphp">trunk/gp-templates/helper-functions.php</a></li>
<li><a href="#trunkgptemplatestranslationsphp">trunk/gp-templates/translations.php</a></li>
<li><a href="#trunkjseditorjs">trunk/js/editor.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/plugins/google-translate/</li>
<li><a href="#trunkpluginsgoogletranslategoogletranslatejs">trunk/plugins/google-translate/google-translate.js</a></li>
<li><a href="#trunkpluginsgoogletranslategoogletranslatephp">trunk/plugins/google-translate/google-translate.php</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkgpincludesgooglephp">trunk/gp-includes/google.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkgpincludesassetsloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/assets-loader.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/assets-loader.php      2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-includes/assets-loader.php 2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -19,7 +19,7 @@
</span><span class="cx">  $scripts->base_url = gp_url_base( 'js' );
</span><span class="cx">  $scripts->default_version = gp_get_option( 'version' );
</span><span class="cx"> 
</span><del>-       $bump = '20130501';
</del><ins>+        $bump = '20130702';
</ins><span class="cx"> 
</span><span class="cx">  $scripts->add( 'jquery', '/jquery/jquery.js', array(), '1.7.2' );
</span><span class="cx">  $scripts->add( 'jquery-ui', '/jquery/jquery-ui.js', array('jquery'), '1.8.18' );
</span><span class="lines">@@ -29,11 +29,9 @@
</span><span class="cx">  $scripts->add( 'tablesorter', '/jquery.tablesorter.min.js', array('jquery'), '1.8.18' );
</span><span class="cx"> 
</span><span class="cx">  $scripts->add( 'common', '/common.js', array( 'jquery' ), $bump );
</span><del>-       $scripts->add( 'editor', '/editor.js', array( 'common', 'google-js-api' ), $bump );
</del><ins>+        $scripts->add( 'editor', '/editor.js', array( 'common' ), $bump );
</ins><span class="cx">   $scripts->add( 'translations-page', '/translations-page.js', array( 'common' ), $bump );
</span><span class="cx">  $scripts->add( 'mass-create-sets-page', '/mass-create-sets-page.js', array( 'common' ), $bump );
</span><del>-
-       $scripts->add( 'google-js-api', 'http://www.google.com/jsapi', array(), '' );
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> add_action( 'wp_default_scripts', 'gp_scripts_default' );
</span></span></pre></div>
<a id="trunkgpincludesgooglephp"></a>
<div class="delfile"><h4>Deleted: trunk/gp-includes/google.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/google.php     2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-includes/google.php        2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<?php
-
-function google_translate_batch( $locale, $strings ) {
-       if ( !$locale->google_code ) {
-               return new WP_Error( 'google_translate', sprintf( "The locale %s isn't supported by Google Translate.", $locale->slug ) );
-       }
-       $url = 'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&langpair=' . urlencode( 'en|'.$locale->google_code );
-       foreach ( $strings as $string ) {
-               $url .= '&q=' . urlencode( $string );
-       }
-       if ( count( $strings ) == 1 ) $url .= '&q=';
-       $response = wp_remote_get( $url );
-       if ( is_wp_error( $response ) ) {
-               return $response;
-       }
-       $json = json_decode( wp_remote_retrieve_body( $response ) );
-       if ( !$json ) {
-               return new WP_Error( 'google_translate', 'Error decoding JSON from Google Translate.' );
-       }
-       if ( $json->responseStatus != 200 ) {
-               return new WP_Error( 'google_translate', sprintf( 'Error auto-translating: %1$s (%2$s)', $json->responseDetails, $json->responseStatus ) );
-       }
-       $translations = array();
-       if ( !is_array( $json->responseData ) ) $json->responseData = array( $json->responseData );
-       foreach( gp_array_zip( $strings, $json->responseData ) as $item ) {
-               list( $string, $translation ) = $item;
-               if ( $translation->responseStatus == 200 ) {
-                       $translations[] = google_translate_fix( $translation->responseData->translatedText );
-               } else {
-                       $max_len = 20;
-                       $excerpt = strlen( $string ) > $max_len? substr( $string, 0, $max_len - 3 ).'...' : $string;
-                       $message = sprintf( 'Error auto-translating string "$1$s": %2$s (%3$s)', $excerpt, $translation->responseDetails, $translation->responseStatus );
-                       $translations[] = new WP_Error( 'google_translate', $message );
-               }
-       }
-       return $translations;
-}
-
-function google_translate_fix( $string ) {
-       $string = preg_replace_callback( '/% (s|d)/i', lambda( '$m', '"%".strtolower($m[1])' ), $string );
-       $string = preg_replace_callback( '/% (\d+) \$ (s|d)/i', lambda( '$m', '"%".$m[1]."\\$".strtolower($m[2])' ), $string );
-       return $string;
-}
</del><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesroutestranslationphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/translation.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/translation.php 2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-includes/routes/translation.php    2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -168,10 +168,9 @@
</span><span class="cx">                          $this->_bulk_approve( $project, $locale, $translation_set, $bulk );
</span><span class="cx">                  }
</span><span class="cx"> 
</span><del>-                       if ( 'gtranslate' == $bulk['action'] ) {
-                               $this->_bulk_google_translate( $project, $locale, $translation_set, $bulk );
-                       }
-               } else {
</del><ins>+                        do_action( 'gp_translation_set_bulk_action_post', $project, $locale, $translation_set, $bulk );
+               }
+               else {
</ins><span class="cx">                   $this->errors[] = 'No translations were supplied.';
</span><span class="cx">          }
</span><span class="cx"> 
</span><span class="lines">@@ -228,62 +227,6 @@
</span><span class="cx">          }
</span><span class="cx">  }
</span><span class="cx"> 
</span><del>-       function _bulk_google_translate( $project, $locale, $translation_set, $bulk ) {
-               $google_errors = 0;
-               $insert_errors = 0;
-               $ok = 0;
-               $skipped = 0;
-
-               $singulars = array();
-               $original_ids = array();
-               foreach( $bulk['row-ids'] as $row_id ) {
-                       if ( gp_in( '-', $row_id) ) {
-                               $skipped++;
-                               continue;
-                       }
-                       $original_id = gp_array_get( split( '-', $row_id ), 0 );
-                       $original = GP::$original->get( $original_id );
-                       if ( !$original || $original->plural ) {
-                               $skipped++;
-                               continue;
-                       }
-                       $singulars[] = $original->singular;
-                       $original_ids[] = $original_id;
-               }
-               $results = google_translate_batch( $locale, $singulars );
-               if ( is_wp_error( $results ) ) {
-                       error_log( print_r( $results, true ) );
-                       $this->errors[] = $results->get_error_message();
-                       return;
-               }
-               foreach( gp_array_zip( $original_ids, $singulars, $results )  as $item ) {
-                       list( $original_id, $singular, $translation ) = $item;
-                       if ( is_wp_error( $translation ) ) {
-                               $google_errors++;
-                               error_log( $translation->get_error_message() );
-                               continue;
-                       }
-                       $data = compact( 'original_id' );
-                       $data['user_id'] = GP::$user->current()->id;
-                       $data['translation_set_id'] = $translation_set->id;
-                       $data['translation_0'] = $translation;
-                       $data['status'] = 'fuzzy';
-                       $data['warnings'] = GP::$translation_warnings->check( $singular, null, array( $translation ), $locale );
-                       $inserted = GP::$translation->create( $data );
-                       $inserted? $ok++ : $insert_errors++;
-               }
-               if ( $google_errors > 0 || $insert_errors > 0 ) {
-                       $message = array();
-                       if ( $ok ) $message[] = sprintf( __('Added: %d.' ), $ok );
-                       if ( $google_errors ) $message[] = sprintf( __('Error from Google Translate: %d.' ), $google_errors );
-                       if ( $insert_errors ) $message[] = sprintf( __('Error adding: %d.' ), $insert_errors );
-                       if ( $skipped ) $message[] = sprintf( __('Skipped: %d.' ), $skipped );
-                       $this->errors[] = implode( '', $message );
-               } else {
-                       $this->notices[] = sprintf( __('%d fuzzy translation from Google Translate were added.' ), $ok );
-               }
-       }
-
</del><span class="cx">   function discard_warning( $project_path, $locale_slug, $translation_set_slug ) {
</span><span class="cx">          return $this->edit_single_translation( $project_path, $locale_slug, $translation_set_slug, array( $this, 'discard_warning_edit_function' ) );
</span><span class="cx">  }
</span></span></pre></div>
<a id="trunkgpincludestemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/template.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/template.php   2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-includes/template.php      2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -312,4 +312,19 @@
</span><span class="cx">          echo '<li>' . $action . '</li>';
</span><span class="cx">  }
</span><span class="cx">  echo '</ul>';
</span><ins>+}
+
+function gp_entry_actions( $seperator = ' &bull; ' ) {
+       $actions = array(
+               '<a href="#" class="copy" tabindex="-1">' . __('Copy from original') . '</a>'
+       );
+
+       $actions = apply_filters( 'gp_entry_actions', $actions );
+
+
+       echo implode( $seperator, $actions );
+       /*
+       <a href="#" class="copy" tabindex="-1"><?php _e('Copy from original'); ?></a> &bull;
+       <a href="#" class="gtranslate" tabindex="-1"><?php _e('Translation from Google'); ?></a>
+       */
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpsettingsphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-settings.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-settings.php    2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-settings.php       2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -282,7 +282,6 @@
</span><span class="cx"> 
</span><span class="cx"> require_once( GP_PATH . GP_INC . 'warnings.php' );
</span><span class="cx"> require_once( GP_PATH . GP_INC . 'validation.php' );
</span><del>-require_once( GP_PATH . GP_INC . 'google.php' );
</del><span class="cx"> require_once( GP_PATH . GP_INC . 'advanced-permissions.php' );
</span><span class="cx"> 
</span><span class="cx"> require_once GP_PATH . GP_INC . 'thing.php';
</span></span></pre></div>
<a id="trunkgptemplateshelperfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/helper-functions.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/helper-functions.php  2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-templates/helper-functions.php     2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -28,8 +28,7 @@
</span><span class="cx"> 
</span><span class="cx">          <?php if ( $can_edit ): ?>
</span><span class="cx">                  <p>
</span><del>-                               <a href="#" class="copy" tabindex="-1"><?php _e('Copy from original'); ?></a> &bull;
-                               <a href="#" class="gtranslate" tabindex="-1"><?php _e('Translation from Google'); ?></a>
</del><ins>+                                <?php gp_entry_actions(); ?>
</ins><span class="cx">                   </p>
</span><span class="cx">          <?php else: ?>
</span><span class="cx">                  <p>
</span></span></pre></div>
<a id="trunkgptemplatestranslationsphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/translations.php (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/translations.php      2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/gp-templates/translations.php 2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -10,7 +10,6 @@
</span><span class="cx"> 
</span><span class="cx"> // localizer adds var in front of the variable name, so we can't use $gp.editor.options
</span><span class="cx"> $editor_options = compact('can_approve', 'can_write', 'url', 'discard_warning_url', 'set_priority_url', 'set_status_url');
</span><del>-$editor_options['google_translate_language'] = $locale->google_code;
</del><span class="cx"> wp_localize_script( 'editor', '$gp_editor_options', $editor_options );
</span><span class="cx"> $parity = gp_parity_factory();
</span><span class="cx"> add_action( 'gp_head', lambda( '', 'gp_preferred_sans_serif_style_tag($locale);', compact( 'locale' ) ) );
</span><span class="lines">@@ -29,7 +28,7 @@
</span><span class="cx">          <option value="" selected="selected"><?php _e('Bulk Actions'); ?></option>
</span><span class="cx">          <option value="approve"><?php _e('Approve'); ?></option>
</span><span class="cx">          <option value="reject"><?php _e('Reject'); ?></option>
</span><del>-               <option value="gtranslate"><?php _e('Translate via Google'); ?></option>
</del><ins>+                <?php do_action( 'gp_translation_set_bulk_action', $translation_set ); ?>
</ins><span class="cx">   </select>
</span><span class="cx">  <input type="hidden" name="bulk[redirect_to]" value="<?php echo esc_attr(gp_url_current()); ?>" id="bulk[redirect_to]" />
</span><span class="cx">  <input type="hidden" name="bulk[row-ids]" value="" id="bulk[row-ids]" />
</span></span></pre></div>
<a id="trunkjseditorjs"></a>
<div class="modfile"><h4>Modified: trunk/js/editor.js (786 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/js/editor.js       2013-06-25 20:44:15 UTC (rev 786)
+++ trunk/js/editor.js  2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -58,7 +58,6 @@
</span><span class="cx">                  .on('change', 'select.priority', $gp.editor.hooks.set_priority)
</span><span class="cx">                  .on('click', 'a.close', $gp.editor.hooks.hide)
</span><span class="cx">                  .on('click', 'a.copy', $gp.editor.hooks.copy)
</span><del>-                       .on('click', 'a.gtranslate', $gp.editor.hooks.google_translate)
</del><span class="cx">                   .on('click', 'a.discard-warning', $gp.editor.hooks.discard_warning)
</span><span class="cx">                  .on('click', 'button.approve', $gp.editor.hooks.set_status_current)
</span><span class="cx">                  .on('click', 'button.reject', $gp.editor.hooks.set_status_rejected)
</span><span class="lines">@@ -182,36 +181,6 @@
</span><span class="cx">          original_text = original_text.replace(/<span class=.invisibles.*?<\/span>/g, '');
</span><span class="cx">          a = link.parents('.textareas').find('textarea').val(original_text).focus();
</span><span class="cx">  },
</span><del>-       google_translate: function(link) {
-               original_text = link.parents('.textareas').siblings('.original').html();
-               if (!original_text) original_text = link.parents('.textareas').siblings('p:last').children('.original').html();
-               if (!original_text) return;
-               if (typeof google == 'undefined') {
-                       $gp.notices.error('Couldn&#8217;t load Google Translate library!');
-                       return;
-               }
-               $gp.notices.notice('Translating via Google Translate&hellip;');             
-               google.language.translate({text: original_text, type: 'html'}, 'en', $gp_editor_options.google_translate_language, function(result) {
-                       if (!result.error) {
-                               // fix common google translate misbehaviours
-                               result.translation = result.translation.replace(/% (s|d)/gi, function(m, letter) {
-                                       return '%'+letter.toLowerCase();
-                               });
-                               result.translation = result.translation.replace(/% (\d+) \$ (S|D)/gi, function(m, number, letter) {
-                                       return '%'+number+'$'+letter.toLowerCase();
-                               });
-                               result.translation = result.translation.replace(/&lt;\/\s+([A-Z]+)&gt;/g, function(m, tag) {
-                                       return '&lt;/'+tag.toLowerCase()+'&gt;';
-                               });
-
-                               link.parent('p').siblings('textarea').html(result.translation).focus();
-                               $gp.notices.success('Translated!');
-                       } else {
-                               $gp.notices.error('Error in translating via Google Translate: '+result.message+'!');
-                               link.parent('p').siblings('textarea').focus();
-                       }
-               });             
-       },
</del><span class="cx">   hooks: {
</span><span class="cx">          show: function() {
</span><span class="cx">                  $gp.editor.show($(this));
</span><span class="lines">@@ -232,10 +201,6 @@
</span><span class="cx">                  $gp.editor.copy($(this));
</span><span class="cx">                  return false;
</span><span class="cx">          },
</span><del>-               google_translate: function() {
-                       $gp.editor.google_translate($(this));
-                       return false;
-               },
</del><span class="cx">           discard_warning: function() {
</span><span class="cx">                  $gp.editor.discard_warning($(this));
</span><span class="cx">                  return false;
</span><span class="lines">@@ -255,8 +220,6 @@
</span><span class="cx">  }
</span><span class="cx"> }}(jQuery);
</span><span class="cx"> 
</span><del>-if (typeof google != 'undefined') google.load("language", "1");
-
</del><span class="cx"> jQuery(function($) {
</span><span class="cx">  $gp.editor.init($('#translations'));
</span><span class="cx"> });
</span></span></pre></div>
<a id="trunkpluginsgoogletranslategoogletranslatejs"></a>
<div class="addfile"><h4>Added: trunk/plugins/google-translate/google-translate.js (0 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/plugins/google-translate/google-translate.js                               (rev 0)
+++ trunk/plugins/google-translate/google-translate.js  2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+$gp.google_translate = function($){ return {
+       current: null,
+       init: function(table) {
+               $gp.init();
+               $gp.google_translate.table = table;
+               $gp.google_translate.install_hooks();
+       },
+       install_hooks: function() {
+               $($gp.google_translate.table).on('click', 'a.gtranslate', $gp.google_translate.hooks.google_translate)
+       },
+       google_translate: function(link) {
+               original_text = link.parents('.textareas').siblings('.original').html();
+               if (!original_text) original_text = link.parents('.textareas').siblings('p:last').children('.original').html();
+               if (!original_text) return;
+
+               $gp.notices.notice('Translating via Google Translate&hellip;');
+
+               var url = 'https://www.googleapis.com/language/translate/v2?key=' + gp_google_translate.key + '&q=' + original_text + '&source=en&target=' + gp_google_translate.locale;
+
+               $.getJSON( url, function(result) {
+                       if (!result.error) {
+                               var translated_text = result.data.translations[0].translatedText;
+
+                               // fix common google translate misbehaviours
+                               translated_text = translated_text.replace(/% (s|d)/gi, function(m, letter) {
+                                       return '%'+letter.toLowerCase();
+                               });
+                               translated_text = translated_text.replace(/% (\d+) \$ (S|D)/gi, function(m, number, letter) {
+                                       return '%'+number+'$'+letter.toLowerCase();
+                               });
+                               translated_text = translated_text.replace(/&lt;\/\s+([A-Z]+)&gt;/g, function(m, tag) {
+                                       return '&lt;/'+tag.toLowerCase()+'&gt;';
+                               });
+
+                               link.parent('p').siblings('textarea').html(translated_text).focus();
+                               $gp.notices.success('Translated!');
+                       }
+                       else {
+                               $gp.notices.error('Error in translating via Google Translate: ' + result.error.message + ': ' + result.error.reason + '');
+                               link.parent('p').siblings('textarea').focus();
+                       }
+               }).fail(function( jqxhr, textStatus, error ) {
+                       var result = jQuery.parseJSON( jqxhr.responseText );
+
+                       $gp.notices.error('Error in translating via Google Translate: ' + result.error.message );
+                       link.parent('p').siblings('textarea').focus();
+               });
+       },
+       hooks: {
+               google_translate: function() {
+                       $gp.google_translate.google_translate($(this));
+                       return false;
+               }
+       }
+}}(jQuery);
+
+if (typeof google != 'undefined') google.load("language", "1");
+
+jQuery(function($) {
+       $gp.google_translate.init($('#translations'));
+});
</ins></span></pre></div>
<a id="trunkpluginsgoogletranslategoogletranslatephp"></a>
<div class="addfile"><h4>Added: trunk/plugins/google-translate/google-translate.php (0 => 787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/plugins/google-translate/google-translate.php                              (rev 0)
+++ trunk/plugins/google-translate/google-translate.php 2013-07-02 19:55:35 UTC (rev 787)
</span><span class="lines">@@ -0,0 +1,180 @@
</span><ins>+<?php
+
+class GP_Google_Translate extends GP_Plugin {
+       public $id = 'gtrans';
+
+       private $key;
+
+       public function __construct() {
+               $this->key = gp_const_get('GP_GOOGLE_TRANSLATE_KEY');
+
+               if( ! $this->key )
+                       return; 
+
+               parent::__construct();
+
+               add_action( 'pre_tmpl_load', array( $this, 'load_script' ), 10, 2 );
+
+               $this->add_filter( 'gp_entry_actions' );
+
+               $this->add_action( 'gp_translation_set_bulk_action' );
+               $this->add_action( 'gp_translation_set_bulk_action_post', array( 'args' => 4 ) );
+       }
+
+       public function load_script( $template, $args ) {
+               if( 'translations' != $template )
+                       return;
+
+               if( is_ssl() )
+                       $url = gp_url_ssl( gp_url_public_root() );
+               else
+                       $url = gp_url_public_root();
+
+               $options = array(
+                       'key'    => $this->key,
+                       'locale' => $args['locale']->google_code
+               );
+
+               wp_enqueue_script( 'google-translate', $url . '/plugins/google-translate/google-translate.js', array( 'jquery', 'editor' ) );
+               wp_localize_script( 'google-translate', 'gp_google_translate', $options ); 
+       }
+
+       public function gp_entry_actions( $actions ) {
+               $actions[] = '<a href="#" class="gtranslate" tabindex="-1">' . __('Translation from Google') . '</a>';
+
+               return $actions;
+       }
+
+
+       public function gp_translation_set_bulk_action() {
+               echo '<option value="gtranslate">' . __('Translate via Google') . '</option>';
+       }
+
+       function gp_translation_set_bulk_action_post( $project, $locale, $translation_set, $bulk ) {
+               if( 'gtranslate' != $bulk['action'] )
+                       return;
+
+               $google_errors = 0;
+               $insert_errors = 0;
+               $ok      = 0;
+               $skipped = 0;
+
+               $singulars = array();
+               $original_ids = array();
+
+               foreach( $bulk['row-ids'] as $row_id ) {
+                       if ( gp_in( '-', $row_id) ) {
+                               $skipped++;
+                               continue;
+                       }
+
+                       $original_id = gp_array_get( split( '-', $row_id ), 0 );
+                       $original    = GP::$original->get( $original_id );
+
+                       if ( !$original || $original->plural ) {
+                               $skipped++;
+                               continue;
+                       }
+
+                       $singulars[] = $original->singular;
+                       $original_ids[] = $original_id;
+               }
+
+               $results = $this->google_translate_batch( $locale, $singulars );
+
+               if ( is_wp_error( $results ) ) {
+                       error_log( print_r( $results, true ) );
+                       $this->errors[] = $results->get_error_message();
+                       return;
+
+               }
+               foreach( gp_array_zip( $original_ids, $singulars, $results )  as $item ) {
+                       list( $original_id, $singular, $translation ) = $item;
+
+                       if ( is_wp_error( $translation ) ) {
+                               $google_errors++;
+                               error_log( $translation->get_error_message() );
+                               continue;
+                       }
+
+                       $data = compact( 'original_id' );
+                       $data['user_id'] = GP::$user->current()->id;
+                       $data['translation_set_id'] = $translation_set->id;
+                       $data['translation_0'] = $translation;
+                       $data['status'] = 'fuzzy';
+                       $data['warnings'] = GP::$translation_warnings->check( $singular, null, array( $translation ), $locale );
+
+                       $inserted = GP::$translation->create( $data );
+                       $inserted? $ok++ : $insert_errors++;
+               }
+
+               if ( $google_errors > 0 || $insert_errors > 0 ) {
+                       $message = array();
+
+                       if ( $ok )
+                               $message[] = sprintf( __('Added: %d.' ), $ok );
+
+                       if ( $google_errors )
+                               $message[] = sprintf( __('Error from Google Translate: %d.' ), $google_errors );
+
+                       if ( $insert_errors )
+                               $message[] = sprintf( __('Error adding: %d.' ), $insert_errors );
+
+                       if ( $skipped )
+                               $message[] = sprintf( __('Skipped: %d.' ), $skipped );
+
+                       $this->errors[] = implode( '', $message );
+               }
+               else {
+                       $this->notices[] = sprintf( __('%d fuzzy translation from Google Translate were added.' ), $ok );
+               }
+       }
+
+       function google_translate_batch( $locale, $strings ) {
+               if ( ! $locale->google_code )
+                       return new WP_Error( 'google_translate', sprintf( "The locale %s isn't supported by Google Translate.", $locale->slug ) );
+
+               $url = 'https://www.googleapis.com/language/translate/v2?key=' . $this->key . '&source=en&target=' . urlencode( $locale->google_code );
+
+               foreach ( $strings as $string ) {
+                       $url .= '&q=' . urlencode( $string );
+               }
+
+               if ( count( $strings ) == 1 )
+                       $url .= '&q=';
+
+               $response = wp_remote_get( $url );
+
+               if ( is_wp_error( $response ) )
+                       return $response;
+
+               $json = json_decode( wp_remote_retrieve_body( $response ) );
+
+               if ( ! $json )
+                       return new WP_Error( 'google_translate', 'Error decoding JSON from Google Translate.' );
+
+               if ( isset( $json->error ) )
+                       return new WP_Error( 'google_translate', sprintf( 'Error auto-translating: %1$s', $json->error->errors[0]->message ) );
+
+               $translations = array();
+
+               if ( ! is_array( $json->data->translations ) )
+                       $json->data->translations = array( $json->data->translations );
+
+               foreach( gp_array_zip( $strings, $json->data->translations ) as $item ) {
+                       list( $string, $translation ) = $item;
+
+                               $translations[] = $this->google_translate_fix( $translation->translatedText );
+               }
+
+               return $translations;
+       }
+
+       function google_translate_fix( $string ) {
+               $string = preg_replace_callback( '/% (s|d)/i', lambda( '$m', '"%".strtolower($m[1])' ), $string );
+               $string = preg_replace_callback( '/% (\d+) \$ (s|d)/i', lambda( '$m', '"%".$m[1]."\\$".strtolower($m[2])' ), $string );
+               return $string;
+       }
+}
+
+GP::$plugins->gp_google_translate = new GP_Google_Translate;
</ins><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>