From deb6dea76dec7d38671afa5ff3f2c278ea28dd65 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 3 Oct 2011 12:12:49 +0200 Subject: [PATCH 1/2] [Translation] Add failing tests to verify that UTF-8 lang files can't be used with another charset --- .../Component/Translation/TranslatorTest.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/Symfony/Tests/Component/Translation/TranslatorTest.php b/tests/Symfony/Tests/Component/Translation/TranslatorTest.php index f1eb5ee807efa..111ed7e7aadf3 100644 --- a/tests/Symfony/Tests/Component/Translation/TranslatorTest.php +++ b/tests/Symfony/Tests/Component/Translation/TranslatorTest.php @@ -132,6 +132,27 @@ public function testFlattenedTrans($expected, $messages, $id) $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 @@ public function getTransChoiceTests() ); } + 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()); From 5473d3b6c94ac38d0658f9745c582f840d49464e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 3 Oct 2011 12:33:01 +0200 Subject: [PATCH 2/2] [Translation] Allow use of UTF-8 encoded catalogues into non-UTF-8 applications --- .../Resources/config/translation.xml | 1 + .../FrameworkBundle/Translation/Translator.php | 8 ++++++-- .../Component/Translation/Translator.php | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index 90b8d7989f299..649f5298cf951 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 34eb0395dcf84..1a9fd3efbd2a4 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 @@ public function __construct(ContainerInterface $container, MessageSelector $sele $this->options = array( 'cache_dir' => null, 'debug' => false, + 'charset' => null, ); // check option names @@ -63,6 +62,11 @@ public function __construct(ContainerInterface $container, MessageSelector $sele } $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 6661af0b27dd1..2bdff6124364f 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 @@ public function __construct($locale, MessageSelector $selector) $this->resources = array(); $this->catalogues = array(); $this->fallbackLocales = array(); + $this->charset = $charset; } /** @@ -173,7 +176,18 @@ private function doLoadCatalogue($locale) 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); } } }