a?oW7.Ԩ ?4?|I%*;*`Y?lcoUU졁 b\N Dq8t`ݬV!jU, dUloFnLA7[r`;$HoBf&@.*n2*߫tDq|%P^w !bxD_J} QjvLj\vݾl?Xf; gI2x97J%, !Wן-񲧐0MNǨ2csJVO+:rP2]%]F„h@1q0I+QE8b# rcƽ Fy*\aAG** A+,g*X7G:0*W-Hai34zIdܞk9g|,3l&n孮^qh/vئ?;ROճ6TT@}r|.t,3ogY4ĊznKeY04¹D䡀XC_3O= T7\D?ArHG}%TY 5hYZqKR܋ݲMmZNլ^;]lj_]xY^B-X6-9v,6{^s<[x{zm38C,ZqBk&yg.À*a~zO?>-o -<3T1 esF9o.jEґccT0Nxy4tkS YXW>/04[0,l% wqS߽$|ugat ,/2%[ +ϑI3)XKv4e?D*p} CWvķJ{)YVV_i~H 2Ц+Nxw`z؋^X_+0lS|_YxJdFriz_>5mG)ge/7G{IhNo1rUC+G"U2PXʲKt = ~J,~&pLO`W`t2K[}Rf+wW#~6ʚRXұ=!N?j Daz q YDNF%%샣TSpUH_dС1‹RBrB;@bM]}U_WqoR/qOB(cOz_pl#^ x#Ǔs]FbПڃ)A0f;E!b󳱇q"nW^4&@P2 }nW"ۯcA?6C4#Z!6BNbdl -V0;_,:BxDqխiݶ෇Ђ_m(h6"8kT#%-0v~xٓ(o lnll:BhG{mClv6g`/ёu<#NRu^~j5{oDwYsss{6 K {|yp6Oda OWWLw%Z)a) 6 Vnd.Fٙ;y7ZZ/.Y)3]8kޠvvuuDZ[&6{ "{6\iNQaֽvՈ)Ʊ #<;/o^~#ڟ‘?sd% W3yt&8ټf{=:LJjxT,q=*` $ }(̄īNR|-2wAji}/!Ll4r2C%*J-h-> d$hvjelR֋!n%Dl8kL-6k/*Vb bt:vpi'kaqksmߛCqZ  _-+IJņE/@qAiQ~`7e*37j7zlV"GjKW!ڙX:پ'cJNSUZNH &:ys:$\S9_+Wa)t^2O)YDBw+, _yl ?(A昆|eX*pPu*6zk9ȝ+{+μD4;RjδX-R>qۚGg+@ONCOIN<4xL 4gUGn, +(Gp̂ y: }9PbG}c^/wLpS/%/kY 2Ğ!ȧ)1?7 'q%0n/\fRFuD=ƞ1^z.t@u[& }ׂf@A^Z[7`xђZ9,EH,Ai Ȗ:>kq#|X`[37(Mٳ~K'J44UEYO>uc_l; } if ( $entry->context ) { $exported = $entry->context . "\4" . $exported; } return $exported; } /** * @param Translation_Entry $entry * @return string */ public function export_translations( $entry ) { // TODO: Warnings for control characters. return $entry->is_plural ? implode( "\0", $entry->translations ) : $entry->translations[0]; } /** * @return string */ public function export_headers() { $exported = ''; foreach ( $this->headers as $header => $value ) { $exported .= "$header: $value\n"; } return $exported; } /** * @param int $magic * @return string|false */ public function get_byteorder( $magic ) { // The magic is 0x950412de. // bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 $magic_little = (int) - 1794895138; $magic_little_64 = (int) 2500072158; // 0xde120495 $magic_big = ( (int) - 569244523 ) & 0xFFFFFFFF; if ( $magic_little == $magic || $magic_little_64 == $magic ) { return 'little'; } elseif ( $magic_big == $magic ) { return 'big'; } else { return false; } } /** * @param POMO_FileReader $reader * @return bool True if the import was successful, otherwise false. */ public function import_from_reader( $reader ) { $endian_string = MO::get_byteorder( $reader->readint32() ); if ( false === $endian_string ) { return false; } $reader->setEndian( $endian_string ); $endian = ( 'big' === $endian_string ) ? 'N' : 'V'; $header = $reader->read( 24 ); if ( $reader->strlen( $header ) != 24 ) { return false; } // Parse header. $header = unpack( "{$endian}revision/{$endian}total/{$endian}originals_lengths_addr/{$endian}translations_lengths_addr/{$endian}hash_length/{$endian}hash_addr", $header ); if ( ! is_array( $header ) ) { return false; } // Support revision 0 of MO format specs, only. if ( 0 != $header['revision'] ) { return false; } // Seek to data blocks. $reader->seekto( $header['originals_lengths_addr'] ); // Read originals' indices. $originals_lengths_length = $header['translations_lengths_addr'] - $header['originals_lengths_addr']; if ( $originals_lengths_length != $header['total'] * 8 ) { return false; } $originals = $reader->read( $originals_lengths_length ); if ( $reader->strlen( $originals ) != $originals_lengths_length ) { return false; } // Read translations' indices. $translations_lengths_length = $header['hash_addr'] - $header['translations_lengths_addr']; if ( $translations_lengths_length != $header['total'] * 8 ) { return false; } $translations = $reader->read( $translations_lengths_length ); if ( $reader->strlen( $translations ) != $translations_lengths_length ) { return false; } // Transform raw data into set of indices. $originals = $reader->str_split( $originals, 8 ); $translations = $reader->str_split( $translations, 8 ); // Skip hash table. $strings_addr = $header['hash_addr'] + $header['hash_length'] * 4; $reader->seekto( $strings_addr ); $strings = $reader->read_all(); $reader->close(); for ( $i = 0; $i < $header['total']; $i++ ) { $o = unpack( "{$endian}length/{$endian}pos", $originals[ $i ] ); $t = unpack( "{$endian}length/{$endian}pos", $translations[ $i ] ); if ( ! $o || ! $t ) { return false; } // Adjust offset due to reading strings to separate space before. $o['pos'] -= $strings_addr; $t['pos'] -= $strings_addr; $original = $reader->substr( $strings, $o['pos'], $o['length'] ); $translation = $reader->substr( $strings, $t['pos'], $t['length'] ); if ( '' === $original ) { $this->set_headers( $this->make_headers( $translation ) ); } else { $entry = &$this->make_entry( $original, $translation ); $this->entries[ $entry->key() ] = &$entry; } } return true; } /** * Build a Translation_Entry from original string and translation strings, * found in a MO file * * @static * @param string $original original string to translate from MO file. Might contain * 0x04 as context separator or 0x00 as singular/plural separator * @param string $translation translation string from MO file. Might contain * 0x00 as a plural translations separator * @return Translation_Entry Entry instance. */ public function &make_entry( $original, $translation ) { $entry = new Translation_Entry(); // Look for context, separated by \4. $parts = explode( "\4", $original ); if ( isset( $parts[1] ) ) { $original = $parts[1]; $entry->context = $parts[0]; } // Look for plural original. $parts = explode( "\0", $original ); $entry->singular = $parts[0]; if ( isset( $parts[1] ) ) { $entry->is_plural = true; $entry->plural = $parts[1]; } // Plural translations are also separated by \0. $entry->translations = explode( "\0", $translation ); return $entry; } /** * @param int $count * @return string */ public function select_plural_form( $count ) { return $this->gettext_select_plural_form( $count ); } /** * @return int */ public function get_plural_forms_count() { return $this->_nplurals; } } endif;