<?php
/**
* Changes from php.mo:
* supress the error if there's no file
* fixed "fuzzy flag first line" bug which didn't saved previous proper string at all
* fix the warning if list finds no $data
* added case for commented unused string
* proper handling of msgctxt
* better storing of same msgid
* corrected data structure for correct counting of plural msgstr
* don't add last translation if it's fuzzy
* removed unedeed phpmo_convert and phpmo_write_mo_file
* more info on https://bugs.mageia.org/show_bug.cgi?id=14899
* 
* it returns array of translations:
* $dictionary = phpmo_parse_po_file('input.po');
*
* $dictionary = array (
*	'' => array (
*		'msgid' => '',
*		'msgstr' => array (
*		   0 => 'Project-Id-Version: ...',
*		),
*	),
*	'string for translation 1' => array (
*		'msgid' => 'string for translation 1',
*		'msgstr' => array (
*			0 => 'translated string 1',
*		),
*	),
*	'string for translation 2' => array (
*		'msgid' => 'string for translation 2',
*		'msgstr' => array (
*			0 => 'translated string 2',
*			1 => 'translated string 2 but different context',
*			2 => 'another translated string 2 with different context',
*		),
*		'msgctxt' => array (
*			1 => 'context explanation for msgstr[1]',
*			2 => 'context explanation for msgstr[2]',
*		),
*	),
*	'string for translation 3' => array (
*		'msgid' => 'string for translation 3',
*		'msgid_plural' => 'plural string for translation 3',
*		'msgstr' => array (
*			0 => array (
*				0 => 'translated string 3 for nplurals 0',
*				1 => 'translated string 3 for nplurals 1',
*				2 => 'translated string 3 for nplurals 2',
*			),
*		),
*	),
* );
*
****************************************************************************************
*
* based on php.mo 0.1 by Joss Crowcroft (http://www.josscrowcroft.com)
* which is
* Based on php-msgfmt by Matthias Bauer (Copyright © 2007), a command-line PHP tool
* for converting .po files to .mo.
* (http://wordpress-soc-2007.googlecode.com/svn/trunk/moeffju/php-msgfmt/msgfmt.php)
*
* License: GPL v3 http://www.opensource.org/licenses/gpl-3.0.html
*/

function phpmo_clean_helper($x) {
	if (is_array($x)) {
		foreach ($x as $k => $v) {
			$x[$k] = phpmo_clean_helper($v);
		}
	} else {
		if ($x[0] == '"')
			$x = substr($x, 1, -1);
		$x = str_replace("\"\n\"", '', $x);
		$x = str_replace('$', '\\$', $x);
	}
	return $x;
}

/* Parse gettext .po files. */
/* @link http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files */
function phpmo_parse_po_file($in) {
	// read .po file
	$fh = @fopen($in, 'r');
	if ($fh === false) {
		// Could not open file resource
		return false;
	}

	// results array
	$hash = array ();
	// temporary array
	$temp = array ();
	// state
	$state = null;
	$fuzzy = false;

	// iterate over lines
	while(($line = fgets($fh, 65536)) !== false) {
		$line = trim($line);
		if ($line === '')
			continue;

		$array_of_splited_string = preg_split('/\s/', $line, 2);
		$key = $array_of_splited_string[0];
		$data = (isset($array_of_splited_string[1]) ? $array_of_splited_string[1] : '');
		switch ($key) {
			case '#,' : // flag...
			case '#' : // translator-comments
			case '#.' : // extracted-comments
			case '#:' : // reference...
			case '#|' : // msgid previous-untranslated-string
			case '#~' : // commented-unused-string
				// start a new entry
				if (sizeof($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) {
					if (!$fuzzy)
						$hash[] = $temp;
					$temp = array ();
					$state = null;
					$fuzzy = false;
				}
				if ($key == '#,') 
					$fuzzy = in_array('fuzzy', preg_split('/,\s*/', $data));
				break;
			case 'msgctxt' :
				// context
			case 'msgid' :
				// untranslated-string
			case 'msgid_plural' :
				// untranslated-string-plural
				$state = $key;
				// store previous entry if it exists
				if (sizeof($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) {
					if (!$fuzzy)
						$hash[] = $temp;
					$temp = array ();
					$fuzzy = false;
				}
				if ($key == 'msgctxt') {
						if (array_key_exists('msgstr', $temp)) {
							$msgctxt_index = count($temp['msgstr']);
						} else {
							$msgctxt_index = 0;
						}
						$temp['msgctxt'][$msgctxt_index] = $data;
				} else {
					$temp[$state] = $data;
				}
				break;
			case 'msgstr' :
				// translated-string
				$state = 'msgstr';
				$temp[$state][] = $data;
				break;
			default :
				if (strpos($key, 'msgstr[') !== FALSE) {
					// translated-string-case-n
					$state = 'msgstr';
					$temp[$state][] = $data;
				} else {
					// continued lines
					switch ($state) {
						case 'msgid' :
						case 'msgid_plural' :
							$temp[$state] .= "\n" . $line;
							break;
						case 'msgctxt' :
						case 'msgstr' :
							$temp[$state][sizeof($temp[$state]) - 1] .= "\n" . $line;
							break;
						default :
							// parse error
							fclose($fh);
							return FALSE;
					}
				}
				break;
		}
	}
	fclose($fh);

	// add final entry
	if ($state == 'msgstr')
		if (!$fuzzy)
			$hash[] = $temp;

	// Cleanup data, merge multiline entries, reindex hash for ksort
	$temp = $hash;
	$hash = array ();
	foreach ($temp as $entry) {
		foreach ($entry as & $v) {
			$v = phpmo_clean_helper($v);
			if ($v === FALSE) {
				// parse error
				return FALSE;
			}
		}
		// if there's already same msgid we need to store it there
		if (array_key_exists($entry['msgid'], $hash)) {
			$index = count($hash[$entry['msgid']]['msgstr']);
			$hash[$entry['msgid']]['msgstr'][$index] = $entry['msgstr'][0];
			// is different msgctxt present also?
			if (array_key_exists('msgctxt', $entry)) {
				$hash[$entry['msgid']]['msgctxt'][$index] = $entry['msgctxt'][0];
			}
		} else {
			// if msgid_plural exists we need to store msgstr to subarray for proper counting of l10n completion
			if (array_key_exists('msgid_plural', $entry)) {
				$msgstr_plural   = $entry['msgstr'];
				$entry['msgstr']   = array();
				$entry['msgstr'][] = $msgstr_plural;
			}
			$hash[$entry['msgid']] = $entry;
		}
	}

	return $hash;
}