diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
index 32eed76e608a7..4d9b96b8f64e2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
@@ -19,6 +19,8 @@
Symfony\Component\Translation\Loader\IniFileLoader
Symfony\Component\Translation\Dumper\PhpFileDumper
Symfony\Component\Translation\Dumper\XliffFileDumper
+ Symfony\Component\Translation\Dumper\PoFileDumper
+ Symfony\Component\Translation\Dumper\MoFileDumper
Symfony\Component\Translation\Dumper\YamlFileDumper
Symfony\Component\Translation\Dumper\QtFileDumper
Symfony\Component\Translation\Dumper\CsvFileDumper
@@ -90,6 +92,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php
new file mode 100644
index 0000000000000..84eafa33ae711
--- /dev/null
+++ b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php
@@ -0,0 +1,82 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Loader\MoFileLoader;
+
+/**
+ * MoFileDumper generates a gettext formated string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class MoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function format(MessageCatalogue $messages, $domain = 'messages')
+ {
+ $output = $sources = $targets = $source_offsets = $target_offsets = '';
+ $offsets = array();
+ $size = 0;
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $offsets[] = array_map('strlen', array($sources, $source, $targets, $target));
+ $sources .= "\0".$source;
+ $targets .= "\0".$target;
+ ++$size;
+ }
+
+ $header = array(
+ 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
+ 'formatRevision' => 0,
+ 'count' => $size,
+ 'offsetId' => MoFileLoader::MO_HEADER_SIZE,
+ 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
+ 'sizeHashes' => 0,
+ 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
+ );
+
+ $sources_size = strlen($sources);
+ $sources_start = $header['offsetHashes'] + 1;
+
+ foreach ($offsets as $offset) {
+ $source_offsets .= $this->writeLong($offset[1])
+ . $this->writeLong($offset[0] + $sources_start);
+ $target_offsets .= $this->writeLong($offset[3])
+ . $this->writeLong($offset[2] + $sources_start + $sources_size);
+ }
+
+ $output = implode(array_map(array($this, 'writeLong'), $header))
+ . $source_offsets
+ . $target_offsets
+ . $sources
+ . $targets
+ ;
+
+ return $output;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getExtension()
+ {
+ return 'mo';
+ }
+
+ private function writeLong($str)
+ {
+ return pack('V*', $str);
+ }
+}
diff --git a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php
new file mode 100644
index 0000000000000..82e26b9e0d483
--- /dev/null
+++ b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PoFileDumper generates a gettext formated string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class PoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function format(MessageCatalogue $messages, $domain = 'messages')
+ {
+ $output = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $output .= sprintf("msgid \"%s\"\n", $this->escape($source));
+ $output .= sprintf("msgstr \"%s\"\n\n", $this->escape($target));
+ }
+
+ return $output;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getExtension()
+ {
+ return 'po';
+ }
+
+ private function escape($str)
+ {
+ return addcslashes($str, "\0..\37\42\134");
+ }
+}
diff --git a/tests/Symfony/Tests/Component/Translation/Dumper/MoFileDumperTest.php b/tests/Symfony/Tests/Component/Translation/Dumper/MoFileDumperTest.php
new file mode 100644
index 0000000000000..34a309e13b72a
--- /dev/null
+++ b/tests/Symfony/Tests/Component/Translation/Dumper/MoFileDumperTest.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\MoFileDumper;
+
+class MoFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDump()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $tempDir = sys_get_temp_dir();
+ $dumper = new MoFileDumper();
+ $dumperString = $dumper->dump($catalogue, array('path' => $tempDir));
+ $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.mo'), file_get_contents($tempDir.'/messages.en.mo'));
+
+ unlink($tempDir.'/messages.en.mo');
+ }
+}
diff --git a/tests/Symfony/Tests/Component/Translation/Dumper/PoFileDumperTest.php b/tests/Symfony/Tests/Component/Translation/Dumper/PoFileDumperTest.php
new file mode 100644
index 0000000000000..bc4491351842e
--- /dev/null
+++ b/tests/Symfony/Tests/Component/Translation/Dumper/PoFileDumperTest.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\PoFileDumper;
+
+class PoFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDump()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $tempDir = sys_get_temp_dir();
+ $dumper = new PoFileDumper();
+ $dumperString = $dumper->dump($catalogue, array('path' => $tempDir));
+ $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.po'), file_get_contents($tempDir.'/messages.en.po'));
+
+ unlink($tempDir.'/messages.en.po');
+ }
+}