WordPress.org

Make WordPress Core

Ticket #17268: 17268.1.diff

File 17268.1.diff, 28.7 KB (added by Mte90, 6 months ago)

it was missing a require

  • src/wp-includes/l10n.php

     
    581581         */ 
    582582        $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain ); 
    583583 
    584         if ( !is_readable( $mofile ) ) return false; 
     584        if ( !is_readable( $mofile ) ) return false; 
    585585 
    586         $mo = new MO(); 
     586        if ( isset( $l10n[$domain] ) ) { 
     587                if ( $l10n[$domain] instanceof MO_dynamic && $l10n[$domain]->Mo_file_loaded( $mofile ) ) { 
     588                        return true; 
     589                } 
     590        } 
     591 
     592        $use_mo_dynamic = apply_filters( 'load_mo_dynamic', true, $domain ); 
     593        if( $use_mo_dynamic ) { 
     594                $cache_mo_dynamic = apply_filters( 'cache_mo_dynamic', true, $domain ); 
     595                $mo = new MO_dynamic ( $domain, $cache_mo_dynamic ); 
     596        } else { 
     597                $mo = new MO(); 
     598        } 
     599 
    587600        if ( !$mo->import_from_file( $mofile ) ) return false; 
    588  
    589         if ( isset( $l10n[$domain] ) ) 
     601 
     602        if ( isset( $l10n[$domain] ) ){ 
    590603                $mo->merge_with( $l10n[$domain] ); 
     604                if ( $l10n[$domain] instanceof MO_dynamic ) { 
     605                        $l10n[$domain]->unhook_and_close(); 
     606                } 
     607        } 
    591608 
    592609        unset( $l10n_unloaded[ $domain ] ); 
    593610 
  • src/wp-includes/load.php

     
    870870        require ABSPATH . WPINC . '/version.php'; 
    871871 
    872872        // Translation and localization 
     873        require_once ABSPATH . WPINC . '/pomo/native.php' ; 
    873874        require_once ABSPATH . WPINC . '/pomo/mo.php'; 
     875        require_once ABSPATH . WPINC . '/pomo/mo-dynamic-loader.php'; 
    874876        require_once ABSPATH . WPINC . '/l10n.php'; 
    875877        require_once ABSPATH . WPINC . '/class-wp-locale.php'; 
    876878        require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php'; 
  • src/wp-includes/pomo/mo-dynamic-loader.php

     
     1<?php 
     2/** 
     3 * Dynamic loading and parsing of MO files 
     4 * 
     5 * @author Björn Ahrens <bjoern@ahrens.net> 
     6 * @package WP Performance Pack 
     7 * @since 0.1 
     8 */ 
     9 
     10/** 
     11 * Class holds information about a single MO file 
     12 */ 
     13class MO_item { 
     14        var $reader = NULL; 
     15        var $mofile = ''; 
     16 
     17        var $loaded = false; 
     18        var $total = 0; 
     19        var $originals = array(); 
     20        var $originals_table; 
     21        var $translations_table; 
     22        var $last_access; 
     23 
     24        var $hash_table; 
     25        var $hash_length = 0; 
     26 
     27        function clear_reader () { 
     28                if ( $this->reader !== NULL ) { 
     29                        $this->reader->close(); 
     30                        $this->reader = NULL; 
     31                } 
     32        } 
     33} 
     34 
     35/** 
     36 * Class for working with MO files 
     37 * Translation entries are created dynamically. 
     38 * Due to this export and save functions are not implemented. 
     39 */ 
     40class MO_dynamic extends Gettext_Translations { 
     41        private $caching = false; 
     42        private $modified = false; 
     43 
     44        protected $domain = ''; 
     45        protected $_nplurals = 2; 
     46        protected $MOs = array(); 
     47 
     48        protected $translations = NULL; 
     49        protected $base_translations = NULL; 
     50 
     51        function __construct( $domain, $caching = false ) { 
     52                $this->domain = $domain; 
     53                $this->caching = $caching; 
     54                if ( $caching ) { 
     55                        add_action ( 'shutdown', array( $this, 'save_to_cache' ) ); 
     56                        add_action ( 'admin_init', array( $this, 'save_base_translations' ), 100 ); 
     57                } 
     58                // Reader has to be destroyed befor any upgrades or else upgrade might fail, if a 
     59                // reader is loaded (cannot delete old plugin/theme/etc. because a language file 
     60                // is still opened). 
     61                add_filter('upgrader_pre_install', array($this, 'clear_reader_before_upgrade'), 10, 2); 
     62        } 
     63 
     64        static function get_byteorder($magic) { 
     65                // The magic is 0x950412de 
     66 
     67                // bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 
     68                $magic_little = (int) - 1794895138; 
     69                $magic_little_64 = (int) 2500072158; 
     70                // 0xde120495 
     71                $magic_big = ((int) - 569244523) & 0xFFFFFFFF; 
     72                if ($magic_little == $magic || $magic_little_64 == $magic) { 
     73                        return 'little'; 
     74                } else if ($magic_big == $magic) { 
     75                        return 'big'; 
     76                } else { 
     77                        return false; 
     78                } 
     79        } 
     80 
     81        function unhook_and_close () { 
     82                remove_action ( 'shutdown', array( $this, 'save_to_cache' ) ); 
     83                remove_action ( 'admin_init', array( $this, 'save_base_translations' ), 100 ); 
     84                foreach ( $this->MOs as $moitem ) { 
     85                        $moitem->clear_reader(); 
     86                } 
     87                $this->MOs = array(); 
     88        } 
     89 
     90        function __destruct() { 
     91                foreach ( $this->MOs as $moitem ) { 
     92                        $moitem->clear_reader(); 
     93                } 
     94        } 
     95 
     96        function clear_reader_before_upgrade($return, $plugin) { 
     97                // stripped down copy of class-wp-upgrader.php Plugin_Upgrader::deactivate_plugin_before_upgrade 
     98                if ( is_wp_error($return) ) //Bypass. 
     99                        return $return; 
     100 
     101                foreach ( $this->MOs as $moitem ) { 
     102                        $moitem->clear_reader(); 
     103                } 
     104        } 
     105 
     106        function get_current_url () { 
     107                $current_url = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 
     108                if ( isset($_SERVER['QUERY_STRING']) && ( $len = strlen( $_SERVER['QUERY_STRING'] ) ) > 0 ) { 
     109                        $current_url = substr ( $current_url, 0, strlen($current_url) - $len - 1 ); 
     110                } 
     111                if ( substr( $current_url, -10 ) === '/wp-admin/' ) { 
     112                        $current_url .= 'index.php'; 
     113                } 
     114                if ( isset( $_GET['page'] ) ) { 
     115                        $current_url .= '?page=' . $_GET['page']; 
     116                } 
     117                return $current_url; 
     118        } 
     119 
     120        function import_from_file( $filename ) { 
     121                $moitem = new MO_item(); 
     122                $moitem->mofile = $filename; 
     123                $this->MOs[] = $moitem; 
     124 
     125                // because only a reference to the MO file is created, at this point there is no information if $filename is a valid MO file, so the return value is always true 
     126                return true; 
     127        } 
     128 
     129        function save_base_translations () { 
     130                if ( is_admin() && $this->translations !== NULL && $this->base_translations === NULL ) { 
     131                        $this->base_translations = $this->translations; 
     132                        $this->translations = array(); 
     133                } 
     134        } 
     135 
     136        private function cache_get ( $key, $cache_time ) { 
     137                $t = wp_cache_get( $key, 'dymoloader1.0' ); 
     138                if ( $t !== false && isset( $t['data'] ) ) { 
     139                        // check soft expire 
     140                        if ( $t['softexpire'] < time() ) { 
     141                                // update cache with new soft expire time 
     142                                $t['softexpire'] = time() + ( $cache_time - ( 5 * MINUTE_IN_SECONDS ) ); 
     143                                wp_cache_replace( $key, $t, 'dymoloader1.0', $cache_time ); 
     144                        } 
     145                        return json_decode( gzuncompress( $t['data'] ), true ); 
     146                } 
     147                return NULL; 
     148        } 
     149 
     150        private function cache_set ( $key, $cache_time, $data ) { 
     151                $t = array(); 
     152                $t['softexpire'] = time() + ( $cache_time - ( 5 * MINUTE_IN_SECONDS ) ); 
     153                $t['data'] = gzcompress( json_encode( $data ) ); 
     154                wp_cache_set( $key, $t, 'dymoloader1.0', $cache_time ); 
     155        } 
     156 
     157        function import_domain_from_cache () { 
     158                // build cache key from domain and request uri 
     159                if ( $this->caching ) { 
     160                        if ( is_admin() ) { 
     161                                $this->base_translations = $this->cache_get( 'backend_' . $this->domain, HOUR_IN_SECONDS ); 
     162                                $this->translations = $this->cache_get( 'backend_' . $this->domain . '_' . $this->get_current_url(), 30 * MINUTE_IN_SECONDS ); 
     163                        } else { 
     164                                $this->translations = $this->cache_get( 'frontend_' . $this->domain, HOUR_IN_SECONDS ); 
     165                        } 
     166                } 
     167 
     168                if ( $this->translations === NULL ) { 
     169                        $this->translations = array(); 
     170                } 
     171        } 
     172 
     173        function save_to_cache () { 
     174                if ( $this->modified ) { 
     175                        if ( is_admin() ) { 
     176                                $this->cache_set( 'backend_' . $this->domain . '_' . $this->get_current_url(), 30 * MINUTE_IN_SECONDS, $this->translations ); // keep admin page cache for 30 minutes 
     177                                if ( count( $this->base_translations ) > 0 ) { 
     178                                        $this->cache_set( 'backend_'.$this->domain, HOUR_IN_SECONDS, $this->base_translations ); // keep admin base cache for 60 minutes 
     179                                } 
     180                        } else { 
     181                                $this->cache_set( 'frontend_'.$this->domain, HOUR_IN_SECONDS, $this->translations ); // keep front end cache for 60 minutes 
     182                        } 
     183                } 
     184        } 
     185 
     186        private function import_fail ( &$moitem ) { 
     187                $moitem->reader->close(); 
     188                $moitem->reader = false; 
     189                unset( $moitem->originals ); 
     190                unset( $moitem->originals_table ); 
     191                unset( $moitem->translations_table ); 
     192                unset( $moitem->hash_table ); 
     193 
     194                return false; 
     195        } 
     196 
     197        function import_from_reader( &$moitem ) { 
     198                if ( $moitem->reader !== NULL) { 
     199                        return ( $moitem->reader !== false ); 
     200                } 
     201 
     202                $file_size = filesize( $moitem->mofile ); 
     203                $moitem->reader=new POMO_FileReader( $moitem->mofile ); 
     204 
     205                if ( $moitem->loaded === true ) { 
     206                        return true; 
     207                } 
     208 
     209                $endian_string = static::get_byteorder( $moitem->reader->readint32() ); 
     210                if ( false === $endian_string ) { 
     211                        return $this->import_fail( $moitem ); 
     212                } 
     213                $moitem->reader->setEndian( $endian_string ); 
     214                $endian = ( 'big' == $endian_string ) ? 'N' : 'V'; 
     215 
     216                $header = $moitem->reader->read( 24 ); 
     217                if ( $moitem->reader->strlen( $header ) != 24 ) { 
     218                        return $this->import_fail( $moitem ); 
     219                } 
     220 
     221                // parse header 
     222                $header = unpack( "{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header ); 
     223                if ( !is_array( $header ) ) { 
     224                        return $this->import_fail( $moitem ); 
     225                } 
     226                extract( $header ); 
     227 
     228                // support revision 0 of MO format specs, only 
     229                if ( $revision !== 0 ) { 
     230                        return $this->import_fail( $moitem ); 
     231                } 
     232 
     233                $moitem->total = $total; 
     234 
     235                // read hashtable 
     236                $moitem->hash_length = $hash_length; 
     237                if ( $hash_length > 0 ) { 
     238                        $moitem->reader->seekto ( $hash_addr ); 
     239                        $str = $moitem->reader->read( $hash_length * 4 ); 
     240                        if ( $moitem->reader->strlen( $str ) != $hash_length * 4 ) { 
     241                                return $this->import_fail( $moitem ); 
     242                        } 
     243                        if ( class_exists ( 'SplFixedArray' ) ) 
     244                                $moitem->hash_table = SplFixedArray::fromArray( unpack ( $endian.$hash_length, $str ), false ); 
     245                        else 
     246                                $moitem->hash_table = array_slice( unpack ( $endian.$hash_length, $str ), 0 ); // force zero based index 
     247                } 
     248 
     249                // read originals' indices 
     250                $moitem->reader->seekto( $originals_lenghts_addr ); 
     251                $originals_lengths_length = $translations_lenghts_addr - $originals_lenghts_addr; 
     252                if ( $originals_lengths_length != $total * 8 ) { 
     253                        return $this->import_fail( $moitem ); 
     254                } 
     255                $str = $moitem->reader->read( $originals_lengths_length ); 
     256                if ( $moitem->reader->strlen( $str ) != $originals_lengths_length ) { 
     257                        return $this->import_fail( $moitem ); 
     258                } 
     259                if ( class_exists ( 'SplFixedArray' ) ) 
     260                        $moitem->originals_table = SplFixedArray::fromArray( unpack ( $endian.($total * 2), $str ), false ); 
     261                else 
     262                        $moitem->originals_table = array_slice( unpack ( $endian.($total * 2), $str ), 0 ); // force zero based index 
     263 
     264                // "sanity check" ( i.e. test for corrupted mo file ) 
     265                for ( $i = 0, $max = $total * 2; $i < $max; $i+=2 ) { 
     266                        if ( $moitem->originals_table[ $i + 1 ] > $file_size 
     267                                || $moitem->originals_table[ $i + 1 ] + $moitem->originals_table[ $i ] > $file_size ) { 
     268                                return $this->import_fail( $moitem ); 
     269                        } 
     270                } 
     271 
     272                // read translations' indices 
     273                $translations_lenghts_length = $hash_addr - $translations_lenghts_addr; 
     274                if ( $translations_lenghts_length != $total * 8 ) { 
     275                        return $this->import_fail( $moitem ); 
     276                } 
     277                $str = $moitem->reader->read( $translations_lenghts_length ); 
     278                if ( $moitem->reader->strlen( $str ) != $translations_lenghts_length ) { 
     279                        return $this->import_fail( $moitem ); 
     280                } 
     281                if ( class_exists ( 'SplFixedArray' ) ) 
     282                        $moitem->translations_table = SplFixedArray::fromArray( unpack ( $endian.($total * 2), $str ), false ); 
     283                else 
     284                        $moitem->translations_table = array_slice( unpack ( $endian.($total * 2), $str ), 0 ); // force zero based index 
     285 
     286                // "sanity check" ( i.e. test for corrupted mo file ) 
     287                for ( $i = 0, $max = $total * 2; $i < $max; $i+=2 ) { 
     288                        if ( $moitem->translations_table[ $i + 1 ] > $file_size 
     289                                || $moitem->translations_table[ $i + 1 ] + $moitem->translations_table[ $i ] > $file_size ) { 
     290                                return $this->import_fail( $moitem ); 
     291                        } 
     292                } 
     293 
     294                $moitem->loaded = true; // read headers can fail, so set loaded to true 
     295 
     296                // read headers 
     297                for ( $i = 0, $max = $total * 2; $i < $max; $i+=2 ) { 
     298                        $original = ''; 
     299                        if ( $moitem->originals_table[$i] > 0 ) { 
     300                                $moitem->reader->seekto( $moitem->originals_table[$i+1] ); 
     301                                $original = $moitem->reader->read( $moitem->originals_table[$i] ); 
     302 
     303                                $j = strpos( $original, 0 ); 
     304                                if ( $j !== false ) 
     305                                        $original = substr( $original, 0, $i ); 
     306                        } 
     307 
     308                        if ( $original === '' ) { 
     309                                $translation = ''; 
     310                                if ( $moitem->translations_table[$i] > 0 ) { 
     311                                        $moitem->reader->seekto( $moitem->translations_table[$i+1] ); 
     312                                        $translation = $moitem->reader->read( $moitem->translations_table[$i] ); 
     313                                } 
     314 
     315                                $this->set_headers( $this->make_headers( $translation ) ); 
     316                        } else 
     317                                return true; 
     318                } 
     319                return true; 
     320        } 
     321 
     322        protected function search_translation ( $key ) { 
     323                $hash_val = NULL; 
     324                $key_len = strlen( $key ); 
     325 
     326                for ( $j = 0, $max = count ( $this->MOs ); $j < $max; $j++ ) { 
     327                        $moitem = $this->MOs[$j]; 
     328                        if ( $moitem->reader == NULL ) { 
     329                                if ( !$this->import_from_reader( $moitem ) ) { 
     330                                        // Error reading MO file, so delete it from MO list to prevent subsequent access 
     331                                        unset( $this->MOs[$j] ); 
     332                                        return false; // return or continue? 
     333                                } 
     334                        } 
     335 
     336                        if ($moitem->hash_length>0) { 
     337                                /* Use mo file hash table to search translation */ 
     338 
     339                                // calculate hash value 
     340                                // hashpjw function by P.J. Weinberger from gettext hash-string.c 
     341                                // adapted to php and its quirkiness caused by missing unsigned ints and shift operators... 
     342                                if ( $hash_val === NULL) { 
     343                                        $hash_val = 0; 
     344                                        $chars = unpack ( 'C*', $key ); // faster than accessing every single char by ord(char) 
     345                                        foreach ( $chars as $char ) { 
     346                                                $hash_val = ( $hash_val << 4 ) + $char; 
     347                                                if( 0 !== ( $g = $hash_val & 0xF0000000 ) ){ 
     348                                                        if ( $g < 0 ) 
     349                                                                $hash_val ^= ( ( ($g & 0x7FFFFFFF) >> 24 ) | 0x80 ); // wordaround: php operator >> is arithmetic, not logic, so shifting negative values gives unexpected results. Cut sign bit, shift right, set sign bit again. 
     350                                                                /* 
     351                                                                workaround based on this function (adapted to actual used parameters): 
     352 
     353                                                                function shr($var,$amt) { 
     354                                                                        $mask = 0x40000000; 
     355                                                                        if($var < 0) { 
     356                                                                                $var &= 0x7FFFFFFF; 
     357                                                                                $mask = $mask >> ($amt-1); 
     358                                                                                return ($var >> $amt) | $mask; 
     359                                                                        } 
     360                                                                        return $var >> $amt; 
     361                                                                } 
     362                                                                */ 
     363                                                        else 
     364                                                                $hash_val ^= ( $g >> 24 ); 
     365                                                        $hash_val ^= $g; 
     366                                                } 
     367                                        } 
     368                                } 
     369 
     370                                // calculate hash table index and increment 
     371                                if ( $hash_val >= 0 ) { 
     372                                        $idx = $hash_val % $moitem->hash_length; 
     373                                        $incr = 1 + ($hash_val % ($moitem->hash_length - 2)); 
     374                                } else { 
     375                                        $hash_val = (float) sprintf('%u', $hash_val); // workaround php not knowing unsigned int - %u outputs $hval as unsigned, then cast to float 
     376                                        $idx = fmod( $hash_val, $moitem->hash_length); 
     377                                        $incr = 1 + fmod ($hash_val, ($moitem->hash_length - 2)); 
     378                                } 
     379 
     380                                $orig_idx = $moitem->hash_table[$idx]; 
     381                                while ( $orig_idx != 0 ) { 
     382                                        $orig_idx--; // index adjustment 
     383 
     384                                        $pos = $orig_idx * 2; 
     385                                        if ( $orig_idx < $moitem->total // orig_idx must be in range 
     386                                                 && $moitem->originals_table[$pos] >= $key_len ) { // and original length must be equal or greater as key length (original can contain plural forms) 
     387 
     388                                                // read original string 
     389                                                $mo_original = ''; 
     390                                                if ( $moitem->originals_table[$pos] > 0 ) { 
     391                                                        $moitem->reader->seekto( $moitem->originals_table[$pos+1] ); 
     392                                                        $mo_original = $moitem->reader->read( $moitem->originals_table[$pos] ); 
     393                                                } 
     394 
     395                                                if ( $moitem->originals_table[$pos] == $key_len 
     396                                                         || ord( $mo_original{$key_len} ) == 0 ) { 
     397                                                        // strings can only match if they have the same length, no need to inspect otherwise 
     398 
     399                                                        if ( false !== ( $i = strpos( $mo_original, 0 ) ) ) 
     400                                                                $cmpval = strncmp( $key, $mo_original, $i ); 
     401                                                        else 
     402                                                                $cmpval = strcmp( $key, $mo_original ); 
     403 
     404                                                        if ( $cmpval === 0 ) { 
     405                                                                // key found, read translation string 
     406                                                                $moitem->reader->seekto( $moitem->translations_table[$pos+1] ); 
     407                                                                $translation = $moitem->reader->read( $moitem->translations_table[$pos] ); 
     408                                                                if ( $j > 0 ) { 
     409                                                                        // Assuming frequent subsequent translations from the same file resort MOs by access time to avoid unnecessary search in the wrong files. 
     410                                                                        $moitem->last_access=time(); 
     411                                                                        usort( $this->MOs, function ($a, $b) {return ($b->last_access - $a->last_access);} ); 
     412                                                                } 
     413                                                                return $translation; 
     414                                                        } 
     415                                                } 
     416                                        } 
     417 
     418                                        if ($idx >= $moitem->hash_length - $incr) 
     419                                                $idx -= ($moitem->hash_length - $incr); 
     420                                        else 
     421                                                $idx += $incr; 
     422                                        $orig_idx = $moitem->hash_table[$idx]; 
     423                                } 
     424                        } else { 
     425                                /* No hash-table, do binary search for matching originals entry */ 
     426                                $left = 0; 
     427                                $right = $moitem->total-1; 
     428 
     429                                while ( $left <= $right ) { 
     430                                        $pivot = $left + (int) ( ( $right - $left ) / 2 ); 
     431                                        $pos = $pivot * 2; 
     432 
     433                                        if ( isset( $moitem->originals[$pivot] ) ) { 
     434                                                $mo_original = $moitem->originals[$pivot]; 
     435                                        } else { 
     436                                                // read and "cache" original string to improve performance of subsequent searches 
     437                                                if ( $moitem->originals_table[$pos] > 0 ) { 
     438                                                        $moitem->reader->seekto( $moitem->originals_table[$pos+1] ); 
     439                                                        $mo_original = $moitem->reader->read( $moitem->originals_table[$pos] ); 
     440                                                } else { 
     441                                                        $mo_original = ''; 
     442                                                } 
     443                                                $moitem->originals[$pivot] = $mo_original; 
     444                                        } 
     445 
     446                                        if ( false !== ( $i = strpos( $mo_original, 0 ) ) ) 
     447                                                $cmpval = strncmp( $key, $mo_original, $i ); 
     448                                        else 
     449                                                $cmpval = strcmp( $key, $mo_original ); 
     450 
     451                                        if ( $cmpval === 0 ) { 
     452                                                // key found read translation string 
     453                                                $moitem->reader->seekto( $moitem->translations_table[$pos+1] ); 
     454                                                $translation = $moitem->reader->read( $moitem->translations_table[$pos] ); 
     455                                                if ( $j > 0 ) { 
     456                                                        // Assuming frequent subsequent translations from the same file resort MOs by access time to avoid unnecessary search in the wrong files. 
     457                                                        $moitem->last_access=time(); 
     458                                                        usort( $this->MOs, function ($a, $b) {return ($b->last_access - $a->last_access);} ); 
     459                                                } 
     460                                                return $translation; 
     461                                        } else if ( $cmpval < 0 ) { 
     462                                                $right = $pivot - 1; 
     463                                        } else { // if ($cmpval>0) 
     464                                                $left = $pivot + 1; 
     465                                        } 
     466                                } 
     467                        } 
     468                } 
     469                // key not found 
     470                return false; 
     471        } 
     472 
     473        function translate ($singular, $context = NULL) { 
     474                if ( !isset ($singular{0} ) ) return $singular; 
     475 
     476                if ( $context == NULL ) { 
     477                        $s = $singular; 
     478                } else { 
     479                        $s = $context . chr(4) . $singular; 
     480                } 
     481 
     482                if ( $this->translations === NULL ) { 
     483                        $this->import_domain_from_cache(); 
     484                } 
     485 
     486                if ( isset( $this->translations[$s] ) ) { 
     487                        $t = $this->translations[$s]; 
     488                } elseif ( isset ($this->base_translations[$s] ) ) { 
     489                        $t = $this->base_translations[$s]; 
     490                } else { 
     491                        if ( false !== ( $t = $this->search_translation( $s ) ) ) { 
     492                                $this->translations[$s] = $t; 
     493                                $this->modified = true; 
     494                        } 
     495                } 
     496 
     497                if ( $t !== false ) { 
     498                        if ( false !== ( $i = strpos( $t, 0 ) ) ) { 
     499                                return substr( $t, 0, $i ); 
     500                        } else { 
     501                                return $t; 
     502                        } 
     503                } else { 
     504                        $this->translations[$s] = $singular; 
     505                        $this->modified = true; 
     506                        return $singular; 
     507                } 
     508        } 
     509 
     510        function translate_plural ($singular, $plural, $count, $context = null) { 
     511                if ( !isset( $singular{0} ) ) return $singular; 
     512 
     513                // Get the "default" return-value 
     514                $default = ($count == 1 ? $singular : $plural); 
     515 
     516                if ( $context == NULL ) { 
     517                        $s = $singular; 
     518                } else { 
     519                        $s = $context . chr(4) . $singular; 
     520                } 
     521 
     522                if ( $this->translations === NULL ) { 
     523                        $this->import_domain_from_cache(); 
     524                } 
     525 
     526                if ( isset( $this->translations[$s] ) ) { 
     527                        $t = $this->translations[$s]; 
     528                } elseif ( isset ($this->base_translations[$s] ) ) { 
     529                        $t = $this->base_translations[$s]; 
     530                } else { 
     531                        if ( false !== ( $t = $this->search_translation( $s ) ) ) { 
     532                                $this->translations[$s] = $t; 
     533                                $this->modified = true; 
     534                        } 
     535                } 
     536 
     537                if ( $t !== false ) { 
     538                        if ( false !== ( $i = strpos( $t, 0 ) ) ) { 
     539                                if ( $count == 1 ) { 
     540                                        return substr ( $t, 0, $i ); 
     541                                } else { 
     542                                        // only one plural form is assumed - needs improvement 
     543                                        return substr( $t, $i+1 ); 
     544                                } 
     545                        } else { 
     546                                return $default; 
     547                        } 
     548                } else { 
     549                        $this->translations[$s] = $singular . chr(0) . $plural; 
     550                        $this->modified = true; 
     551                        return $default; 
     552                } 
     553        } 
     554 
     555        function merge_with( &$other ) { 
     556                if ( $other instanceof WPPP_MO_dynamic ) { 
     557                        if ( $other->translations !== NULL ) { 
     558                                foreach( $other->translations as $key => $translation ) { 
     559                                        $this->translations[$key] = $translation; 
     560                                } 
     561                        } 
     562                        if ( $other->base_translations !== NULL ) { 
     563                                foreach( $other->base_translations as $key => $translation ) { 
     564                                        $this->base_translations[$key] = $translation; 
     565                                } 
     566                        } 
     567 
     568                        foreach ( $other->MOs as $moitem ) { 
     569                                $i = 0; 
     570                                $c = count( $this->MOs ); 
     571                                $found = false; 
     572                                while ( !$found && ( $i < $c ) ) { 
     573                                        $found = $this->MOs[$i]->mofile == $moitem->mofile; 
     574                                        $i++; 
     575                                } 
     576                                if ( !$found ) 
     577                                        $this->MOs[] = $moitem; 
     578                        } 
     579                } 
     580        } 
     581 
     582        function MO_file_loaded ( $mofile ) { 
     583                foreach ($this->MOs as $moitem) { 
     584                        if ($moitem->mofile == $mofile) { 
     585                                return true; 
     586                        } 
     587                } 
     588                return false; 
     589        } 
     590} 
     591 No newline at end of file 
  • src/wp-includes/pomo/native.php

     
     1<?PHP 
     2 
     3  /** 
     4   * Native GetText-Support for WordPress 
     5   * ------------------------------------ 
     6   * 
     7   * Copyright (C) 2012 Bernd Holzmueller <bernd@quarxconnect.de> 
     8   * 
     9   * This program is free software: you can redistribute it and/or modify 
     10   * it under the terms of the GNU General Public License as published by 
     11   * the Free Software Foundation, either version 3 of the License, or 
     12   * (at your option) any later version. 
     13   * 
     14   * This program is distributed in the hope that it will be useful, 
     15   * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     17   * GNU General Public License for more details. 
     18   * 
     19   * You should have received a copy of the GNU General Public License 
     20   * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     21   * 
     22   * @revision 02 
     23   * @author Bernd Holzmueller <bernd@tiggerswelt.net> 
     24   * @url http://oss.tiggerswelt.net/wordpress/3.3.1/ 
     25   **/ 
     26 
     27  // Check if gettext-support is available 
     28  if (!extension_loaded ('gettext')) 
     29    return; 
     30 
     31  class Translate_GetText_Native { 
     32    // Our default domain 
     33    private $Domain = null; 
     34 
     35    // Merged domains 
     36    private $pOthers = array (); 
     37    private $sOthers = array (); 
     38 
     39    // Some Dummy-Function just to be API-compatible 
     40    function add_entry ($entry) { return false; } 
     41    function add_entry_or_merge ($entry) { return false; } 
     42    function set_header ($header, $value) { return false; } 
     43    function set_headers (&$headers) { return false; } 
     44    function get_header ($header) { return false; } 
     45    function translate_entry (&$entry) { return false; } 
     46 
     47    // {{{ select_plural_form 
     48    /** 
     49     * Given the number of items, returns the 0-based index of the plural form to use 
     50     * 
     51     * Here, in the base Translations class, the common logic for English is implemented: 
     52     *      0 if there is one element, 1 otherwise 
     53     * 
     54     * This function should be overrided by the sub-classes. For example MO/PO can derive the logic 
     55     * from their headers. 
     56     * 
     57     * @param integer $count number of items 
     58     **/ 
     59    function select_plural_form ($count) { 
     60      return (1 == $count? 0 : 1); 
     61    } 
     62    // }}} 
     63 
     64    function get_plural_forms_count () { return 2; } 
     65 
     66    // {{{ merge_with 
     67    /** 
     68     * Merge this translation with another one, the other one takes precedence 
     69     * 
     70     * @param object $other 
     71     * 
     72     * @access public 
     73     * @return void 
     74     **/ 
     75    function merge_with (&$other) { 
     76      $this->pOthers [] = $other; 
     77    } 
     78    // }}} 
     79 
     80    // {{{ merge_originals_with 
     81    /** 
     82     * Merge this translation with another one, this one takes precedence 
     83     * 
     84     * @param object $other 
     85     * 
     86     * @access public 
     87     * @return void 
     88     **/ 
     89    function merge_originals_with (&$other) { 
     90      $this->sOthers [] = $Other; 
     91   } 
     92    // }}} 
     93 
     94    // {{{ translate 
     95    /** 
     96     * Try to translate a given string 
     97     * 
     98     * @param string $singular 
     99     * @param string $context (optional) 
     100     * 
     101     * @access public 
     102     * @return string 
     103     **/ 
     104    function translate ($singular, $context = null) { 
     105      // Check for an empty string 
     106      if (strlen ($singular) == 0) 
     107        return $singular; 
     108 
     109      // Check other domains that take precedence 
     110      foreach ($this->pOthers as $o) 
     111        if (($t = $o->translate ($singular, $context)) != $singular) 
     112          return $t; 
     113 
     114      // Make sure we have a domain assigned 
     115      if ($this->Domain === null) 
     116        return $singular; 
     117 
     118      // Translate without a context 
     119      if ($context === null) { 
     120        if (($t = dgettext ($this->Domain, $singular)) != $singular) 
     121          return $t; 
     122 
     123      // Translate with a given context 
     124      } else { 
     125        $T = $context . "\x04" . $singular; 
     126        $t = dgettext ($this->Domain, $T); 
     127 
     128        if ($T != $t) 
     129          return $t; 
     130      } 
     131 
     132      // Check for other domains 
     133      foreach ($this->sOthers as $o) 
     134        if (($t = $o->translate ($singular, $context)) != $singular) 
     135          return $t; 
     136 
     137      return $singular; 
     138    } 
     139    // }}} 
     140 
     141    // {{{ translate_plural 
     142    /** 
     143     * Try to translate a plural string 
     144     * 
     145     * @param string $singular Singular version 
     146     * @param string $plural Plural version 
     147     * @param int $count Number of "items" 
     148     * @param string $context (optional) 
     149     * 
     150     * @access public 
     151     * @return string 
     152     **/ 
     153    function translate_plural ($singular, $plural, $count, $context = null) { 
     154      // Check for an empty string 
     155      if (strlen ($singular) == 0) 
     156        return $singular; 
     157 
     158      // Get the "default" return-value 
     159      $default = ($count == 1 ? $singular : $plural); 
     160 
     161      // Check other domains that take precedence 
     162      foreach ($this->pOthers as $o) 
     163        if (($t = $o->translate_plural ($singular, $plural, $count, $context)) != $default) 
     164          return $t; 
     165 
     166      // Make sure we have a domain assigned 
     167      if ($this->Domain === null) 
     168        return $default; 
     169 
     170      // Translate without context 
     171      if ($context === null) { 
     172        $t = dngettext ($this->Domain, $singular, $plural, $count); 
     173 
     174        if (($t != $singular) && ($t != $plural)) 
     175          return $t; 
     176 
     177      // Translate using a given context 
     178      } else { 
     179        $T = $context . "\x04" . $singular; 
     180        $t = dngettext ($this->Domain, $T, $plural, $count); 
     181 
     182        if (($T != $t) && ($t != $plural)) 
     183          return $t; 
     184      } 
     185 
     186      // Check other domains 
     187      foreach ($this->sOthers as $o) 
     188        if (($t = $o->translate_plural ($singular, $plural, $count, $context)) != $default) 
     189          return $t; 
     190 
     191      return $default; 
     192    } 
     193    // }}} 
     194 
     195    // {{{ import_from_file 
     196    /** 
     197     * Fills up with the entries from MO file $filename 
     198     * 
     199     * @param string $filename MO file to load 
     200     **/ 
     201    function import_from_file ($filename) { 
     202      // Make sure that the locale is set correctly in environment 
     203      global $locale; 
     204 
     205      putenv ('LC_ALL=' . $locale); 
     206      setlocale (LC_ALL, $locale); 
     207 
     208      // Retrive MD5-hash of the file 
     209      # DIRTY! But there is no other way at the moment to make this work 
     210      if (!($Domain = md5_file ($filename))) 
     211        return false; 
     212 
     213      // Make sure that the language-directory exists 
     214      $Path = './wp-lang/' . $locale . '/LC_MESSAGES'; 
     215 
     216      if (!wp_mkdir_p ($Path)) 
     217        return false; 
     218 
     219      // Make sure that the MO-File is existant at the destination 
     220      $fn = $Path . '/' . $Domain . '.mo'; 
     221 
     222      if (!is_file ($fn) && !@copy ($filename, $fn)) 
     223        return false; 
     224 
     225      // Setup the "domain" for gettext 
     226      bindtextdomain ($Domain, './wp-lang/'); 
     227      bind_textdomain_codeset ($Domain, 'UTF-8'); 
     228 
     229      // Do the final stuff and return success 
     230      $this->Domain = $Domain; 
     231 
     232      return true; 
     233    } 
     234    // }}} 
     235  } 
     236 
     237  if (function_exists ('class_alias')) 
     238    class_alias ('Translate_GetText_Native', 'MO'); 
     239  else { 
     240    class MO extends Translate_GetText_Native { } 
     241  } 
     242 
  • src/wp-settings.php

     
    9999require( ABSPATH . WPINC . '/class-wp-matchesmapregex.php' ); 
    100100require( ABSPATH . WPINC . '/class-wp.php' ); 
    101101require( ABSPATH . WPINC . '/class-wp-error.php' ); 
     102require( ABSPATH . WPINC . '/pomo/native.php' ); 
    102103require( ABSPATH . WPINC . '/pomo/mo.php' ); 
     104require( ABSPATH . WPINC . '/pomo/mo-dynamic-loader.php' ); 
    103105 
    104106// Include the wpdb class and, if present, a db.php database drop-in. 
    105107global $wpdb;