Overview

Namespaces

  • None
  • PHP

Classes

  • i81n
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: 
  3: /* 
  4:  * Copyright (C) 2014 Everton
  5:  *
  6:  * This program is free software: you can redistribute it and/or modify
  7:  * it under the terms of the GNU General Public License as published by
  8:  * the Free Software Foundation, either version 3 of the License, or
  9:  * (at your option) any later version.
 10:  *
 11:  * This program is distributed in the hope that it will be useful,
 12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14:  * GNU General Public License for more details.
 15:  *
 16:  * You should have received a copy of the GNU General Public License
 17:  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 18:  */
 19: 
 20: /**
 21:  * Library for internationalizing applications with PHP
 22:  * 
 23:  * 
 24:  */
 25: class i81n{
 26:     /**
 27:      * The language to be used
 28:      * @var string
 29:      */
 30:     protected $lang = NULL;
 31:     
 32:     /**
 33:      * The directory containing the translation INI files. The default is ./locale
 34:      * @var string
 35:      */
 36:     protected $localeDir = './locale';
 37:     
 38:     /**
 39:      * Holds the translation table.
 40:      * 
 41:      * @var array
 42:      */
 43:     protected $translateTable = array();
 44:     
 45:     /**
 46:      * Specifies the domain to be used. Each INI file is a domain. For all domains, use * (default).
 47:      * @var string
 48:      */
 49:     protected $domain = '*';
 50: 
 51:     /**
 52:      * Class constructor.
 53:      * 
 54:      * @param string $lang A string representing the language to be used.
 55:      * 
 56:      * @throws Exception
 57:      */
 58:     public function __construct($lang = NULL, $domain = '*') {
 59:         if($lang == NULL){
 60:             throw new Exception('Undefined language!');
 61:         }
 62:         $this->setLang($lang);
 63:         
 64:         $this->setDomain($domain);
 65:         
 66:         $this->parseLang();
 67:     }
 68: 
 69:     /**
 70:      * Sets the domain to be used for translation.
 71:      * 
 72:      * Each domain corresponds to an INI file with the translations. It is useful to create translations for separate modules.
 73:      * 
 74:      * @param string $domain The domain to be used for translation.
 75:      * @return boolean
 76:      * @throws Exception
 77:      */
 78:     public function setDomain($domain){
 79:         switch ($domain){
 80:             case '*'://all domains
 81:                 $this->domain = $domain;
 82:                 break;
 83:             default:
 84:                 if(!file_exists($this->getLocaleDir().'/'.$this->getLang().'/'.$domain.'.ini')){
 85:                     throw new Exception("The domain $domain was not found.");
 86:                 }else{
 87:                     $this->domain = $domain;
 88:                 }
 89:                 break;
 90:         }
 91:         return true;
 92:     }
 93:     
 94:     /**
 95:      * Returns the currently configured domain.
 96:      * @return string
 97:      */
 98:     public function getDomain(){
 99:         return $this->domain;
100:     }
101: 
102:     /**
103:      * Returns the language set in the LANG environment variable
104:      * 
105:      * @return string
106:      */
107:     public function getLang(){
108:         return $this->lang;
109:     }
110:     
111:     /**
112:      * Set the LANG environment variable.
113:      * 
114:      * @param string $lang A language code, such as en_US, en_GB, ...
115:      * @return string Returns the contents of LANG after the change.
116:      */
117:     public function setLang($lang){
118:         $this->lang = $lang;
119:         return $this->getLang();
120:     }
121:     
122:     /**
123:      * Returns the path for translation files.
124:      * @return string
125:      */
126:     public function getLocaleDir(){
127:         return realpath($this->localeDir);
128:     }
129:     
130:     /**
131:      * Sets the path for translation files.
132:      * 
133:      * @param string $dirname The directory where the files are translation.
134:      * @return string Returns the configured directory.
135:      * @throws Exception
136:      */
137:     public function setLocaleDir($dirname){
138:         //forehead is directory and if there
139:         if(!is_dir($dirname)){
140:             throw new Exception("$dirname is not a directory.");
141:         }elseif(!file_exists($dirname)){
142:             throw new Exception("The $dirname directory does not exist.");
143:         }
144:         
145:         //defines the location of the translation files
146:         $this->localeDir = realpath($dirname);//pega o caminho absoluto
147:         
148:         return $this->getLocaleDir();
149:     }
150:     
151:     /**
152:      * Mounts from the domain specified translation table.
153:      * 
154:      * @return bool
155:      * @throws Exception
156:      */
157:     protected function parseLang(){
158:         if($this->getDomain() === '*'){
159:             try{
160:                 $dir = glob($this->getLocaleDir().'/'.$this->getLang()."/*.ini");
161:             } catch (Exception $ex) {
162:                 throw $ex;
163:             }
164:         }else{
165:             $dir = array($this->getLocaleDir().'/'.$this->getLang().'/'.$this->getDomain().'.ini');
166:         }
167:         $table = array();
168:         foreach($dir as $path){
169:             if(is_file($path)){
170:                 try{
171:                     $ini = parse_ini_file($path, true);
172:                     $table = array_merge($table, $ini);
173:                 } catch (Exception $ex) {
174:                     throw $ex;
175:                 }
176:             }
177:         }
178:         $this->translateTable = $table;
179:               
180:         return true;
181:     }
182:     
183:     /**
184:      * Creates a hash for a message.
185:      * 
186:      * Used to reference the messages in INI file translation.
187:      * 
188:      * 
189:      * @param string $msg The message to compute the hash
190:      * @return string Returns the hash for the message
191:      */
192:     protected static function hash($msg){
193:         return sha1($msg);
194:     }
195:     
196:     /**
197:      * Search through a translation of the original hash mesnagem.
198:      * 
199:      * @param string $hash The hash of the message to be sought in the translation table.
200:      * @return string Returns the translated message or an empty string.
201:      */
202:     protected function searchInTranslateTable($hash){
203:         
204:         if(count($this->translateTable) == 0){
205:             return '';
206:         }else{
207:             if(array_key_exists($hash, $this->translateTable)){
208:                 return $this->translateTable[$hash]['tmsg'];
209:             }else{
210:                 return '';
211:             }
212:         }
213:     }
214: 
215:     /**
216:      * Performs the translation of messages.
217:      * 
218:      * @param string $string The message to be translated.
219:      * @return string The translated message
220:      */
221:     public function translate($msg){
222:         if(count($this->translateTable) == 0){
223:             return $msg;
224:         }else{
225:             $hash = self::hash($msg);
226:             $translated = $this->searchInTranslateTable($hash);
227:             if(strlen($translated) > 0){
228:                 return $translated;
229:             }else{
230:                 return $msg;
231:             }
232:         }
233:     }
234:     
235:     //here start methods for automatic creation of INI files
236:     
237:     /**
238:      * Identifies a file source for messages used with i81n library (translate method) and creates an INI file translation.
239:      * 
240:      * @param string $file Source file for the parser
241:      * @param string $pattern The search pattern of the messages to translate
242:      * @return array Returns an array with the lines of the INI file translation
243:      * @throws Exception
244:      */
245:     protected static function parseFileSource($file, $pattern = '->translate'){
246:         //printf("<p>Initiating processing %s</p>", $file);
247:         //tests the source file
248:         if(!file_exists($file)){
249:             throw new Exception("File $file not found.");
250:         }
251:         
252:         //reads the contents of the source file
253:         //printf("<p>Loading the contents of %s</p>", $file);
254:         try {
255:             $source = file($file);
256:         } catch (Exception $ex) {
257:             throw $ex;
258:         }
259:         
260:         $msg = array();
261:         foreach($source as $line){
262:             $explode = explode($pattern, $line);
263:             if(count($explode) > 0){
264:                 foreach ($explode as $row){
265:                     preg_match_all("/\(\'(.*)\'\)/", $row, $matches);
266:                     if(count($matches) > 0){
267:                         foreach ($matches[1] as $m){
268:                             $msg[] = $m;
269:                         }
270:                     }
271:                 }
272:             }
273:         }
274:         
275:         $inistr = array();
276:         foreach ($msg as $str){
277:             $hash = self::hash($str);
278:             $inistr[] = "[$hash]".PHP_EOL;
279:             $inistr[] = "omsg = '$str'".PHP_EOL;
280:             $inistr[] = "tmsg = '$str'".PHP_EOL;
281:         }
282:         
283:         return $inistr;
284:     }
285:     
286:     public static function parseDir($configfile){
287:         printf("Starting the scan".PHP_EOL);
288:         //Load the settings file
289:         try {
290:             $conf = parse_ini_file($configfile, true);
291:         } catch (Exception $ex) {
292:             throw $ex;
293:         }
294:         
295:         $input = realpath($conf['general']['input']);
296:         $output = realpath($conf['general']['output']);
297:         $domain = $conf['general']['domain'];
298:         $pattern = $conf['general']['pattern'];
299:         $recursive = $conf['general']['recursive'];
300:         $exclude = $conf['exclude'];
301:         printf("%s loaded".PHP_EOL, $configfile);
302:         
303:         if(!file_exists($input)){
304:             throw new Exception("Source directory does not exist!");
305:         }
306:         
307:         if(!file_exists($output)){
308:             throw new Exception("Destination directory does not exist!");
309:         }
310:         
311:         $sources = self::getFileSources($input, $recursive, $exclude);
312:         printf("Sources found".PHP_EOL);
313:         echo '<pre>';
314:         print_r($sources);
315:         echo '</pre>';
316:         
317:         foreach($sources as $filename){
318:             printf("Processing file %s with pattern %s ".PHP_EOL, $filename, $pattern);
319:             $parsed = self::parseFileSource($filename, $pattern);
320:             
321:             switch ($domain) {
322:                 case 'FILE_DOMAIN':
323:                     $d = basename($filename, '.php');
324:                     $mode = 'w';
325:                     break;
326: 
327:                 case 'UNIQUE_DOMAIN':
328:                     $d = 'main';
329:                     $mode = 'a';
330:                     break;
331: 
332:                 case 'DIR_DOMAIN':
333:                     $d = str_replace(dirname($input), '', dirname($filename));
334:                     $d = str_replace('/', '.', $d);
335:                     $d = str_replace('\\', '.', $d);
336:                     if($d[0] == '.');
337:                     $d = substr($d, 1);
338:                     $mode = 'w';
339:                     break;
340: 
341:                 default:
342:                     throw new Exception("The choice for a domain name is not valid!");
343:                     break;
344:             }
345:             printf("Selected domain %s based on option %s".PHP_EOL, $d, $domain);
346:             $o = "$output/$d.ini";
347:             try{
348:                 $handle = fopen($o, $mode);
349:                 foreach ($parsed as $str){
350:                     fwrite($handle, "$str".PHP_EOL);
351:                 }
352:                 fclose($handle);
353:             } catch (Exception $ex) {
354:                 throw $ex;
355:             }
356:             printf("Save translation in %s".PHP_EOL, $o);
357:         }
358:         
359:         printf("Process completed".PHP_EOL);
360:         
361:         return true;
362:         
363:         
364:     }
365:     
366:     protected static function getFileSources($sourcedir, $recursive, $exclude){
367:         printf("Starting search for files in %s".PHP_EOL, $sourcedir);
368:         reset($exclude);
369:         $sources = array();
370:         
371:         $glob = glob("$sourcedir/*");
372:         
373:         foreach($glob as $f){
374:             printf("Analyzing the file %s".PHP_EOL, $f);
375:             $ex = false;
376:             foreach($exclude as $pattern){
377:                 if(preg_match($pattern, $f) === 1){
378:                     $ex = true;
379:                     printf("Deleted file %s by pattern %s".PHP_EOL, $f, $pattern);
380:                 }
381:             }
382:             if($ex == false){
383:                 if(is_dir($f)){
384:                     if($recursive == 1){
385:                         printf("%s is a directory. Recursion starting".PHP_EOL, $f);
386:                         $child = self::getFileSources($f, $recursive, $exclude);
387:                         $sources = array_merge($sources, $child);
388:                         printf("Recursion of %s terminated".PHP_EOL, $f);
389:                     }else{
390:                         printf("%s is a directory. Recursion not initialised".PHP_EOL, $f);
391:                     }
392:                 }else{
393:                     $sources[] = $f;
394:                     printf("Adding %s the list".PHP_EOL, $f);
395:                 }
396:             }
397:         }
398:         
399:         return $sources;
400:     }
401: }
API documentation generated by ApiGen 2.8.0