1 <?php
2 3 4 5 6 7
8
9 namespace Hawk;
10
11 12 13 14 15
16 class Lang{
17
18 const DEFAULT_LANGUAGE = 'en';
19 const ORIGIN_CACHE_FILE = 'lang-file-paths.php';
20 const CACHE_DIR = 'lang/';
21 const TRANSLATIONS_DIR = 'admin/translations/';
22
23 24 25 26 27
28 private static $keys = array(),
29
30 31 32 33 34
35 $usedLanguage = '',
36
37 38 39 40 41
42 $originCache = array();
43
44 45 46 47 48
49 private $plugin,
50
51 52 53 54 55
56 $lang,
57
58 59 60 61 62
63 $originFile,
64
65 66 67 68 69
70 $translatedFile,
71
72 73 74 75 76
77 $cacheFile;
78
79
80 81 82 83 84 85
86 private function __construct($plugin, $lang){
87 $this->plugin = $plugin;
88 $this->lang = $lang;
89
90 $this->originFile = $this->getOriginFile();
91 $this->translatedFile = $this->getTranslatedFile();
92 $this->cacheFile = $this->getCacheFile();
93 }
94
95
96 97 98 99 100
101 private function getOriginFile(){
102 if(is_file(App::cache()->getCacheFilePath(self::ORIGIN_CACHE_FILE)) && empty(self::$originCache)) {
103 self::$originCache = App::cache()->includeCache(self::ORIGIN_CACHE_FILE);
104 }
105
106 if(isset(self::$originCache["$this->plugin.$this->lang"])) {
107
108 return self::$originCache["$this->plugin.$this->lang"];
109 }
110
111
112 foreach(array(MAIN_PLUGINS_DIR, PLUGINS_DIR) as $dir){
113 $files = App::fs()->find($dir, $this->plugin . '.' . $this->lang . '.lang', FileSystem::FIND_FILE_ONLY);
114 if(!empty($files)) {
115 $file = $files[0];
116
117
118 self::$originCache["$this->plugin.$this->lang"] = $file;
119
120 return $file;
121 }
122 }
123 return null;
124 }
125
126
127 128 129 130 131
132 private function getTranslatedFile(){
133 return USERFILES_PLUGINS_DIR . self::TRANSLATIONS_DIR . $this->plugin . '.' . $this->lang . '.lang';
134 }
135
136 137 138 139 140
141 private function getCacheFile(){
142 return self::CACHE_DIR . $this->plugin . '.' . $this->lang . '.php';
143 }
144
145
146 147 148 149 150 151 152
153 private function parse($file){
154 return is_file($file) ? parse_ini_string(file_get_contents($file)) : array();
155 }
156
157
158 159 160
161 private function build(){
162 $build = false;
163
164 if(!is_file(App::cache()->getCacheFilePath($this->cacheFile))) {
165 $build = true;
166 }
167 elseif(is_file($this->originFile) && !App::cache()->isCached($this->originFile, $this->cacheFile)) {
168
169 $build = true;
170 }
171 elseif(is_file($this->translatedFile) && !App::cache()->isCached($this->translatedFile, $this->cacheFile)) {
172
173 $build = true;
174 }
175
176
177 if($build) {
178
179 $data = array_merge($this->parse($this->originFile), $this->parse($this->translatedFile));
180
181 App::cache()->save($this->cacheFile, '<?php return ' . var_export($data, true) . ';');
182 }
183 }
184
185
186
187 188 189 190 191 192 193
194 private static function load($plugin, $language = LANGUAGE, $force = false){
195 if(!isset(self::$keys[$plugin][$language]) || $force || $language !== self::$usedLanguage) {
196 App::logger()->debug('Reload keys for plugin ' . $plugin . ' and for language ' . $language);
197 self::$keys[$plugin][$language] = array();
198
199 $instance = new self($plugin, self::DEFAULT_LANGUAGE);
200 $instance->build();
201 self::$keys[$plugin][$language] = App::cache()->includeCache($instance->cacheFile);
202
203 if($language !== self::DEFAULT_LANGUAGE) {
204 $instance = new self($plugin, $language);
205 $instance->build();
206 $translations = App::cache()->includeCache($instance->cacheFile);
207
208 if(!is_array($translations)) {
209 $translations = array();
210 }
211
212 self::$keys[$plugin][$language] = array_merge(self::$keys[$plugin][$language], $translations);
213 }
214
215 self::$usedLanguage = $language;
216 }
217 }
218
219
220 221 222 223 224 225 226
227 public static function keys($plugin, $language = LANGUAGE, $reload = false){
228 self::load($plugin, $language, $reload);
229
230 return self::$keys[$plugin][$language];
231 }
232
233
234 235 236
237 public static function saveOriginCache(){
238 file_put_contents(CACHE_DIR . self::ORIGIN_CACHE_FILE, '<?php return ' . var_export(self::$originCache, true) . ';');
239 }
240
241
242
243
244 245 246 247 248 249 250
251 public static function exists($langKey){
252 list($plugin, $key) = explode('.', $langKey);
253
254
255 self::load($plugin);
256
257 return isset(self::$keys[$plugin][self::$usedLanguage][$key]);
258 }
259
260
261
262
263 264 265 266 267 268 269 270 271 272
273 public static function get($langKey, $param = array(), $number = 0, $language = LANGUAGE){
274 $tmp = explode('.', $langKey);
275 if(count($tmp) != 2) {
276 return $langKey;
277 }
278
279 list($plugin, $key) = explode('.', $langKey);
280
281
282 self::load($plugin, $language);
283
284
285 $labels = isset(self::$keys[$plugin][$language][$key]) ? self::$keys[$plugin][$language][$key] : null;
286
287 if($labels !== null) {
288 if(is_array($labels)) {
289
290 if((int) $number > 1) {
291
292 $label = isset($labels[$number]) ? $labels[$number] : (isset($labels['p']) ? $labels['p'] : $langKey);
293 }
294 else{
295
296 $label = isset($labels[$number]) ? $labels[$number] : (isset($labels['s']) ? $labels['s'] : $langKey);
297 }
298 }
299 else{
300
301 $label = $labels;
302 }
303
304 if(!empty($param)) {
305
306 return str_replace(
307 array_map(
308 function ($key) {
309 return '{'.$key.'}';
310 }, array_keys($param)
311 ), $param, $label
312 );
313 }
314 else
315 return $label;
316 }
317 else{
318 return $langKey;
319 }
320 }
321
322
323
324 325 326 327 328 329 330 331
332 public static function addKeysToJavascript(...$keys){
333 $script = "";
334 foreach($keys as $key){
335 list($plugin, $langKey) = explode(".", $key);
336 $script .= "Lang.set('$key', '" . addcslashes(self::get($key), "'") . "');";
337 }
338
339 App::router()->getCurrentController()->addJavaScriptInline($script);
340 }
341
342
343
344 345 346 347 348 349
350 public static function getUserTranslations($plugin, $language) {
351 $lang = new self($plugin, $language);
352 $file = $lang->getTranslatedFile();
353 return is_file($file) ? parse_ini_string(file_get_contents($file)) : array();
354 }
355
356 357 358 359 360 361 362
363 public static function saveUserTranslations($plugin, $language, $data) {
364 $lang = new self($plugin, $language);
365 $file = $lang->getTranslatedFile();
366
367 $lines = array();
368 foreach($data as $key => $value){
369 if(! is_array($value)) {
370 $lines[] = $key . ' = "' . addcslashes($value, '"') . '"';
371 }
372 else{
373 foreach($value as $multiplier => $val){
374 $lines[] = $key . '[' . $multiplier . '] = "' . addcslashes($val, '"') . '"';
375 }
376 }
377 }
378
379 $content = implode(PHP_EOL, $lines);
380 $dir = dirname($file);
381 if(!is_dir($dir)) {
382 mkdir($dir, 0755, true);
383 }
384
385 file_put_contents($file, $content);
386 touch($file, time() + 3);
387 }
388 }
389
390
391 Event::on('process-end', function (Event $event) {
392 Lang::saveOriginCache();
393 });