| [ Index ] |
PHP Cross Reference of Wordpress 2.9.1 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Class for a set of entries for translation and their associated headers 4 * 5 * @version $Id: translations.php 291 2009-10-21 05:46:08Z nbachiyski $ 6 * @package pomo 7 * @subpackage translations 8 */ 9 10 require_once dirname(__FILE__) . '/entry.php'; 11 12 if ( !class_exists( 'Translations' ) ): 13 class Translations { 14 var $entries = array(); 15 var $headers = array(); 16 17 /** 18 * Add entry to the PO structure 19 * 20 * @param object &$entry 21 * @return bool true on success, false if the entry doesn't have a key 22 */ 23 function add_entry($entry) { 24 if (is_array($entry)) { 25 $entry = new Translation_Entry($entry); 26 } 27 $key = $entry->key(); 28 if (false === $key) return false; 29 $this->entries[$key] = &$entry; 30 return true; 31 } 32 33 /** 34 * Sets $header PO header to $value 35 * 36 * If the header already exists, it will be overwritten 37 * 38 * TODO: this should be out of this class, it is gettext specific 39 * 40 * @param string $header header name, without trailing : 41 * @param string $value header value, without trailing \n 42 */ 43 function set_header($header, $value) { 44 $this->headers[$header] = $value; 45 } 46 47 function set_headers(&$headers) { 48 foreach($headers as $header => $value) { 49 $this->set_header($header, $value); 50 } 51 } 52 53 function get_header($header) { 54 return isset($this->headers[$header])? $this->headers[$header] : false; 55 } 56 57 function translate_entry(&$entry) { 58 $key = $entry->key(); 59 return isset($this->entries[$key])? $this->entries[$key] : false; 60 } 61 62 function translate($singular, $context=null) { 63 $entry = new Translation_Entry(array('singular' => $singular, 'context' => $context)); 64 $translated = $this->translate_entry($entry); 65 return ($translated && !empty($translated->translations))? $translated->translations[0] : $singular; 66 } 67 68 /** 69 * Given the number of items, returns the 0-based index of the plural form to use 70 * 71 * Here, in the base Translations class, the commong logic for English is implmented: 72 * 0 if there is one element, 1 otherwise 73 * 74 * This function should be overrided by the sub-classes. For example MO/PO can derive the logic 75 * from their headers. 76 * 77 * @param integer $count number of items 78 */ 79 function select_plural_form($count) { 80 return 1 == $count? 0 : 1; 81 } 82 83 function get_plural_forms_count() { 84 return 2; 85 } 86 87 function translate_plural($singular, $plural, $count, $context = null) { 88 $entry = new Translation_Entry(array('singular' => $singular, 'plural' => $plural, 'context' => $context)); 89 $translated = $this->translate_entry($entry); 90 $index = $this->select_plural_form($count); 91 $total_plural_forms = $this->get_plural_forms_count(); 92 if ($translated && 0 <= $index && $index < $total_plural_forms && 93 is_array($translated->translations) && 94 isset($translated->translations[$index])) 95 return $translated->translations[$index]; 96 else 97 return 1 == $count? $singular : $plural; 98 } 99 100 /** 101 * Merge $other in the current object. 102 * 103 * @param Object &$other Another Translation object, whose translations will be merged in this one 104 * @return void 105 **/ 106 function merge_with(&$other) { 107 $this->entries = array_merge($this->entries, $other->entries); 108 } 109 } 110 111 class Gettext_Translations extends Translations { 112 /** 113 * The gettext implmentation of select_plural_form. 114 * 115 * It lives in this class, because there are more than one descendand, which will use it and 116 * they can't share it effectively. 117 * 118 */ 119 function gettext_select_plural_form($count) { 120 if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) { 121 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); 122 $this->_nplurals = $nplurals; 123 $this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression); 124 } 125 return call_user_func($this->_gettext_select_plural_form, $count); 126 } 127 128 function nplurals_and_expression_from_header($header) { 129 if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) { 130 $nplurals = (int)$matches[1]; 131 $expression = trim($this->parenthesize_plural_exression($matches[2])); 132 return array($nplurals, $expression); 133 } else { 134 return array(2, 'n != 1'); 135 } 136 } 137 138 /** 139 * Makes a function, which will return the right translation index, according to the 140 * plural forms header 141 */ 142 function make_plural_form_function($nplurals, $expression) { 143 $expression = str_replace('n', '$n', $expression); 144 $func_body = " 145 \$index = (int)($expression); 146 return (\$index < $nplurals)? \$index : $nplurals - 1;"; 147 return create_function('$n', $func_body); 148 } 149 150 /** 151 * Adds parantheses to the inner parts of ternary operators in 152 * plural expressions, because PHP evaluates ternary oerators from left to right 153 * 154 * @param string $expression the expression without parentheses 155 * @return string the expression with parentheses added 156 */ 157 function parenthesize_plural_exression($expression) { 158 $expression .= ';'; 159 $res = ''; 160 $depth = 0; 161 for ($i = 0; $i < strlen($expression); ++$i) { 162 $char = $expression[$i]; 163 switch ($char) { 164 case '?': 165 $res .= ' ? ('; 166 $depth++; 167 break; 168 case ':': 169 $res .= ') : ('; 170 break; 171 case ';': 172 $res .= str_repeat(')', $depth) . ';'; 173 $depth= 0; 174 break; 175 default: 176 $res .= $char; 177 } 178 } 179 return rtrim($res, ';'); 180 } 181 182 function make_headers($translation) { 183 $headers = array(); 184 // sometimes \ns are used instead of real new lines 185 $translation = str_replace('\n', "\n", $translation); 186 $lines = explode("\n", $translation); 187 foreach($lines as $line) { 188 $parts = explode(':', $line, 2); 189 if (!isset($parts[1])) continue; 190 $headers[trim($parts[0])] = trim($parts[1]); 191 } 192 return $headers; 193 } 194 195 function set_header($header, $value) { 196 parent::set_header($header, $value); 197 if ('Plural-Forms' == $header) { 198 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); 199 $this->_nplurals = $nplurals; 200 $this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression); 201 } 202 } 203 } 204 endif; 205 206 if ( !class_exists( 'NOOP_Translations' ) ): 207 /** 208 * Provides the same interface as Translations, but doesn't do anything 209 */ 210 class NOOP_Translations { 211 var $entries = array(); 212 var $headers = array(); 213 214 function add_entry($entry) { 215 return true; 216 } 217 218 function set_header($header, $value) { 219 } 220 221 function set_headers(&$headers) { 222 } 223 224 function get_header($header) { 225 return false; 226 } 227 228 function translate_entry(&$entry) { 229 return false; 230 } 231 232 function translate($singular, $context=null) { 233 return $singular; 234 } 235 236 function select_plural_form($count) { 237 return 1 == $count? 0 : 1; 238 } 239 240 function get_plural_forms_count() { 241 return 2; 242 } 243 244 function translate_plural($singular, $plural, $count, $context = null) { 245 return 1 == $count? $singular : $plural; 246 } 247 248 function merge_with(&$other) { 249 } 250 } 251 endif;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Fri Jan 8 00:19:48 2010 | Cross-referenced by PHPXref 0.7 |