<!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>[1774] sites/trunk/wordpress.org/public_html/wp-content/plugins: Add a new plugin, GlotPress Translate Bridge, which allows code to translate strings directly from a GlotPress instance.</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" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/1774">1774</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/1774","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-07-22 08:03:42 +0000 (Wed, 22 Jul 2015)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Add a new plugin, GlotPress Translate Bridge, which allows code to translate strings directly from a GlotPress instance.</pre>
<h3>Added Paths</h3>
<ul>
<li>sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/</li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsglotpresstranslatebridgeglotpresstranslatebridgephp">sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/glotpress-translate-bridge.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsglotpresstranslatebridgeglotpresstranslatebridgephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/glotpress-translate-bridge.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/glotpress-translate-bridge.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/glotpress-translate-bridge.php 2015-07-22 08:03:42 UTC (rev 1774)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,202 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/*
+ * Plugin Name: GlotPress Translate Bridge
+ * Description: This plugin allows for a code to translate arbitrary strings from a GlotPress instance for the current locale.
+ * Version: 0.1
+ * Plugin URI: https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/
+ * Author: wordpressdotorg
+ * Author URI: http://wordpress.org/
+ * License: GPLv2
+ * License URI: http://opensource.org/licenses/gpl-2.0.php
+ */
+
+/**
+ * The GlotPress Translate Bridge is designed to allow the translation of single strings from a GlotPress instance.
+ * This has been written for WordPress.org, so assumes a few things about the environment.
+ * - It assumes that GlotPress is using the 'gp_' prefix, unless GLOTPRESS_TABLE_PREFIX is defined.
+ * - It assumes that $wpdb has access to the GlotPress tables.
+ * - It assumes that you have an object cache enabled (but works without it too).
+ * - It assumes that you want to use the current locale.
+ * - It assumes you're using the WordPress Locale format.
+ *
+ * An example of how to use this plugin is:
+ * $translated = GlotPress_Translate_Bridge::translate( "Hello World", "wp/dev" );
+ *
+ */
+class GlotPress_Translate_Bridge {
+ static $instance = null;
+
+ private $gp_prefix = 'gp_';
+ private $cache_group = 'glotpress-translate-bridge'; // __construct() marks this as global.
+ private $cache_duration = 21600; // 6 * HOUR_IN_SECONDS;
+
+ /**
+ * Translate a single string.
+ *
+ * @param $singular The string to translate.
+ * @param $project_path The GlotPress project path.
+ * @param $context The strings context. Default: null.
+ *
+ * @return string The translated string if it exists, else, the existing string.
+ */
+ static function translate( $singular, $project_path, $context = null ) {
+ $t = self::instance();
+
+ $translation = $t->find_translation( compact( 'singular', 'context' ), $project_path );
+
+ return $translation ? $translation[0] : $singular;
+ }
+
+ /**
+ * Translate a pluralised string. This does not support the `$count` parameter of `_n()`.
+ *
+ * @param $singular The singular form of the string.
+ * @param $plural The plural form of the string.
+ * @param $project_path The GlotPress project path.
+ * @param $context The strings context. Default: null
+ *
+ * @return array The translated plural forms of the string.
+ */
+ static function translate_plural( $singular, $plural, $project_path, $context = null ) {
+ $t = self::instance();
+
+ $translation = $t->find_translation( compact( 'singular', 'plural', 'context' ), $project_path );
+
+ return $translation ?: array( $singular, $plural );
+ }
+
+ /**
+ * Retrieves the instance of the GlotPress Translate Bridge.
+ *
+ * @return object
+ */
+ public function instance() {
+ if ( is_null( self::$instance ) ) {
+ $class = __CLASS__;
+ self::$instance = new $class;
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Basic configurations for the plugin, sets the cache group to a global.
+ *
+ * @access private
+ */
+ private function __construct() {
+ wp_cache_add_global_groups( array( $this->cache_group ) );
+ if ( defined( 'GLOTPRESS_TABLE_PREFIX' ) ) {
+ $this->gp_prefix = GLOTPRESS_TABLE_PREFIX;
+ }
+ }
+
+ /**
+ * Retrieves the translations for a string from the GlotPress database.
+ * Checks the Object cache first.
+ *
+ * @param array $strings {
+ * @type string $singular The singular form of the string.
+ * @type string $plural The plural form of the string.
+ * @type string $context The context of the string
+ * }
+ * @param string $project_path The path of the GlotPress project.
+ *
+ * @access private
+ *
+ * @return array|false An array of translated string, false if none found.
+ */
+ private function find_translation( array $strings, $project_path ) {
+ global $wpdb;
+
+ $locale = $this->glotpress_locale();
+ if ( ! $locale ) {
+ return false;
+ }
+
+ $cache_key = $this->cache_key( $strings, $project_path );
+ $cache_not_found = '__NONE__';
+
+ if ( false !== ( $cache = wp_cache_get( $cache_key, $this->cache_group ) ) ) {
+ if ( $cache === $cache_not_found ) {
+ return false;
+ }
+ return $cache;
+ }
+
+ $sql_project = $wpdb->prepare( "p.path = %s", $project_path );
+ $sql_singular = isset( $strings['singular'] ) ? $wpdb->prepare( "o.singular = %s", $strings['singular'] ) : 'o.singular IS NULL';
+ $sql_plural = isset( $strings['plural'] ) ? $wpdb->prepare( "o.plural = %s", $strings['plural'] ) : 'o.plural IS NULL';
+ $sql_context = isset( $strings['context'] ) ? $wpdb->prepare( "o.contxt = %s", $strings['context'] ) : 'o.context IS NULL';
+
+ $sql_locale = $wpdb->prepare( "s.locale = %s AND s.slug = %s", $locale['locale'], $locale['slug'] );
+
+ $translation = $wpdb->get_row(
+ "SELECT t.translation_0, t.translation_1, t.translation_2, t.translation_3, t.translation_4, t.translation_5
+ FROM translate_projects p
+ LEFT JOIN translate_originals o ON p.id = o.project_id
+ LEFT JOIN translate_translation_sets s ON p.id = s.project_id
+ LEFT JOIN translate_translations t ON t.original_id = o.id AND t.translation_set_id = s.id
+
+ WHERE
+ $sql_project AND $sql_singular AND $sql_plural AND $sql_context AND $sql_locale
+ AND o.status = '+active'
+ AND t.status = 'current'
+
+ ORDER BY t.date_modified DESC
+ LIMIT 1",
+ ARRAY_N
+ );
+
+ if ( $translation ) {
+ $translation = array_filter( $translation );
+ wp_cache_set( $cache_key, $translation, $this->cache_group, $this->cache_duration );
+ } else {
+ wp_cache_set( $cache_key, $cache_not_found, $this->cache_group, $this->cache_duration );
+ }
+
+ return $translation;
+ }
+
+ /**
+ * Determines the GlotPress Locale for a given WordPress Locale
+ *
+ * This makes assumptions about the format of a GlotPress slug, which may not reflect real-world use-cases.
+ *
+ * @access private
+ *
+ * @return array|false False if the current loale is English (US), an array of the Locale and slug of the GlotPress translation set otherwise.
+ */
+ private function glotpress_locale() {
+ $gp_locale = strtolower( get_locale() );
+
+ if ( 'en_us' === $gp_locale ) {
+ return false;
+ }
+
+ preg_match( '!^([a-z]{2,3})(_([a-z]{2}))?(_([a-z0-9]+))?$!', $gp_locale, $matches );
+
+ $locale = $matches[1];
+ $country = isset( $matches[3] ) ? $matches[3] : $matches[1];
+ $variant = isset( $matches[5] ) ? $matches[5] : false;
+
+ if ( $locale !== $country ) {
+ $locale .= '-' . $country;
+ }
+
+ $slug = $variant ?: 'default';
+
+ return compact( 'locale', 'slug' );
+ }
+
+ /**
+ * Generates a unique cache key for the given strings & project.
+ * The cache is based on the current locale, the project path, and the non-blank strings.
+ *
+ * @access private
+ *
+ * @return string The cache key.
+ */
+ private function cache_key( $strings, $project_path ) {
+ return strtolower( get_locale() ) . ':' . $project_path . ':' . serialize( array_filter( $strings ) );
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/glotpress-translate-bridge/glotpress-translate-bridge.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>
</body>
</html>