Intl.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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\Intl;
  11. use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader;
  12. use Symfony\Component\Intl\Data\Bundle\Reader\BufferedBundleReader;
  13. use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader;
  14. use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
  15. use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
  16. use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
  17. use Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface;
  18. use Symfony\Component\Intl\ResourceBundle\LanguageBundle;
  19. use Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface;
  20. use Symfony\Component\Intl\ResourceBundle\LocaleBundle;
  21. use Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface;
  22. use Symfony\Component\Intl\ResourceBundle\RegionBundle;
  23. use Symfony\Component\Intl\ResourceBundle\RegionBundleInterface;
  24. /**
  25. * Gives access to internationalization data.
  26. *
  27. * @author Bernhard Schussek <bschussek@gmail.com>
  28. */
  29. final class Intl
  30. {
  31. /**
  32. * The number of resource bundles to buffer. Loading the same resource
  33. * bundle for n locales takes up n spots in the buffer.
  34. */
  35. const BUFFER_SIZE = 10;
  36. /**
  37. * The directory name of the currency data.
  38. */
  39. const CURRENCY_DIR = 'currencies';
  40. /**
  41. * The directory name of the language data.
  42. */
  43. const LANGUAGE_DIR = 'languages';
  44. /**
  45. * The directory name of the script data.
  46. */
  47. const SCRIPT_DIR = 'scripts';
  48. /**
  49. * The directory name of the locale data.
  50. */
  51. const LOCALE_DIR = 'locales';
  52. /**
  53. * The directory name of the region data.
  54. */
  55. const REGION_DIR = 'regions';
  56. /**
  57. * @var ResourceBundle\CurrencyBundleInterface
  58. */
  59. private static $currencyBundle;
  60. /**
  61. * @var ResourceBundle\LanguageBundleInterface
  62. */
  63. private static $languageBundle;
  64. /**
  65. * @var ResourceBundle\LocaleBundleInterface
  66. */
  67. private static $localeBundle;
  68. /**
  69. * @var ResourceBundle\RegionBundleInterface
  70. */
  71. private static $regionBundle;
  72. /**
  73. * @var string|bool|null
  74. */
  75. private static $icuVersion = false;
  76. /**
  77. * @var string
  78. */
  79. private static $icuDataVersion = false;
  80. /**
  81. * @var BundleEntryReaderInterface
  82. */
  83. private static $entryReader;
  84. /**
  85. * Returns whether the intl extension is installed.
  86. *
  87. * @return bool Returns true if the intl extension is installed, false otherwise
  88. */
  89. public static function isExtensionLoaded()
  90. {
  91. return class_exists('\ResourceBundle');
  92. }
  93. /**
  94. * Returns the bundle containing currency information.
  95. *
  96. * @return CurrencyBundleInterface The currency resource bundle
  97. */
  98. public static function getCurrencyBundle()
  99. {
  100. if (null === self::$currencyBundle) {
  101. self::$currencyBundle = new CurrencyBundle(
  102. self::getDataDirectory().'/'.self::CURRENCY_DIR,
  103. self::getEntryReader(),
  104. self::getLocaleBundle()
  105. );
  106. }
  107. return self::$currencyBundle;
  108. }
  109. /**
  110. * Returns the bundle containing language information.
  111. *
  112. * @return LanguageBundleInterface The language resource bundle
  113. */
  114. public static function getLanguageBundle()
  115. {
  116. if (null === self::$languageBundle) {
  117. self::$languageBundle = new LanguageBundle(
  118. self::getDataDirectory().'/'.self::LANGUAGE_DIR,
  119. self::getEntryReader(),
  120. self::getLocaleBundle(),
  121. new ScriptDataProvider(
  122. self::getDataDirectory().'/'.self::SCRIPT_DIR,
  123. self::getEntryReader()
  124. )
  125. );
  126. }
  127. return self::$languageBundle;
  128. }
  129. /**
  130. * Returns the bundle containing locale information.
  131. *
  132. * @return LocaleBundleInterface The locale resource bundle
  133. */
  134. public static function getLocaleBundle()
  135. {
  136. if (null === self::$localeBundle) {
  137. self::$localeBundle = new LocaleBundle(
  138. self::getDataDirectory().'/'.self::LOCALE_DIR,
  139. self::getEntryReader()
  140. );
  141. }
  142. return self::$localeBundle;
  143. }
  144. /**
  145. * Returns the bundle containing region information.
  146. *
  147. * @return RegionBundleInterface The region resource bundle
  148. */
  149. public static function getRegionBundle()
  150. {
  151. if (null === self::$regionBundle) {
  152. self::$regionBundle = new RegionBundle(
  153. self::getDataDirectory().'/'.self::REGION_DIR,
  154. self::getEntryReader(),
  155. self::getLocaleBundle()
  156. );
  157. }
  158. return self::$regionBundle;
  159. }
  160. /**
  161. * Returns the version of the installed ICU library.
  162. *
  163. * @return null|string The ICU version or NULL if it could not be determined
  164. */
  165. public static function getIcuVersion()
  166. {
  167. if (false === self::$icuVersion) {
  168. if (!self::isExtensionLoaded()) {
  169. self::$icuVersion = self::getIcuStubVersion();
  170. } elseif (defined('INTL_ICU_VERSION')) {
  171. self::$icuVersion = INTL_ICU_VERSION;
  172. } else {
  173. try {
  174. $reflector = new \ReflectionExtension('intl');
  175. ob_start();
  176. $reflector->info();
  177. $output = strip_tags(ob_get_clean());
  178. preg_match('/^ICU version (?:=>)?(.*)$/m', $output, $matches);
  179. self::$icuVersion = trim($matches[1]);
  180. } catch (\ReflectionException $e) {
  181. self::$icuVersion = null;
  182. }
  183. }
  184. }
  185. return self::$icuVersion;
  186. }
  187. /**
  188. * Returns the version of the installed ICU data.
  189. *
  190. * @return string The version of the installed ICU data
  191. */
  192. public static function getIcuDataVersion()
  193. {
  194. if (false === self::$icuDataVersion) {
  195. self::$icuDataVersion = trim(file_get_contents(self::getDataDirectory().'/version.txt'));
  196. }
  197. return self::$icuDataVersion;
  198. }
  199. /**
  200. * Returns the ICU version that the stub classes mimic.
  201. *
  202. * @return string The ICU version of the stub classes
  203. */
  204. public static function getIcuStubVersion()
  205. {
  206. return '58.2';
  207. }
  208. /**
  209. * Returns the absolute path to the data directory.
  210. *
  211. * @return string The absolute path to the data directory
  212. */
  213. public static function getDataDirectory()
  214. {
  215. return __DIR__.'/Resources/data';
  216. }
  217. /**
  218. * Returns the cached bundle entry reader.
  219. *
  220. * @return BundleEntryReaderInterface The bundle entry reader
  221. */
  222. private static function getEntryReader()
  223. {
  224. if (null === self::$entryReader) {
  225. self::$entryReader = new BundleEntryReader(new BufferedBundleReader(
  226. new JsonBundleReader(),
  227. self::BUFFER_SIZE
  228. ));
  229. }
  230. return self::$entryReader;
  231. }
  232. /**
  233. * This class must not be instantiated.
  234. */
  235. private function __construct()
  236. {
  237. }
  238. }