GettextPoFile.php 2.68 KB
Newer Older
resurtm committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
<?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
{
	/**
	 * 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);
Alexander Makarov committed
33
		$matches = [];
resurtm committed
34 35
		$matchCount = preg_match_all($pattern, $content, $matches);

Alexander Makarov committed
36
		$messages = [];
resurtm committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
		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;
			}
		}
		return $messages;
	}

	/**
	 * 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);
	}

	/**
	 * 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(
Alexander Makarov committed
77 78
			['"', "\n", "\t", "\r"],
			['\\"', '\\n', '\\t', '\\r'],
resurtm committed
79 80 81 82 83 84 85 86 87 88 89 90
			$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(
Alexander Makarov committed
91 92
			['/"\s+"/', '/\\\\n/', '/\\\\r/', '/\\\\t/', '/\\\\"/'],
			['', "\n", "\r", "\t", '"'],
resurtm committed
93 94 95 96 97
			$string
		);
		return substr(rtrim($string), 1, -1);
	}
}