GettextPoFile.php 3.15 KB
Newer Older
resurtm committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\i18n;

use Yii;

/**
 * GettextPoFile represents a PO Gettext message file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class GettextPoFile extends GettextFile
{
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
    /**
     * Loads messages from a PO file.
     * @param  string $filePath file path
     * @param  string $context  message context
     * @return array  message translations. Array keys are source messages and array values are translated messages:
     *                         source message => translated message.
     */
    public function load($filePath, $context)
    {
        $pattern = '/(msgctxt\s+"(.*?(?<!\\\\))")?\s+' // context
            . 'msgid\s+((?:".*(?<!\\\\)"\s*)+)\s+' // message ID, i.e. original string
            . 'msgstr\s+((?:".*(?<!\\\\)"\s*)+)/'; // translated string
        $content = file_get_contents($filePath);
        $matches = [];
        $matchCount = preg_match_all($pattern, $content, $matches);
resurtm committed
35

36 37 38 39 40 41 42 43
        $messages = [];
        for ($i = 0; $i < $matchCount; ++$i) {
            if ($matches[2][$i] == $context) {
                $id = $this->decode($matches[3][$i]);
                $message = $this->decode($matches[4][$i]);
                $messages[$id] = $message;
            }
        }
resurtm committed
44

45 46
        return $messages;
    }
resurtm committed
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    /**
     * Saves messages to a PO file.
     * @param string $filePath file path
     * @param array  $messages message translations. Array keys are source messages and array values are
     *                         translated messages: source message => translated message. Note if the message has a context,
     *                         the message ID must be prefixed with the context with chr(4) as the separator.
     */
    public function save($filePath, $messages)
    {
        $content = '';
        foreach ($messages as $id => $message) {
            $separatorPosition = strpos($id, chr(4));
            if ($separatorPosition !== false) {
                $content .= 'msgctxt "' . substr($id, 0, $separatorPosition) . "\"\n";
                $id = substr($id, $separatorPosition + 1);
            }
            $content .= 'msgid "' . $this->encode($id) . "\"\n";
            $content .= 'msgstr "' . $this->encode($message) . "\"\n\n";
        }
        file_put_contents($filePath, $content);
    }
resurtm committed
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    /**
     * Encodes special characters in a message.
     * @param  string $string message to be encoded
     * @return string the encoded message
     */
    protected function encode($string)
    {
        return str_replace(
            ['"', "\n", "\t", "\r"],
            ['\\"', '\\n', '\\t', '\\r'],
            $string
        );
    }

    /**
     * Decodes special characters in a message.
     * @param  string $string message to be decoded
     * @return string the decoded message
     */
    protected function decode($string)
    {
        $string = preg_replace(
            ['/"\s+"/', '/\\\\n/', '/\\\\r/', '/\\\\t/', '/\\\\"/'],
            ['', "\n", "\r", "\t", '"'],
            $string
        );

        return substr(rtrim($string), 1, -1);
    }
resurtm committed
99
}