FileLoader.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. namespace Illuminate\Translation;
  3. use Illuminate\Contracts\Translation\Loader;
  4. use Illuminate\Filesystem\Filesystem;
  5. use Illuminate\Support\Collection;
  6. use RuntimeException;
  7. class FileLoader implements Loader
  8. {
  9. /**
  10. * The filesystem instance.
  11. *
  12. * @var \Illuminate\Filesystem\Filesystem
  13. */
  14. protected $files;
  15. /**
  16. * The default paths for the loader.
  17. *
  18. * @var array
  19. */
  20. protected $paths;
  21. /**
  22. * All of the registered paths to JSON translation files.
  23. *
  24. * @var array
  25. */
  26. protected $jsonPaths = [];
  27. /**
  28. * All of the namespace hints.
  29. *
  30. * @var array
  31. */
  32. protected $hints = [];
  33. /**
  34. * Create a new file loader instance.
  35. *
  36. * @param \Illuminate\Filesystem\Filesystem $files
  37. * @param array|string $path
  38. */
  39. public function __construct(Filesystem $files, array|string $path)
  40. {
  41. $this->files = $files;
  42. $this->paths = is_string($path) ? [$path] : $path;
  43. }
  44. /**
  45. * Load the messages for the given locale.
  46. *
  47. * @param string $locale
  48. * @param string $group
  49. * @param string|null $namespace
  50. * @return array
  51. */
  52. public function load($locale, $group, $namespace = null)
  53. {
  54. if ($group === '*' && $namespace === '*') {
  55. return $this->loadJsonPaths($locale);
  56. }
  57. if (is_null($namespace) || $namespace === '*') {
  58. return $this->loadPaths($this->paths, $locale, $group);
  59. }
  60. return $this->loadNamespaced($locale, $group, $namespace);
  61. }
  62. /**
  63. * Load a namespaced translation group.
  64. *
  65. * @param string $locale
  66. * @param string $group
  67. * @param string $namespace
  68. * @return array
  69. */
  70. protected function loadNamespaced($locale, $group, $namespace)
  71. {
  72. if (isset($this->hints[$namespace])) {
  73. $lines = $this->loadPaths([$this->hints[$namespace]], $locale, $group);
  74. return $this->loadNamespaceOverrides($lines, $locale, $group, $namespace);
  75. }
  76. return [];
  77. }
  78. /**
  79. * Load a local namespaced translation group for overrides.
  80. *
  81. * @param array $lines
  82. * @param string $locale
  83. * @param string $group
  84. * @param string $namespace
  85. * @return array
  86. */
  87. protected function loadNamespaceOverrides(array $lines, $locale, $group, $namespace)
  88. {
  89. return (new Collection($this->paths))
  90. ->reduce(function ($output, $path) use ($locale, $group, $namespace) {
  91. $file = "{$path}/vendor/{$namespace}/{$locale}/{$group}.php";
  92. if ($this->files->exists($file)) {
  93. $output = array_replace_recursive($output, $this->files->getRequire($file));
  94. }
  95. return $output;
  96. }, $lines);
  97. }
  98. /**
  99. * Load a locale from a given path.
  100. *
  101. * @param array $paths
  102. * @param string $locale
  103. * @param string $group
  104. * @return array
  105. */
  106. protected function loadPaths(array $paths, $locale, $group)
  107. {
  108. return (new Collection($paths))
  109. ->reduce(function ($output, $path) use ($locale, $group) {
  110. if ($this->files->exists($full = "{$path}/{$locale}/{$group}.php")) {
  111. $output = array_replace_recursive($output, $this->files->getRequire($full));
  112. }
  113. return $output;
  114. }, []);
  115. }
  116. /**
  117. * Load a locale from the given JSON file path.
  118. *
  119. * @param string $locale
  120. * @return array
  121. *
  122. * @throws \RuntimeException
  123. */
  124. protected function loadJsonPaths($locale)
  125. {
  126. return (new Collection(array_merge($this->jsonPaths, $this->paths)))
  127. ->reduce(function ($output, $path) use ($locale) {
  128. if ($this->files->exists($full = "{$path}/{$locale}.json")) {
  129. $decoded = json_decode($this->files->get($full), true);
  130. if (is_null($decoded) || json_last_error() !== JSON_ERROR_NONE) {
  131. throw new RuntimeException("Translation file [{$full}] contains an invalid JSON structure.");
  132. }
  133. $output = array_merge($output, $decoded);
  134. }
  135. return $output;
  136. }, []);
  137. }
  138. /**
  139. * Add a new namespace to the loader.
  140. *
  141. * @param string $namespace
  142. * @param string $hint
  143. * @return void
  144. */
  145. public function addNamespace($namespace, $hint)
  146. {
  147. $this->hints[$namespace] = $hint;
  148. }
  149. /**
  150. * Get an array of all the registered namespaces.
  151. *
  152. * @return array
  153. */
  154. public function namespaces()
  155. {
  156. return $this->hints;
  157. }
  158. /**
  159. * Add a new path to the loader.
  160. *
  161. * @param string $path
  162. * @return void
  163. */
  164. public function addPath($path)
  165. {
  166. $this->paths[] = $path;
  167. }
  168. /**
  169. * Add a new JSON path to the loader.
  170. *
  171. * @param string $path
  172. * @return void
  173. */
  174. public function addJsonPath($path)
  175. {
  176. $this->jsonPaths[] = $path;
  177. }
  178. /**
  179. * Get an array of all the registered paths to translation files.
  180. *
  181. * @return array
  182. */
  183. public function paths()
  184. {
  185. return $this->paths;
  186. }
  187. /**
  188. * Get an array of all the registered paths to JSON translation files.
  189. *
  190. * @return array
  191. */
  192. public function jsonPaths()
  193. {
  194. return $this->jsonPaths;
  195. }
  196. }