1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
namespace Nexendrie\Translation\Loaders; |
5
|
|
|
|
6
|
|
|
use Nette\Utils\Finder; |
7
|
|
|
use Nette\Utils\Strings; |
8
|
|
|
use Nexendrie\Translation\ILocaleResolver; |
9
|
|
|
use Nexendrie\Translation\Resolvers\ManualLocaleResolver; |
10
|
|
|
use Nexendrie\Translation\ISettableLocaleResolver; |
11
|
|
|
use Nexendrie\Translation\InvalidFolderException; |
12
|
|
|
use Nexendrie\Translation\FolderNotSetException; |
13
|
|
|
use Nette\Utils\Arrays; |
14
|
|
|
use Nexendrie\Translation\IFileLoader; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Generic file translations loader |
18
|
|
|
* Loads texts from {$this->extension} files |
19
|
|
|
* You need to define method parseFile() which processes individual file |
20
|
|
|
* |
21
|
|
|
* @author Jakub Konečný |
22
|
|
|
* @property string $lang |
23
|
|
|
* @property-read array $texts |
24
|
|
|
* @property string[] $folders |
25
|
|
|
* @property-read array $resources |
26
|
|
|
* @method void onLanguageChange(FileLoader $loader, string $oldLang, string $newLang) |
27
|
|
|
* @method void onFoldersChange(FileLoader $loader, string[] $folders) |
28
|
|
|
* @method void onLoad(FileLoader $loader, string $lang) |
29
|
|
|
*/ |
30
|
1 |
|
abstract class FileLoader implements IFileLoader { |
31
|
|
|
use \Nette\SmartObject; |
32
|
|
|
|
33
|
|
|
protected const DOMAIN_MASK = "%domain%"; |
34
|
|
|
protected const LANGUAGE_MASK = "%language%"; |
35
|
|
|
|
36
|
|
|
public string $defaultLang = "en"; |
37
|
|
|
protected ?string $loadedLang = null; |
38
|
|
|
protected array $texts = []; |
39
|
|
|
/** @var string[] */ |
40
|
|
|
protected array $folders = []; |
41
|
|
|
protected ILocaleResolver $resolver; |
42
|
|
|
protected array $resources = []; |
43
|
|
|
protected string $extension; |
44
|
|
|
/** @var callable[] */ |
45
|
|
|
public array $onLanguageChange = []; |
46
|
|
|
/** @var callable[] */ |
47
|
|
|
public array $onFoldersChange = []; |
48
|
|
|
/** @var callable[] */ |
49
|
|
|
public array $onLoad = []; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @param string[] $folders |
53
|
|
|
*/ |
54
|
|
|
public function __construct(ILocaleResolver $resolver = null, array $folders = []) { |
55
|
1 |
|
$this->setFolders($folders); |
|
|
|
|
56
|
1 |
|
$this->resolver = $resolver ?? new ManualLocaleResolver(); |
57
|
1 |
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @deprecated Access the property directly |
61
|
|
|
*/ |
62
|
|
|
public function getLang(): string { |
63
|
1 |
|
return $this->resolver->resolve() ?? $this->defaultLang; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @deprecated Access the property directly |
68
|
|
|
*/ |
69
|
|
|
public function setLang(string $lang): void { |
70
|
1 |
|
if(is_a($this->resolver, ISettableLocaleResolver::class)) { |
71
|
1 |
|
$oldLang = $this->lang; |
72
|
1 |
|
$this->resolver->setLang($lang); |
73
|
1 |
|
$this->onLanguageChange($this, $oldLang, $lang); |
74
|
|
|
} |
75
|
1 |
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @deprecated Access the property directly |
79
|
|
|
*/ |
80
|
|
|
public function getDefaultLang(): string { |
81
|
1 |
|
return $this->defaultLang; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @deprecated Access the property directly |
86
|
|
|
*/ |
87
|
|
|
public function setDefaultLang(string $defaultLang): void { |
88
|
1 |
|
$this->defaultLang = $defaultLang; |
89
|
1 |
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @return string[] |
93
|
|
|
* @deprecated Access the property directly |
94
|
|
|
*/ |
95
|
|
|
public function getFolders(): array { |
96
|
1 |
|
return $this->folders; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @param string[] $folders |
101
|
|
|
* @throws InvalidFolderException |
102
|
|
|
* @deprecated Access the property directly |
103
|
|
|
*/ |
104
|
|
|
public function setFolders(array $folders): void { |
105
|
1 |
|
foreach($folders as $folder) { |
106
|
1 |
|
if(!is_dir($folder)) { |
107
|
1 |
|
throw new InvalidFolderException("Folder $folder does not exist."); |
108
|
|
|
} |
109
|
1 |
|
$this->folders[] = $folder; |
110
|
|
|
} |
111
|
1 |
|
$this->onFoldersChange($this, $folders); |
112
|
1 |
|
} |
113
|
|
|
|
114
|
|
|
protected function addResource(string $filename, string $domain): void { |
115
|
1 |
|
if(!isset($this->resources[$domain]) || !in_array($filename, $this->resources[$domain], true)) { |
116
|
1 |
|
$this->resources[$domain][] = $filename; |
117
|
|
|
} |
118
|
1 |
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* @deprecated Access the property directly |
122
|
|
|
*/ |
123
|
|
|
public function getResources(): array { |
124
|
1 |
|
return $this->resources; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Parse individual file |
129
|
|
|
*/ |
130
|
|
|
abstract protected function parseFile(string $filename): array; |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Load texts from one text domain |
134
|
|
|
*/ |
135
|
|
|
protected function loadDomain(string $name): array { |
136
|
1 |
|
$return = []; |
137
|
1 |
|
$defaultLang = $this->defaultLang; |
138
|
1 |
|
$defaultFilename = $this->getLanguageFilenameMask(); |
139
|
1 |
|
$defaultFilename = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], [$name, $defaultLang, ], $defaultFilename); |
|
|
|
|
140
|
1 |
|
$files = Finder::findFiles($defaultFilename) |
141
|
1 |
|
->from($this->folders); |
142
|
|
|
/** @var \SplFileInfo $file */ |
143
|
1 |
|
foreach($files as $file) { |
144
|
1 |
|
$default = $this->parseFile($file->getPathname()); |
145
|
1 |
|
$this->addResource($file->getPathname(), $name); |
146
|
1 |
|
$lang = []; |
147
|
1 |
|
$filename = str_replace($defaultLang, $this->lang, $defaultFilename); |
148
|
1 |
|
$filename = str_replace($defaultFilename, $filename, $file->getPathname()); |
149
|
1 |
|
if($this->lang != $defaultLang && is_file($filename)) { |
150
|
1 |
|
$lang = $this->parseFile($filename); |
151
|
1 |
|
$this->addResource($filename, $name); |
152
|
|
|
} |
153
|
1 |
|
$return = Arrays::mergeTree($return, Arrays::mergeTree($lang, $default)); |
154
|
|
|
} |
155
|
1 |
|
return $return; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Load all texts |
160
|
|
|
* |
161
|
|
|
* @throws FolderNotSetException |
162
|
|
|
*/ |
163
|
|
|
protected function loadTexts(): void { |
164
|
1 |
|
if($this->lang === $this->loadedLang) { |
165
|
1 |
|
return; |
166
|
|
|
} |
167
|
1 |
|
if(count($this->folders) === 0) { |
168
|
1 |
|
throw new FolderNotSetException("Folder for translations was not set."); |
169
|
|
|
} |
170
|
1 |
|
$default = $this->defaultLang; |
171
|
1 |
|
$this->resources = $texts = []; |
172
|
1 |
|
$mask = $this->getLanguageFilenameMask(); |
173
|
1 |
|
$mask = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], ["*", $default, ], $mask); |
174
|
1 |
|
$files = Finder::findFiles($mask) |
175
|
1 |
|
->from($this->folders); |
176
|
|
|
/** @var \SplFileInfo $file */ |
177
|
1 |
|
foreach($files as $file) { |
178
|
1 |
|
$domain = $file->getBasename((string) Strings::after($mask, "*")); |
179
|
1 |
|
$texts[$domain] = $this->loadDomain($domain); |
180
|
|
|
} |
181
|
1 |
|
$this->texts = $texts; |
182
|
1 |
|
$this->loadedLang = $this->lang; |
183
|
1 |
|
$this->onLoad($this, $this->lang); |
184
|
1 |
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @deprecated Access the property directly |
188
|
|
|
*/ |
189
|
|
|
public function getTexts(): array { |
190
|
1 |
|
$this->loadTexts(); |
191
|
1 |
|
return $this->texts; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
public function getResolverName(): string { |
195
|
1 |
|
$class = get_class($this->resolver); |
196
|
1 |
|
return (string) Strings::after($class, '\\', -1); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
protected function getLanguageFilenameMask(): string { |
200
|
1 |
|
return static::DOMAIN_MASK . "." . static::LANGUAGE_MASK . "." . $this->extension; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* @return string[] |
205
|
|
|
* @throws FolderNotSetException |
206
|
|
|
*/ |
207
|
|
|
public function getAvailableLanguages(): array { |
208
|
1 |
|
if(count($this->folders) === 0) { |
209
|
1 |
|
throw new FolderNotSetException("Folder for translations was not set."); |
210
|
|
|
} |
211
|
1 |
|
$languages = []; |
212
|
1 |
|
$extension = $this->extension; |
213
|
1 |
|
$mask = $this->getLanguageFilenameMask(); |
214
|
1 |
|
$mask = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], "*", $mask); |
215
|
1 |
|
$files = Finder::findFiles($mask) |
216
|
1 |
|
->from($this->folders); |
217
|
|
|
/** @var \SplFileInfo $file */ |
218
|
1 |
|
foreach($files as $file) { |
219
|
1 |
|
$filename = $file->getBasename(".$extension"); |
220
|
1 |
|
$lang = (string) Strings::after($filename, "."); |
221
|
1 |
|
if(!in_array($lang, $languages, true)) { |
222
|
1 |
|
$languages[] = $lang; |
223
|
|
|
} |
224
|
|
|
} |
225
|
1 |
|
return $languages; |
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
?> |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.