array ( * 0 => array ( * 0 => 'Project-Id-Version: ...', * ), * ), * 'msgid string for translation 1' => array ( // msgid * 0 => array ( * 0 => 'translated string 1', // msgstr * ), * ), * 'msgid string for translation 2' => array ( // msgid * 0 => array ( * 0 => 'translated string 2', // msgstr * ), * 'context explanation for msgstr[1]' => array ( // msgctxt * 0 => 'translated string 2 but different context', // msgstr * ), * 'context explanation for msgstr[2]' => array ( // msgctxt * 0 => 'another translated string 2 with different context', // msgstr * ), * ), * 'msgid string for translation 3' => array ( // msgid * 0 => array ( * 'msgid_plural' => 'plural string for translation 3', // msgid_plural * 0 => 'translated string 3 for nplurals 0', // msgstr[0] * 1 => 'translated string 3 for nplurals 1', // msgstr[1] * 2 => 'translated string 3 for nplurals 2', // msgstr[2] * ), * ), * 'msgid string for translation 4' => array ( // msgid * 'context explanation for msgstr[0]' => array ( // msgctxt * 'msgid_plural' => 'plural string for translation 4', // msgid_plural * 0 => 'translated string 4 for nplurals 0', // msgstr[0] * 1 => 'translated string 4 for nplurals 1', // msgstr[1] * 2 => 'translated string 4 for nplurals 2', // msgstr[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, $translation_in_file = true) { if ($translation_in_file === true) { // read .po file $fh = @fopen($in, 'r'); if ($fh === false) { // Could not open file resource return false; } } else { if (!is_array($in) || empty($in)) { // given translation not valid return false; } $translation_in_file = false; } // results array $hash = array (); // temporary array $temp = array (); // state $state = null; $fuzzy = false; $parse_condition = true; // iterate over lines while($parse_condition) { // output and test line for translation in file if ($translation_in_file) { if (($line = fgets($fh, 65536)) === false) { $parse_condition = false; continue; } // output and test line for translation in array } else { $line = current($in); $end_array_test = next($in); if (false === $end_array_test) { $parse_condition = false; continue; } } $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 if ($translation_in_file) { fclose($fh); } return FALSE; } } break; } } if ($translation_in_file) { 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; } } // add msgctxt if present $msgctxt = (array_key_exists('msgctxt', $entry) ? $entry['msgctxt'][0] : 0); // and also msgid_plural if (array_key_exists('msgid_plural', $entry)) { $entry['msgstr']['msgid_plural'] = $entry['msgid_plural']; } $hash[$entry['msgid']][$msgctxt] = $entry['msgstr']; } return $hash; }