Как я могу разобрать getmoxt .mo файлы в PHP4, не полагаясь на setlocale / locales вообще? - PullRequest
2 голосов
/ 23 декабря 2009

Я создал пару связанных тем, но это единственный прямой вопрос, на который я ищу ответ. Мой фреймворк будет использовать Zend_Translate, если версия php 5, в противном случае я должен имитировать функциональность для 4.

Кажется, что почти каждая реализация gettext опирается на setlocale или locales, я знаю, что во многих системах существует много несоответствий, поэтому я не хочу полагаться на это.

Я пару раз пытался заставить работать функции textdomain, bindtextdomain и gettext, но мне всегда нужно было вызывать setlocale.

Кстати, все файлы .mo будут в формате UTF-8.

Ответы [ 2 ]

2 голосов
/ 04 апреля 2012

Вот некоторый код многократного использования для анализа файлов MO в PHP, основанный на Zend_Translate_Adapter_Gettext:

<?php

class MoParser {

    private $_bigEndian   = false;
    private $_file        = false;
    private $_data        = array();

    private function _readMOData($bytes)
    {
        if ($this->_bigEndian === false) {
            return unpack('V' . $bytes, fread($this->_file, 4 * $bytes));
        } else {
            return unpack('N' . $bytes, fread($this->_file, 4 * $bytes));
        }
    }

    public function loadTranslationData($filename, $locale)
    {
        $this->_data      = array();
        $this->_bigEndian = false;
        $this->_file      = @fopen($filename, 'rb');
        if (!$this->_file) throw new Exception('Error opening translation file \'' . $filename . '\'.');
        if (@filesize($filename) < 10) throw new Exception('\'' . $filename . '\' is not a gettext file');

        // get Endian
        $input = $this->_readMOData(1);
        if (strtolower(substr(dechex($input[1]), -8)) == "950412de") {
            $this->_bigEndian = false;
        } else if (strtolower(substr(dechex($input[1]), -8)) == "de120495") {
            $this->_bigEndian = true;
        } else {
            throw new Exception('\'' . $filename . '\' is not a gettext file');
        }
        // read revision - not supported for now
        $input = $this->_readMOData(1);

        // number of bytes
        $input = $this->_readMOData(1);
        $total = $input[1];

        // number of original strings
        $input = $this->_readMOData(1);
        $OOffset = $input[1];

        // number of translation strings
        $input = $this->_readMOData(1);
        $TOffset = $input[1];

        // fill the original table
        fseek($this->_file, $OOffset);
        $origtemp = $this->_readMOData(2 * $total);
        fseek($this->_file, $TOffset);
        $transtemp = $this->_readMOData(2 * $total);

        for($count = 0; $count < $total; ++$count) {
            if ($origtemp[$count * 2 + 1] != 0) {
                fseek($this->_file, $origtemp[$count * 2 + 2]);
                $original = @fread($this->_file, $origtemp[$count * 2 + 1]);
                $original = explode("\0", $original);
            } else {
                $original[0] = '';
            }

            if ($transtemp[$count * 2 + 1] != 0) {
                fseek($this->_file, $transtemp[$count * 2 + 2]);
                $translate = fread($this->_file, $transtemp[$count * 2 + 1]);
                $translate = explode("\0", $translate);
                if ((count($original) > 1) && (count($translate) > 1)) {
                    $this->_data[$locale][$original[0]] = $translate;
                    array_shift($original);
                    foreach ($original as $orig) {
                        $this->_data[$locale][$orig] = '';
                    }
                } else {
                    $this->_data[$locale][$original[0]] = $translate[0];
                }
            }
        }

        $this->_data[$locale][''] = trim($this->_data[$locale]['']);

        unset($this->_data[$locale]['']);
        return $this->_data;
    }

}
1 голос
/ 24 декабря 2009

Хорошо, в итоге я написал парсер mo-файлов, основанный на Zend Gettext Adapter, насколько я знаю, gettext в значительной степени зависит от локали, поэтому ручной анализ файла .mo избавил бы от необходимости работать в странных условиях. с проблемами локали с setlocale. Я также планирую проанализировать данные Zend Locale, представленные в виде XML-файлов.

...