3 * Class for working with MO files
5 * @version $Id: mo.php 33 2009-02-16 09:33:39Z nbachiyski $
10 require_once dirname(__FILE__) . '/translations.php';
11 require_once dirname(__FILE__) . '/streams.php';
13 class MO extends Translations {
17 function set_header($header, $value) {
18 parent::set_header($header, $value);
19 if ('Plural-Forms' == $header)
20 $this->_gettext_select_plural_form = $this->_make_gettext_select_plural_form($value);
24 * Fills up with the entries from MO file $filename
26 * @param string $filename MO file to load
28 function import_from_file($filename) {
29 $reader = new POMO_CachedIntFileReader($filename);
30 if (isset($reader->error)) {
33 return $this->import_from_reader($reader);
36 function get_byteorder($magic) {
38 // The magic is 0x950412de
40 // bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565
41 $magic_little = (int) - 1794895138;
42 $magic_little_64 = (int) 2500072158;
44 $magic_big = ((int) - 569244523) && 0xFFFFFFFF;
46 if ($magic_little == $magic || $magic_little_64 == $magic) {
48 } else if ($magic_big == $magic) {
55 function import_from_reader($reader) {
56 $reader->setEndian('little');
57 $endian = MO::get_byteorder($reader->readint32());
58 if (false === $endian) {
61 $reader->setEndian($endian);
63 $revision = $reader->readint32();
64 $total = $reader->readint32();
65 // get addresses of array of lenghts and offsets for original string and translations
66 $originals_lo_addr = $reader->readint32();
67 $translations_lo_addr = $reader->readint32();
69 $reader->seekto($originals_lo_addr);
70 $originals_lo = $reader->readint32array($total * 2); // each of
71 $reader->seekto($translations_lo_addr);
72 $translations_lo = $reader->readint32array($total * 2);
74 $length = create_function('$i', 'return $i * 2 + 1;');
75 $offset = create_function('$i', 'return $i * 2 + 2;');
77 for ($i = 0; $i < $total; ++$i) {
78 $reader->seekto($originals_lo[$offset($i)]);
79 $original = $reader->read($originals_lo[$length($i)]);
80 $reader->seekto($translations_lo[$offset($i)]);
81 $translation = $reader->read($translations_lo[$length($i)]);
82 if ('' == $original) {
83 $this->set_headers($this->make_headers($translation));
85 $this->add_entry($this->make_entry($original, $translation));
91 function make_headers($translation) {
93 $lines = explode("\n", $translation);
94 foreach($lines as $line) {
95 $parts = explode(':', $line, 2);
96 if (!isset($parts[1])) continue;
97 $headers[trim($parts[0])] = trim($parts[1]);
105 function &make_entry($original, $translation) {
108 $parts = explode(chr(4), $original);
109 if (isset($parts[1])) {
110 $original = $parts[1];
111 $args['context'] = $parts[0];
113 // look for plural original
114 $parts = explode(chr(0), $original);
115 $args['singular'] = $parts[0];
116 if (isset($parts[1])) {
117 $args['plural'] = $parts[1];
119 // plural translations are also separated by \0
120 $args['translations'] = explode(chr(0), $translation);
121 $entry = & new Translation_Entry($args);
125 function select_plural_form($count) {
126 return $this->gettext_select_plural_form($count);
129 function get_plural_forms_count() {
130 return $this->_nplurals;