diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index 90b8d7989f..649f5298cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -35,6 +35,7 @@ %kernel.cache_dir%/translations %kernel.debug% + %kernel.charset% diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 34eb0395dc..1a9fd3efbd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -46,8 +46,6 @@ class Translator extends BaseTranslator */ public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array(), Session $session = null) { - parent::__construct(null, $selector); - $this->session = $session; $this->container = $container; $this->loaderIds = $loaderIds; @@ -55,6 +53,7 @@ class Translator extends BaseTranslator $this->options = array( 'cache_dir' => null, 'debug' => false, + 'charset' => null, ); // check option names @@ -63,6 +62,11 @@ class Translator extends BaseTranslator } $this->options = array_merge($this->options, $options); + + if ($this->options['charset'] === 'UTF-8') { + $this->options['charset'] = null; + } + parent::__construct(null, $selector, $this->options['charset']); } /** diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 6661af0b27..2bdff61243 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -28,16 +28,18 @@ class Translator implements TranslatorInterface private $loaders; private $resources; private $selector; + private $charset; /** * Constructor. * * @param string $locale The locale * @param MessageSelector $selector The message selector for pluralization + * @param string $charset Application charset * * @api */ - public function __construct($locale, MessageSelector $selector) + public function __construct($locale, MessageSelector $selector, $charset = null) { $this->locale = $locale; $this->selector = $selector; @@ -45,6 +47,7 @@ class Translator implements TranslatorInterface $this->resources = array(); $this->catalogues = array(); $this->fallbackLocales = array(); + $this->charset = $charset; } /** @@ -173,7 +176,18 @@ class Translator implements TranslatorInterface if (!isset($this->loaders[$resource[0]])) { throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0])); } - $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); + $catalogue = $this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]); + if (null !== $this->charset && extension_loaded('mbstring')) { + foreach ($catalogue->all() as $domain => $messages) { + foreach ($messages as $key => $translation) { + $srcCharset = mb_detect_encoding($translation); + if ($srcCharset !== $this->charset) { + $catalogue->set($key, mb_convert_encoding($translation, $this->charset, $srcCharset), $domain); + } + } + } + } + $this->catalogues[$locale]->addCatalogue($catalogue); } } } diff --git a/tests/Symfony/Tests/Component/Translation/TranslatorTest.php b/tests/Symfony/Tests/Component/Translation/TranslatorTest.php index f1eb5ee807..111ed7e7aa 100644 --- a/tests/Symfony/Tests/Component/Translation/TranslatorTest.php +++ b/tests/Symfony/Tests/Component/Translation/TranslatorTest.php @@ -132,6 +132,27 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr')); } + /** + * @dataProvider getLoadCatalogueTests + */ + public function testLoadCatalogueConvertsEncoding($translation, $charset) + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('This test relies on the mbstring extension'); + } + $translator = new Translator('en', new MessageSelector(), $charset); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', array('id' => $translation), 'en', 'messages'); + + if (null !== $charset && mb_detect_encoding($translation) !== $charset) { + $expected = mb_convert_encoding($translation, $charset, mb_detect_encoding($translation)); + } else { + $expected = $translation; + } + + $this->assertEquals($expected, $translator->trans('id', array(), 'messages', 'en')); + } + /** * @dataProvider getTransChoiceTests */ @@ -199,6 +220,21 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase ); } + public function getLoadCatalogueTests() + { + return array( + array('oia', null), + array('oia', 'UTF-8'), + array('öïä', 'UTF-8'), + array('oia', 'ISO-8859-1'), + array('öïä', 'ISO-8859-1'), + array('цфЭ', 'UTF-8'), + array('цфЭ', 'KOI8-R'), + array('ヨラリ', 'UTF-8'), + array('ヨラリ', 'SJIS'), + ); + } + public function testTransChoiceFallback() { $translator = new Translator('ru', new MessageSelector());