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