MessagesFileLoader.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\I18n;
  16. use Aura\Intl\Package;
  17. use Cake\Core\App;
  18. use Cake\Core\Plugin;
  19. use Cake\Utility\Inflector;
  20. use \Locale;
  21. /**
  22. * A generic translations package factory that will load translations files
  23. * based on the file extension and the package name.
  24. *
  25. * This class is a callable, so it can be used as a package loader argument.
  26. */
  27. class MessagesFileLoader {
  28. /**
  29. * The package (domain) name.
  30. *
  31. * @var string
  32. */
  33. protected $_name;
  34. /**
  35. * The locale to load for the given package.
  36. *
  37. * @var string
  38. */
  39. protected $_locale;
  40. /**
  41. * The extension name.
  42. *
  43. * @var string
  44. */
  45. protected $_extension;
  46. /**
  47. * Creates a translation file loader. The file to be loaded corresponds to
  48. * the following rules:
  49. *
  50. * - The locale is a folder under the `Locale` directory, a fallback will be
  51. * used if the folder is not found.
  52. * - The $name corresponds to the file name to load
  53. * - If there is a loaded plugin with the underscored version of $name, the
  54. * translation file will be loaded from such plugin.
  55. *
  56. * @param string $name The name (domain) of the translations package.
  57. * @param string $locale The locale to load, this will be mapped to a folder
  58. * in the system.
  59. * @param string $extension The file extension to use. This will also be mapped
  60. * to a messages parser class.
  61. */
  62. public function __construct($name, $locale, $extension = 'po') {
  63. $this->_name = $name;
  64. $this->_locale = $locale;
  65. $this->_extension = $extension;
  66. }
  67. /**
  68. * Loads the translation file and parses it. Returns an instance of a translations
  69. * package containing the messages loaded from the file.
  70. *
  71. * @return Aura\Intl\Package
  72. * @throws \RuntimeException if no file parser class could be found for the specified
  73. * file extension.
  74. */
  75. public function __invoke() {
  76. $package = new Package;
  77. $folder = $this->translationsFolder();
  78. $ext = $this->_extension;
  79. if (!$folder || !is_file($folder . $this->_name . ".$ext")) {
  80. return $package;
  81. }
  82. $name = ucfirst($ext);
  83. $class = App::classname($name, 'I18n\Parser', 'FileParser');
  84. if (!$class) {
  85. throw new \RuntimeException(sprintf('Could not find class %s', "{$name}FileParser"));
  86. }
  87. $messages = (new $class)->parse($folder . $this->_name . ".$ext");
  88. $package->setMessages($messages);
  89. return $package;
  90. }
  91. /**
  92. * Returns the folder where the file should be looked for according to the locale
  93. * and package name.
  94. *
  95. * @return string|boolean The folder where the file should be looked for or false
  96. * if it does not exists.
  97. */
  98. public function translationsFolder() {
  99. $locale = Locale::parseLocale($this->_locale) + ['region' => null];
  100. $folders = [
  101. implode('_', [$locale['language'], $locale['region']]),
  102. $locale['language']
  103. ];
  104. $pluginName = Inflector::camelize($this->_name);
  105. $basePath = APP . 'Locale' . DS;
  106. if (Plugin::loaded($pluginName)) {
  107. $basePath = Plugin::path($pluginName) . 'src' . DS . 'Locale' . DS;
  108. }
  109. foreach ($folders as $folder) {
  110. $path = $basePath . $folder . DS;
  111. if (is_dir($path)) {
  112. return $path;
  113. }
  114. }
  115. return false;
  116. }
  117. }