Skip to content

Commit

Permalink
merged branch clemens-tolboom/pofileloader-better-whitelines (PR #4339)
Browse files Browse the repository at this point in the history
Commits
-------

fb6cf3e Allow for missing whitelines.

Discussion
----------

Allow for missing whitelines.

The Gettext specification allows for 'whitespace is optional' between message string.

For this to work PoFileLoader needs to save found messages on more places while processing. Thus a new method is introduced.

For the tests to work PoFileDumper was changed slightly to only emit white-lines when necessary.

I added more documentation from the GNU gettext documentation to make the code more understandable.

When [[BUG] PoFileLoader pluralhandling uses interval instead of index.](symfony/symfony#4336) this patch needs some small rework.

(this is part of [[WIP]: Allow Drupal to use Translate component)](symfony/symfony#4249)

---------------------------------------------------------------------------

by travisbot at 2012-05-19T12:44:19Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1374295) (merged fb6cf3ef into 58b92453).

---------------------------------------------------------------------------

by stof at 2012-05-19T13:19:29Z

you need to rebase your branch. github tells us it cannot be merged automatically
  • Loading branch information
fabpot committed May 19, 2012
2 parents f3486a2 + 66a0aa6 commit f269b7b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 16 deletions.
11 changes: 9 additions & 2 deletions Dumper/PoFileDumper.php
Expand Up @@ -27,9 +27,16 @@ public function format(MessageCatalogue $messages, $domain = 'messages')
{
$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;
Expand Down
82 changes: 70 additions & 12 deletions Loader/PoFileLoader.php
Expand Up @@ -15,6 +15,7 @@

/**
* @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
{
Expand All @@ -41,6 +42,36 @@ public function load($resource, $locale, $domain = 'messages')
/**
* 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.
Expand Down Expand Up @@ -69,20 +100,14 @@ private function parse($resource)
$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);
Expand All @@ -103,8 +128,41 @@ private function parse($resource)
}

}
// 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']);
}
}
}
3 changes: 1 addition & 2 deletions Tests/fixtures/resources.po
@@ -1,3 +1,2 @@
msgid "foo"
msgstr "bar"

msgstr "bar"

0 comments on commit f269b7b

Please sign in to comment.