Translator.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Translation;
  11. use Symfony\Component\Translation\Loader\LoaderInterface;
  12. /**
  13. * Translator.
  14. *
  15. * @author Fabien Potencier <fabien@symfony.com>
  16. *
  17. * @api
  18. */
  19. class Translator implements TranslatorInterface
  20. {
  21. protected $catalogues;
  22. protected $locale;
  23. private $fallbackLocale;
  24. private $loaders;
  25. private $resources;
  26. private $selector;
  27. /**
  28. * Constructor.
  29. *
  30. * @param string $locale The locale
  31. * @param MessageSelector $selector The message selector for pluralization
  32. *
  33. * @api
  34. */
  35. public function __construct($locale, MessageSelector $selector)
  36. {
  37. $this->locale = $locale;
  38. $this->selector = $selector;
  39. $this->loaders = array();
  40. $this->resources = array();
  41. $this->catalogues = array();
  42. }
  43. /**
  44. * Adds a Loader.
  45. *
  46. * @param string $format The name of the loader (@see addResource())
  47. * @param LoaderInterface $loader A LoaderInterface instance
  48. *
  49. * @api
  50. */
  51. public function addLoader($format, LoaderInterface $loader)
  52. {
  53. $this->loaders[$format] = $loader;
  54. }
  55. /**
  56. * Adds a Resource.
  57. *
  58. * @param string $format The name of the loader (@see addLoader())
  59. * @param mixed $resource The resource name
  60. * @param string $locale The locale
  61. * @param string $domain The domain
  62. *
  63. * @api
  64. */
  65. public function addResource($format, $resource, $locale, $domain = 'messages')
  66. {
  67. $this->resources[$locale][] = array($format, $resource, $domain);
  68. }
  69. /**
  70. * {@inheritdoc}
  71. *
  72. * @api
  73. */
  74. public function setLocale($locale)
  75. {
  76. $this->locale = $locale;
  77. }
  78. /**
  79. * {@inheritdoc}
  80. *
  81. * @api
  82. */
  83. public function getLocale()
  84. {
  85. return $this->locale;
  86. }
  87. /**
  88. * Sets the fallback locale.
  89. *
  90. * @param string $locale The fallback locale
  91. *
  92. * @api
  93. */
  94. public function setFallbackLocale($locale)
  95. {
  96. // needed as the fallback locale is used to fill-in non-yet translated messages
  97. $this->catalogues = array();
  98. $this->fallbackLocale = $locale;
  99. }
  100. /**
  101. * {@inheritdoc}
  102. *
  103. * @api
  104. */
  105. public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null)
  106. {
  107. if (!isset($locale)) {
  108. $locale = $this->getLocale();
  109. }
  110. if (!isset($this->catalogues[$locale])) {
  111. $this->loadCatalogue($locale);
  112. }
  113. return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters);
  114. }
  115. /**
  116. * {@inheritdoc}
  117. *
  118. * @api
  119. */
  120. public function transChoice($id, $number, array $parameters = array(), $domain = 'messages', $locale = null)
  121. {
  122. if (!isset($locale)) {
  123. $locale = $this->getLocale();
  124. }
  125. if (!isset($this->catalogues[$locale])) {
  126. $this->loadCatalogue($locale);
  127. }
  128. if (!$this->catalogues[$locale]->defines((string) $id, $domain)) {
  129. // we will use the fallback
  130. $locale = $this->computeFallbackLocale($locale);
  131. if (!isset($this->catalogues[$locale])) {
  132. $this->loadCatalogue($locale);
  133. }
  134. }
  135. return strtr($this->selector->choose($this->catalogues[$locale]->get((string) $id, $domain), (int) $number, $locale), $parameters);
  136. }
  137. protected function loadCatalogue($locale)
  138. {
  139. $this->catalogues[$locale] = new MessageCatalogue($locale);
  140. if (isset($this->resources[$locale])) {
  141. foreach ($this->resources[$locale] as $resource) {
  142. if (!isset($this->loaders[$resource[0]])) {
  143. throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
  144. }
  145. $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
  146. }
  147. }
  148. $this->optimizeCatalogue($locale);
  149. }
  150. private function optimizeCatalogue($locale)
  151. {
  152. if (!$fallback = $this->computeFallbackLocale($locale)) {
  153. return;
  154. }
  155. if (!isset($this->catalogues[$fallback])) {
  156. $this->loadCatalogue($fallback);
  157. }
  158. $this->catalogues[$locale]->addFallbackCatalogue($this->catalogues[$fallback]);
  159. }
  160. private function computeFallbackLocale($locale)
  161. {
  162. if (strlen($locale) > 3) {
  163. return substr($locale, 0, -strlen(strrchr($locale, '_')));
  164. } else {
  165. return $this->fallbackLocale;
  166. }
  167. }
  168. }