namespace Symfony\Component\Translation;
-use Symfony\Component\Translation\Loader\LoaderInterface;
-use Symfony\Component\Translation\Exception\NotFoundResourceException;
-use Symfony\Component\Config\ConfigCacheInterface;
-use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Config\ConfigCacheFactory;
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
+use Symfony\Component\Config\ConfigCacheInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
+use Symfony\Component\Translation\Loader\LoaderInterface;
/**
- * Translator.
- *
* @author Fabien Potencier <fabien@symfony.com>
*/
class Translator implements TranslatorInterface, TranslatorBagInterface
/**
* @var string
*/
- protected $locale;
+ private $locale;
/**
* @var array
private $resources = array();
/**
- * @var MessageSelector
+ * @var MessageFormatterInterface
*/
- private $selector;
+ private $formatter;
/**
* @var string
private $configCacheFactory;
/**
- * Constructor.
+ * @param string $locale The locale
+ * @param MessageFormatterInterface|null $formatter The message formatter
+ * @param string|null $cacheDir The directory to use for the cache
+ * @param bool $debug Use cache in debug mode ?
*
- * @param string $locale The locale
- * @param MessageSelector|null $selector The message selector for pluralization
- * @param string|null $cacheDir The directory to use for the cache
- * @param bool $debug Use cache in debug mode ?
- *
- * @throws \InvalidArgumentException If a locale contains invalid characters
+ * @throws InvalidArgumentException If a locale contains invalid characters
*/
- public function __construct($locale, MessageSelector $selector = null, $cacheDir = null, $debug = false)
+ public function __construct($locale, $formatter = null, $cacheDir = null, $debug = false)
{
$this->setLocale($locale);
- $this->selector = $selector ?: new MessageSelector();
+
+ if ($formatter instanceof MessageSelector) {
+ $formatter = new MessageFormatter($formatter);
+ @trigger_error(sprintf('Passing a "%s" instance into the "%s()" method as a second argument is deprecated since Symfony 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED);
+ } elseif (null === $formatter) {
+ $formatter = new MessageFormatter();
+ }
+
+ $this->formatter = $formatter;
$this->cacheDir = $cacheDir;
$this->debug = $debug;
}
- /**
- * Sets the ConfigCache factory to use.
- *
- * @param ConfigCacheFactoryInterface $configCacheFactory
- */
public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
{
$this->configCacheFactory = $configCacheFactory;
* @param string $locale The locale
* @param string $domain The domain
*
- * @throws \InvalidArgumentException If the locale contains invalid characters
+ * @throws InvalidArgumentException If the locale contains invalid characters
*/
public function addResource($format, $resource, $locale, $domain = null)
{
$this->resources[$locale][] = array($format, $resource, $domain);
- if (in_array($locale, $this->fallbackLocales)) {
+ if (\in_array($locale, $this->fallbackLocales)) {
$this->catalogues = array();
} else {
unset($this->catalogues[$locale]);
return $this->locale;
}
- /**
- * Sets the fallback locale(s).
- *
- * @param string|array $locales The fallback locale(s)
- *
- * @throws \InvalidArgumentException If a locale contains invalid characters
- *
- * @deprecated since version 2.3, to be removed in 3.0. Use setFallbackLocales() instead
- */
- public function setFallbackLocale($locales)
- {
- @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Use the setFallbackLocales() method instead.', E_USER_DEPRECATED);
-
- $this->setFallbackLocales(is_array($locales) ? $locales : array($locales));
- }
-
/**
* Sets the fallback locales.
*
* @param array $locales The fallback locales
*
- * @throws \InvalidArgumentException If a locale contains invalid characters
+ * @throws InvalidArgumentException If a locale contains invalid characters
*/
public function setFallbackLocales(array $locales)
{
$domain = 'messages';
}
- return strtr($this->getCatalogue($locale)->get((string) $id, $domain), $parameters);
+ return $this->formatter->format($this->getCatalogue($locale)->get((string) $id, $domain), $locale, $parameters);
}
/**
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
{
+ if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
+ throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
+ }
+
if (null === $domain) {
$domain = 'messages';
}
}
}
- return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
+ return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
}
/**
return $this->loaders;
}
- /**
- * Collects all messages for the given locale.
- *
- * @param string|null $locale Locale of translations, by default is current locale
- *
- * @return array[array] indexed by catalog
- *
- * @deprecated since version 2.8, to be removed in 3.0. Use TranslatorBagInterface::getCatalogue() method instead.
- */
- public function getMessages($locale = null)
- {
- @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0. Use TranslatorBagInterface::getCatalogue() method instead.', E_USER_DEPRECATED);
-
- $catalogue = $this->getCatalogue($locale);
- $messages = $catalogue->all();
- while ($catalogue = $catalogue->getFallbackCatalogue()) {
- $messages = array_replace_recursive($catalogue->all(), $messages);
- }
-
- return $messages;
- }
-
/**
* @param string $locale
*/
}
$this->assertValidLocale($locale);
- $self = $this; // required for PHP 5.3 where "$this" cannot be use()d in anonymous functions. Change in Symfony 3.0.
$cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
- function (ConfigCacheInterface $cache) use ($self, $locale) {
- $self->dumpCatalogue($locale, $cache);
+ function (ConfigCacheInterface $cache) use ($locale) {
+ $this->dumpCatalogue($locale, $cache);
}
);
$this->catalogues[$locale] = include $cache->getPath();
}
- /**
- * This method is public because it needs to be callable from a closure in PHP 5.3. It should be made protected (or even private, if possible) in 3.0.
- *
- * @internal
- */
- public function dumpCatalogue($locale, ConfigCacheInterface $cache)
+ private function dumpCatalogue($locale, ConfigCacheInterface $cache)
{
$this->initializeCatalogue($locale);
$fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
private function getCatalogueCachePath($locale)
{
- return $this->cacheDir.'/catalogue.'.$locale.'.'.sha1(serialize($this->fallbackLocales)).'.php';
+ return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php';
}
private function doLoadCatalogue($locale)
if (isset($this->resources[$locale])) {
foreach ($this->resources[$locale] as $resource) {
if (!isset($this->loaders[$resource[0]])) {
- throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $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]));
}
foreach ($this->computeFallbackLocales($locale) as $fallback) {
if (!isset($this->catalogues[$fallback])) {
- $this->loadCatalogue($fallback);
+ $this->initializeCatalogue($fallback);
}
$fallbackCatalogue = new MessageCatalogue($fallback, $this->catalogues[$fallback]->all());
$locales[] = $fallback;
}
- if (strrchr($locale, '_') !== false) {
- array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
+ if (false !== strrchr($locale, '_')) {
+ array_unshift($locales, substr($locale, 0, -\strlen(strrchr($locale, '_'))));
}
return array_unique($locales);
*
* @param string $locale Locale to tests
*
- * @throws \InvalidArgumentException If the locale contains invalid characters
+ * @throws InvalidArgumentException If the locale contains invalid characters
*/
protected function assertValidLocale($locale)
{
if (1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
- throw new \InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
+ throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
}
}