" . basename($mo_file) . "\n"; $entries = parse_po($po_file); write_mo($mo_file, $entries); echo "Done. " . count($entries) . " entries.\n"; } function parse_po($file) { $content = file_get_contents($file); $entries = array(); $current_msgid = null; $current_msgstr = array(); $current_msgid_plural = null; $state = ''; $lines = explode("\n", $content); foreach ($lines as $line) { $line = trim($line); // Skip comments if (empty($line) || $line[0] === '#') { if ($current_msgid !== null && $state !== '') { save_entry($entries, $current_msgid, $current_msgid_plural, $current_msgstr); $current_msgid = null; $current_msgid_plural = null; $current_msgstr = array(); $state = ''; } continue; } if (preg_match('/^msgid\s+"(.*)"$/', $line, $m)) { if ($current_msgid !== null) { save_entry($entries, $current_msgid, $current_msgid_plural, $current_msgstr); } $current_msgid = stripcslashes($m[1]); $current_msgid_plural = null; $current_msgstr = array(); $state = 'msgid'; } elseif (preg_match('/^msgid_plural\s+"(.*)"$/', $line, $m)) { $current_msgid_plural = stripcslashes($m[1]); $state = 'msgid_plural'; } elseif (preg_match('/^msgstr\s+"(.*)"$/', $line, $m)) { $current_msgstr[0] = stripcslashes($m[1]); $state = 'msgstr'; } elseif (preg_match('/^msgstr\[(\d+)\]\s+"(.*)"$/', $line, $m)) { $current_msgstr[(int)$m[1]] = stripcslashes($m[2]); $state = 'msgstr[' . $m[1] . ']'; } elseif (preg_match('/^"(.*)"$/', $line, $m)) { $val = stripcslashes($m[1]); if ($state === 'msgid') { $current_msgid .= $val; } elseif ($state === 'msgid_plural') { $current_msgid_plural .= $val; } elseif (preg_match('/^msgstr/', $state)) { $idx = 0; if (preg_match('/\[(\d+)\]/', $state, $im)) { $idx = (int)$im[1]; } $current_msgstr[$idx] = ($current_msgstr[$idx] ?? '') . $val; } } } if ($current_msgid !== null) { save_entry($entries, $current_msgid, $current_msgid_plural, $current_msgstr); } return $entries; } function save_entry(&$entries, $msgid, $msgid_plural, $msgstr) { if ($msgid === null) return; if ($msgid_plural !== null) { $key = $msgid . "\x00" . $msgid_plural; ksort($msgstr); $val = implode("\x00", $msgstr); } else { $key = $msgid; $val = $msgstr[0] ?? ''; } $entries[$key] = $val; } function write_mo($file, $entries) { ksort($entries); $offsets = array(); $ids = ''; $strs = ''; foreach ($entries as $id => $str) { $offsets[] = array(strlen($id), strlen($ids), strlen($str), strlen($strs)); $ids .= $id . "\x00"; $strs .= $str . "\x00"; } $count = count($offsets); $header_size = 28; $key_offset_start = $header_size; $val_offset_start = $key_offset_start + $count * 8; $keys_start = $val_offset_start + $count * 8; $vals_start = $keys_start + strlen($ids); $output = pack('V', 0x950412de); // magic $output .= pack('V', 0); // revision $output .= pack('V', $count); // number of strings $output .= pack('V', $key_offset_start); // offset of original strings table $output .= pack('V', $val_offset_start); // offset of translated strings table $output .= pack('V', 0); // hash table size $output .= pack('V', 0); // hash table offset // Original strings offsets foreach ($offsets as $o) { $output .= pack('V', $o[0]); // length $output .= pack('V', $keys_start + $o[1]); // offset } // Translated strings offsets foreach ($offsets as $o) { $output .= pack('V', $o[2]); // length $output .= pack('V', $vals_start + $o[3]); // offset } $output .= $ids; $output .= $strs; file_put_contents($file, $output); }