[Translation] added support for more than one fallback locale
This commit is contained in:
parent
3a4d1a6a22
commit
5526072dba
@ -38,6 +38,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
||||
|
||||
### Translation
|
||||
|
||||
* added support for more than one fallback locale
|
||||
* added support for translations in ResourceBundles
|
||||
* added support for extracting translation messages from templates (Twig and PHP)
|
||||
* added dumpers for translation catalogs
|
||||
|
@ -24,7 +24,7 @@ class Translator implements TranslatorInterface
|
||||
{
|
||||
protected $catalogues;
|
||||
protected $locale;
|
||||
private $fallbackLocale;
|
||||
private $fallbackLocales;
|
||||
private $loaders;
|
||||
private $resources;
|
||||
private $selector;
|
||||
@ -44,6 +44,7 @@ class Translator implements TranslatorInterface
|
||||
$this->loaders = array();
|
||||
$this->resources = array();
|
||||
$this->catalogues = array();
|
||||
$this->fallbackLocales = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,18 +96,18 @@ class Translator implements TranslatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fallback locale.
|
||||
* Sets the fallback locale(s).
|
||||
*
|
||||
* @param string $locale The fallback locale
|
||||
* @param string|array $locale The fallback locale(s)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setFallbackLocale($locale)
|
||||
public function setFallbackLocale($locales)
|
||||
{
|
||||
// needed as the fallback locale is used to fill-in non-yet translated messages
|
||||
// needed as the fallback locales are linked to the already loaded catalogues
|
||||
$this->catalogues = array();
|
||||
|
||||
$this->fallbackLocale = $locale;
|
||||
$this->fallbackLocales = is_array($locales) ? $locales : array($locales);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,15 +143,28 @@ class Translator implements TranslatorInterface
|
||||
$this->loadCatalogue($locale);
|
||||
}
|
||||
|
||||
if (!$this->catalogues[$locale]->defines((string) $id, $domain)) {
|
||||
// we will use the fallback
|
||||
$locale = $this->computeFallbackLocale($locale);
|
||||
$id = (string) $id;
|
||||
|
||||
if (!$this->catalogues[$locale]->defines($id, $domain)) {
|
||||
// we will use the locale fallback
|
||||
foreach ($this->computeFallbackLocales($locale) as $fallback) {
|
||||
if ($this->catalogues[$fallback]->defines($id, $domain)) {
|
||||
$locale = $fallback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strtr($this->selector->choose($this->catalogues[$locale]->get((string) $id, $domain), (int) $number, $locale), $parameters);
|
||||
return strtr($this->selector->choose($this->catalogues[$locale]->get($id, $domain), (int) $number, $locale), $parameters);
|
||||
}
|
||||
|
||||
protected function loadCatalogue($locale)
|
||||
{
|
||||
$this->doLoadCatalogue($locale);
|
||||
$this->optimizeCatalogue($locale);
|
||||
}
|
||||
|
||||
private function doLoadCatalogue($locale)
|
||||
{
|
||||
$this->catalogues[$locale] = new MessageCatalogue($locale);
|
||||
|
||||
@ -162,29 +176,29 @@ class Translator implements TranslatorInterface
|
||||
$this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
|
||||
}
|
||||
}
|
||||
|
||||
$this->optimizeCatalogue($locale);
|
||||
}
|
||||
|
||||
private function optimizeCatalogue($locale)
|
||||
{
|
||||
if (!$fallback = $this->computeFallbackLocale($locale)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current = $this->catalogues[$locale];
|
||||
foreach ($this->computeFallbackLocales($locale) as $fallback) {
|
||||
if (!isset($this->catalogues[$fallback])) {
|
||||
$this->loadCatalogue($fallback);
|
||||
$this->doLoadCatalogue($fallback);
|
||||
}
|
||||
|
||||
$this->catalogues[$locale]->addFallbackCatalogue($this->catalogues[$fallback]);
|
||||
$current->addFallbackCatalogue($this->catalogues[$fallback]);
|
||||
$current = $this->catalogues[$fallback];
|
||||
}
|
||||
}
|
||||
|
||||
private function computeFallbackLocale($locale)
|
||||
private function computeFallbackLocales($locale)
|
||||
{
|
||||
$locales = $this->fallbackLocales;
|
||||
|
||||
if (strlen($locale) > 3) {
|
||||
return substr($locale, 0, -strlen(strrchr($locale, '_')));
|
||||
} else {
|
||||
return $this->fallbackLocale;
|
||||
array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
|
||||
}
|
||||
|
||||
return $locales;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,20 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('foobar', $translator->trans('bar'));
|
||||
}
|
||||
|
||||
public function testSetFallbackLocaleMultiple()
|
||||
{
|
||||
$translator = new Translator('en', new MessageSelector());
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('foo' => 'foo (en)'), 'en');
|
||||
$translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');
|
||||
|
||||
// force catalogue loading
|
||||
$translator->trans('bar');
|
||||
|
||||
$translator->setFallbackLocale(array('fr_FR', 'fr'));
|
||||
$this->assertEquals('bar (fr)', $translator->trans('bar'));
|
||||
}
|
||||
|
||||
public function testTransWithFallbackLocale()
|
||||
{
|
||||
$translator = new Translator('fr_FR', new MessageSelector());
|
||||
@ -62,6 +76,19 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('foobar', $translator->trans('bar'));
|
||||
}
|
||||
|
||||
public function testTransWithFallbackLocaleTer()
|
||||
{
|
||||
$translator = new Translator('fr_FR', new MessageSelector());
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('foo' => 'foo (en_US)'), 'en_US');
|
||||
$translator->addResource('array', array('bar' => 'bar (en)'), 'en');
|
||||
|
||||
$translator->setFallbackLocale(array('en_US', 'en'));
|
||||
|
||||
$this->assertEquals('foo (en_US)', $translator->trans('foo'));
|
||||
$this->assertEquals('bar (en)', $translator->trans('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
@ -173,6 +200,28 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||
}
|
||||
|
||||
public function testTransChoiceFallbackBis()
|
||||
{
|
||||
$translator = new Translator('ru', new MessageSelector());
|
||||
$translator->setFallbackLocale(array('en_US', 'en'));
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en_US');
|
||||
|
||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testTransChoiceFallbackWithNoTranslation()
|
||||
{
|
||||
$translator = new Translator('ru', new MessageSelector());
|
||||
$translator->setFallbackLocale('en');
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
|
||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||
}
|
||||
}
|
||||
|
||||
class String
|
||||
|
Reference in New Issue
Block a user