. */ if (!class_exists("PO")) { class PO { // an id-str pair with attributes var $num, $id, $str, $tranId, $tranVal, $keyId, $keyVal; const MINMATCH = 89; function __construct($id, $str) { $this->id = (string) $id; $this->str = (string) $str; $this->tranVal = self::MINMATCH; $this->keyVal = self::MINMATCH; } function PO($id, $str) { if (version_compare(PHP_VERSION, "5.0.0", "<")) { $this->__construct($id, $str); register_shutdown_function(array($this, "__destruct")); } } // Returns a properly escaped string static function decorate($str, $esc) { if (!get_magic_quotes_gpc()) { $str = addcslashes($str, $esc); } return $str; } static function undecorate($str) { if (!get_magic_quotes_gpc()) { $str = stripslashes($str); } return $str; } // Returns a text-area string of the Id function textId() { $ht = round(strlen($this->id) / 52 + 1) * 25; $col = 'background-color:#f5f5f5;'; $tit = ''; if ($this->keyVal > self::MINMATCH + 1) { $col = "background-color:#ffc;border: solid 1px #f00"; $tit = 'onmouseover = "Tip(\'Another similar string: ' . htmlspecialchars('
' . addslashes($this->keyId) . '
', ENT_QUOTES) . 'exists. Please alert the author.\',WIDTH, 300)" ' . 'onmouseout="UnTip()"'; } $s = '  '; return $s; } function textStr() { $ht = round(strlen($this->id) / 52 + 1) * 25; $col = ''; $tit = ''; if ($this->tranVal > self::MINMATCH + 1) { $col = "background-color:#fdd;border: solid 1px #f00"; $tit = 'onmouseover = "Tip(\'Using the translation for a similar string: ' . htmlspecialchars('
' . addslashes($this->tranId) . '
', ENT_QUOTES) . 'Please check carefully.\',WIDTH, 300)" ' . 'onmouseout="UnTip()"'; } if (empty($this->str)) { $col = "background-color:#dff;border: solid 1px #0ff"; $tit = 'onmouseover = "Tip(\'Using Machine Translation from Google.
Please check carefully.\',WIDTH, 300)" ' . 'onmouseout="UnTip()"'; $this->str = $this->googleTran(); } $s = '
'; return $s; } function googleTran() { $q = urlencode($this->id); $locale = get_locale(); $tl = substr($locale, 0, 2); $sl = "auto"; if (!$q) { return; } // avoid unneeded curling $url = 'http://translate.google.com/translate_a/t?client=a&q=' . $q . '&tl=' . $tl . '&sl=' . $sl; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //must set agent for google to respond with utf-8 curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); $output = curl_exec($ch); curl_close($ch); if ($output === false) { return "No help from Google!"; } $jsonarr = json_decode($output); if (!$jsonarr) { return "No help from Google!"; } if (!isset($jsonarr->results)) { $jsonarr2->results[] = $jsonarr; $jsonarr = $jsonarr2; } return $jsonarr->results[0]->sentences[0]->trans; } } } if (!class_exists("EzTran")) { class EzTran { var $status, $error, $plgName, $plgDir, $plgURL, $domain, $locale, $state; var $adminMsg; var $helpers; function __construct($plgFile, $plgName, $domain = '') { $this->helpers = array('easy-adsense'); if (!empty($_POST['ezt-savePot'])) { // saving cannot be done from handleSubmits // because it would be too late for the headers. $file = $_POST['potFile']; $str = $_POST['potStr']; header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename="' . $file . '"'); header("Content-Transfer-Encoding: ascii"); header('Expires: 0'); header('Pragma: no-cache'); ob_start(); print htmlspecialchars_decode($str, ENT_QUOTES); ob_end_flush(); $this->status = '
Pot file: ' . $file . ' was saved.
'; exit(0); } $this->status = ''; $this->error = ''; if (empty($plgName)) { $plgName = basename($plgFile, '.php'); $plgName = ucfirst(strtr('-_', ' ', $plgName)); } $this->plgName = $plgName; if (empty($domain)) { $domain = strtolower(strtr(' !.,', '----', $plgName)); $domain = str_replace("--", "-", $domain); } $this->domain = $domain; $this->plgDir = dirname($plgFile); $this->plgURL = plugin_dir_url($plgFile); $locale = get_locale(); $this->locale = str_replace('-', '_', $locale); if (!session_id()) { session_start(); } if (empty($_SESSION[$this->domain])) { $_SESSION[$this->domain] = array(); } } function EzTran($plgFile, $plgName = '', $domain = '') { if (version_compare(PHP_VERSION, "5.0.0", "<")) { $this->__construct($plgName, $domain); register_shutdown_function(array($this, "__destruct")); } } // Return the contents of all PHP files in the dir specified function getFileContents() { $files = glob($this->plgDir . '/*.php'); $page = ""; foreach ($files as $f) { $page .= file_get_contents($f, FILE_IGNORE_NEW_LINES); } return $page; } // Percentage Levenshtein distance function levDist(&$s1, &$s2) { similar_text($s1, $s2, $p); return round($p); } // Get the closest existing translation keys, and the recursivley closest in the // key set function getClose(&$mo, &$POs) { foreach ($POs as $n => $po) { $s1 = $po->id; if (strlen($po->str) == 0) { if (!empty($mo)) { foreach ($mo as $mn => $mk) { $s2 = $mn; $result = $this->levDist($s1, $s2); if ($result > $po->tranVal) { $po->tranVal = $result; $po->tranId = $mn; $po->str = $mk->translations[0]; } } } } foreach ($POs as $n2 => $po2) { if ($n != $n2) { $s2 = $po2->id; $result = $this->levDist($s1, $s2); if ($result > $po2->keyVal) { $po->keyVal = $result; $po->keyId = $po2->id; $po2->keyVal = $result; $po2->keyId = $po->id; } } } } } // Get the strings that look like translation keys function getTranPOs(&$contents, &$mo, $domain, &$POs) { $matches = array(); preg_match_all("#_[_e].*\([\'\"](.+?)[\'\"]\s*,\s*[\'\"]" . $domain . "[\'\"]#", $contents, $matches); $keys = array_unique($matches[1]); $keys = str_replace(array("\'", '\"', '\n'), array("'", '"', "\n"), $keys); foreach ($keys as $n => $k) { if (!empty($mo[$k])) { $v = $mo[$k]; $t = $v->translations[0]; } else { $t = ''; } $po = new PO($k, $t); $po->num = $n; array_push($POs, $po); } $this->getClose($mo, $POs); } // Make a POT string from ids and msgs function mkPot(&$POs, $msg) { $time = current_time('mysql'); $pot = <<plgName} # Your Name: {$msg["name"]} # Your Email: {$msg["email"]} # Your Website: {$msg["blog"]} # Your URL: {$msg["url"]} # Your Locale: {$msg["locale"]} # Your Language: {$msg["lang"]} #, fuzzy msgid "" msgstr "" "Project-Id-Version: {$this->plgName}\\n" "PO-Revision-Date: $time\\n" "Last-Translator: {$msg['name']} <{$msg['email']}>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset={$msg['charset']}\\n" "Content-Transfer-Encoding: 8bit\\n" EOF; foreach ($POs as $po) { $pot .= "msgid " . '"' . PO::decorate($po->id, "\n\r\"") . '"' . "\n"; $t = $msg[$po->num]; $pot .= "msgstr " . '"' . PO::decorate($t, "\n\r") . '"' . "\n\n"; } return $pot; } // Update the PO objects in $POs with the text box stuff function updatePot(&$POs, $msg) { foreach ($POs as $po) { $t = $msg[$po->num]; $po->str = PO::undecorate($t); } } // Error messages function errMsg($s, $class = "error", $close = true) { $e = ''; if ($class == "error") { $e = "Error: "; } $s = '

' . $e . $s . '

'; if ($close) { $s .= "\n\n"; } return $s; } function handleSubmits() { $adminNeeded = false; if (empty($_POST)) { return $adminNeeded; } if (isset($_POST['ezt-english'])) { global $l10n; unset($l10n[$this->domain]); $this->adminMsg = "

Ok, in English for now." . "

"; return $adminNeeded; } $adminNeeded = true; if (isset($_POST['ezt-translate'])) { $_POST['eztran'] = 'eztran'; return $adminNeeded; } if (!isset($_POST['eztran'])) { return $adminNeeded; } if (!check_admin_referer('ezTranSubmit', 'ezTranNonce')) { return $adminNeeded; } if (isset($_POST['ezt-clear'])) { $this->status = '
Reloaded the translations from PHP files and MO.
'; unset($_SESSION[$this->domain]['ezt-POs']); return $adminNeeded; } if (!empty($_POST['ezt-mailPot'])) { $file = $_POST['potFile']; $str = stripslashes($_POST['potStr']); $str = str_replace("\'", "'", $str); if (!class_exists("phpmailer")) { require_once(ABSPATH . 'wp-includes/class-phpmailer.php'); } $mail = new PHPMailer(); $mail->From = get_bloginfo('admin_email'); $mail->FromName = get_bloginfo('name'); $mail->AddAddress('Manoj@Thulasidas.com', "Manoj Thulasidas"); $mail->CharSet = get_bloginfo('charset'); $mail->Mailer = 'php'; $mail->SMTPAuth = false; $mail->Subject = $file; $mail->AddStringAttachment($str, $file); $pos1 = strpos($str, "msgstr"); $pos2 = strpos($str, "msgid", $pos1); $head = substr($str, 0, $pos2); $mail->Body = $head; if ($mail->Send()) { $this->status = '
Pot file: ' . $file . ' was sent.
'; } else { $this->error = '
Error: ' . $mail->ErrorInfo . ' Please save the pot file and contact the author
'; } return $adminNeeded; } return $adminNeeded; } // Prints out the admin page function printAdminPage() { $printed = false; if (!$this->handleSubmits()) { return $printed; } if (!isset($_POST['eztran'])) { return $printed; } if (isset($_POST['ezt-english'])) { return $printed; } $printed = true; $backButton = "
If you are done with translating,
You can continue later, and your translation for the session will be remembered until you close the browser window.
"; echo '
'; echo '
'; wp_nonce_field('ezTranSubmit', 'ezTranNonce'); echo ""; $locale = get_locale(); $made = isset($_POST['ezt-make']); echo "\n\n"; echo "

Translation Interface for {$this->plgName}

"; $domain = $this->domain; if (isset($_SESSION[$this->domain]['ezt-POs'])) { if (empty($this->status)) { $this->status = '
Continuing from your last translation session. Click on "Reload Translation" if you would like to start from scratch.
'; } $POs = $_SESSION[$this->domain]['ezt-POs']; } else { global $l10n; $mo = array($l10n[$domain]->entries); $s = $this->getFileContents(); $POs = array(); $this->getTranPOs($s, $mo[0], $domain, $POs); // cache the POs $_SESSION[$this->domain]['ezt-POs'] = $POs; } if ($made) { $pot = htmlspecialchars($this->mkPot($POs, $_POST), ENT_QUOTES); $this->updatePot($POs, $_POST); // cache the updated POs $_SESSION[$this->domain]['ezt-POs'] = $POs; } else { global $current_user; $pot = ''; if (count($POs) > 0) { get_currentuserinfo(); $pot .= '
Your Name:
' . 'user_lastname . '" />
' . "\n"; $pot .= '
Your Email:
' . '
' . "\n"; $pot .= '
Your Website:
' . '' . "\n
"; $pot .= '
Your URL:
' . '' . "\n
"; $pot .= '
Your Locale:
' . '
' . "\n"; $pot .= '
Your Language:
' . '
' . "\n"; $pot .= '
Character Set:
' . '' . "\n

"; $pot .= '
'; $pot .= '
' . 'English (en_US)
'; $pot .= '
' . 'Translation (' . $locale . ')
'; $pot .= '
'; if (!class_exists("PO")) { die("Class definition error on PO (on Chrome)."); } foreach ($POs as $po) { if (!is_object($po) && gettype($po) == 'object') { $po = unserialize(serialize($po)); } // need this only on Chrome!! $pot .= $po->textId() . "\n" . $po->textStr() . "\n\n"; } } else { $pot .= "
No translatable strings found for the plugin {$this->plgName}. Although the translation interface is ready, the plugin author has not yet internationalized this plugin.
"; } } $makeStr = '
   
' . $this->status . $this->error; $saveStr = '
   
' . $this->status . $this->error; if ($made) { echo "
If you are happy with the POT file as below, please save it or email it to the author. If not, edit it further. $backButton
"; $this->status = '
Ready to email to POT file to the author. Click on "Mail POT file" to send it.
'; echo ''; echo ''; echo $saveStr; echo "\n" . '
' . $pot . '
'; } else { echo << You are editing the $locale translation for {$this->plgName}. Text Domain is {$this->domain}.
Enter the translated strings in the text boxes below and hit the "Display POT File" button. $backButton
EOF1; echo $makeStr; echo $pot; } echo "\n"; return $printed; } function getInvite() { $locale = $this->locale; $lo = substr($locale, 0, 2); if ($lo == 'en') { return ""; } $plgName = $this->plgName; $patience = "I will include your translation in the next release.

Please note that the page may take a while to load because the plugin will query Google Translator for each string. Please be patient!"; if ($this->state == "Not Translated") { $tip = htmlentities("It is easy to have $plgName in your language. All you have to do is to translate some strings, and email the file to the author.

If you would like to help, please use the translation interface. It picks up the translatable strings in $plgName and presents them (and their existing translations in $locale, if any) in an easy-to-edit form. You can then generate a translation file and email it to the author all from the same form. $patience"); $invite = " Would you like to see $plgName in your langugage ($locale)?  "; } else { $tip = htmlentities("If you would like to improve this translation, please use the translation interface. It picks up the translatable strings in $plgName and presents them and their existing translations in $locale in an easy-to-edit form. You can then generate a translation file and email it to the author all from the same form. Slick, isn\'t it? $patience"); $invite = " Would you like to improve this translation of $plgName in your langugage ($locale)?  "; } return $invite; } function loadTran($helper = '') { $locale = ''; if (empty($helper)) { $moDir = "{$this->plgDir}/lang"; } else { $moDir = "{$this->plgDir}/../$helper/lang"; } $moFile = "$moDir/{$this->locale}.mo"; $lo = substr($this->locale, 0, 2); if (file_exists($moFile) && is_readable($moFile)) { load_textdomain($this->domain, $moFile); $locale = basename(dirname($moFile)); } else { // look for any other similar locale with the same first two characters $moFiles = glob("$moDir/$lo*.mo"); if (!empty($moFiles)) { $moFile = $moFiles[0]; load_textdomain($this->domain, $moFile); $locale = basename(dirname($moFile)); } } return $locale; } function setLang() { $locale = $this->locale; $lo = substr($locale, 0, 2); if ($lo != 'en') { $locale = $this->loadTran(); // Append translations in the helpers foreach ($this->helpers as $helper) { $this->loadTran($helper); } } if (empty($locale)) { $this->state = "Not Translated"; } else if ($locale == $this->locale) { $this->state = "Translated"; } else { $this->state = "Alternate MO"; } return $locale; } function renderTranslator() { if (strncmp($this->locale, "en", 2) == 0) { return; } echo "
\n"; echo "
\n"; echo '
'; echo $this->getInvite(); if ($this->state != "Not Translated") { echo ""; echo '
'; echo $this->adminMsg; return; } echo "
"; $plgName = strtr(' ', '-', str_replace(' pro', '', strtolower($this->plgName))); echo ""; $ms = true; $google = true; if ($ms) { $msBtn = " "; $msLink = "Microsoft® "; $msJS = " "; } else { $msBtn = $msJs = $msLink = ''; } if ($google) { $ggBtn = " "; $ggLink = "Google®"; $ggJS = ""; } else { $ggBtn = $ggJS = $ggLink = ''; } if ($google && $ms) { $or = "or"; } echo "See this page in your language ({$this->locale}) using machine translation. $ggLink $or $msLink Translator."; echo $ggBtn . $msBtn . $ggJS . $msJS; echo ''; } } }