diff --git a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php index cc523ce1bd..1c069aca9b 100644 --- a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php @@ -27,9 +27,16 @@ class PoFileDumper extends FileDumper { $output = ''; + $newLine = FALSE; foreach ($messages->all($domain) as $source => $target) { - $output .= sprintf("msgid \"%s\"\n", $this->escape($source)); - $output .= sprintf("msgstr \"%s\"\n\n", $this->escape($target)); + if ($newLine) { + $output .= "\n"; + } + else { + $newLine = TRUE; + } + $output .= sprintf('msgid "%s"' . "\n", $this->escape($source)); + $output .= sprintf('msgstr "%s"', $this->escape($target)); } return $output; diff --git a/src/Symfony/Component/Translation/Loader/PoFileLoader.php b/src/Symfony/Component/Translation/Loader/PoFileLoader.php index b464f9acb3..dace701bd3 100644 --- a/src/Symfony/Component/Translation/Loader/PoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/PoFileLoader.php @@ -15,6 +15,7 @@ use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) + * @copyright Copyright (c) 2012, Clemens Tolboom */ class PoFileLoader extends ArrayLoader implements LoaderInterface { @@ -41,6 +42,36 @@ class PoFileLoader extends ArrayLoader implements LoaderInterface /** * Parses portable object (PO) format. * + * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files + * we should be able to parse files having: + * + * white-space + * # translator-comments + * #. extracted-comments + * #: reference... + * #, flag... + * #| msgid previous-untranslated-string + * msgid untranslated-string + * msgstr translated-string + * + * extra or different lines are: + * + * #| msgctxt previous-context + * #| msgid previous-untranslated-string + * msgctxt context + * + * #| msgid previous-untranslated-string-singular + * #| msgid_plural previous-untranslated-string-plural + * msgid untranslated-string-singular + * msgid_plural untranslated-string-plural + * msgstr[0] translated-string-case-0 + * ... + * msgstr[N] translated-string-case-n + * + * The definition states: + * - white-space and comments are optional. + * - msgid "" that an empty singleline defines a header. + * * This parser sacrifices some features of the reference implementation the * differences to that implementation are as follows. * - No support for comments spanning multiple lines. @@ -69,20 +100,14 @@ class PoFileLoader extends ArrayLoader implements LoaderInterface $line = trim($line); if ($line === '') { - if (is_array($item['translated'])) { - $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]); - if (isset($item['ids']['plural'])) { - $plurals = array(); - foreach ($item['translated'] as $plural => $translated) { - $plurals[] = $translated; - } - $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); - } - } elseif(!empty($item['ids']['singular'])) { - $messages[$item['ids']['singular']] = stripslashes($item['translated']); - } + // Whitespace indicated current item is done + $this->addMessage($messages, $item); $item = $defaults; } elseif (substr($line, 0, 7) === 'msgid "') { + // We start a new msg so save previous + // TODO: this fails when comments or contexts are added + $this->addMessage($messages, $item); + $item = $defaults; $item['ids']['singular'] = substr($line, 7, -1); } elseif (substr($line, 0, 8) === 'msgstr "') { $item['translated'] = substr($line, 8, -1); @@ -103,8 +128,41 @@ class PoFileLoader extends ArrayLoader implements LoaderInterface } } + // save last item + $this->addMessage($messages, $item); fclose($stream); return $messages; } + + /** + * Save a translation item to the messeages. + * + * A .po file could contain by error missing plural indexes. We need to + * fix these before saving them. + * + * @param array $messages + * @param array $item + */ + private function addMessage(array &$messages, array $item) + { + if (is_array($item['translated'])) { + $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]); + if (isset($item['ids']['plural'])) { + $plurals = $item['translated']; + // PO are by definition indexed so sort by index. + ksort($plurals); + // Make sure every index is filled. + end($plurals); + $count = key($plurals); + // Fill missing spots with '-'. + $empties = array_fill(0, $count+1, '-'); + $plurals += $empties; + ksort($plurals); + $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); + } + } elseif(!empty($item['ids']['singular'])) { + $messages[$item['ids']['singular']] = stripslashes($item['translated']); + } + } } diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources.po b/src/Symfony/Component/Translation/Tests/fixtures/resources.po index 59ecd39896..da0d5f46ae 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources.po +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources.po @@ -1,3 +1,2 @@ msgid "foo" -msgstr "bar" - +msgstr "bar" \ No newline at end of file