PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/joomla/libraries/joomla/language/language.php

https://github.com/reechalee/joomla1.6
PHP | 1198 lines | 712 code | 108 blank | 378 comment | 70 complexity | 49a5ee354a22c1505528fc11997f220a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, JSON
  1. <?php
  2. /**
  3. * @version $Id: language.php 20196 2011-01-09 02:40:25Z ian $
  4. * @package Joomla.Framework
  5. * @subpackage Language
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. // No direct access.
  10. defined('JPATH_BASE') or die;
  11. /**
  12. * Allows for quoting in language .ini files.
  13. */
  14. define('_QQ_', '"');
  15. // import some libariries
  16. jimport('joomla.filesystem.stream');
  17. /**
  18. * Languages/translation handler class
  19. *
  20. * @package Joomla.Framework
  21. * @subpackage Language
  22. * @since 1.5
  23. */
  24. class JLanguage extends JObject
  25. {
  26. protected static $languages = array();
  27. /**
  28. * Debug language, If true, highlights if string isn't found
  29. *
  30. * @var boolean
  31. * @since 1.5
  32. */
  33. protected $debug = false;
  34. /**
  35. * The default language
  36. *
  37. * The default language is used when a language file in the requested language does not exist.
  38. *
  39. * @var string
  40. * @since 1.5
  41. */
  42. protected $default = 'en-GB';
  43. /**
  44. * An array of orphaned text
  45. *
  46. * @var array
  47. * @since 1.5
  48. */
  49. protected $orphans = array();
  50. /**
  51. * Array holding the language metadata
  52. *
  53. * @var array
  54. * @since 1.5
  55. */
  56. protected $metadata = null;
  57. /**
  58. * Array|boolean holding the language locale
  59. *
  60. * @var array|boolean
  61. * @since 1.5
  62. */
  63. protected $locale = null;
  64. /**
  65. * The language to load
  66. *
  67. * @var string
  68. * @since 1.5
  69. */
  70. protected $lang = null;
  71. /**
  72. * List of language files that have been loaded
  73. *
  74. * @var array of arrays
  75. * @since 1.5
  76. */
  77. protected $paths = array();
  78. /**
  79. * List of language files that are in error state
  80. *
  81. * @var array of string
  82. * @since 1.6
  83. */
  84. protected $errorfiles = array();
  85. /**
  86. * Translations
  87. *
  88. * @var array
  89. * @since 1.5
  90. */
  91. protected $strings = null;
  92. /**
  93. * An array of used text, used during debugging
  94. *
  95. * @var array
  96. * @since 1.5
  97. */
  98. protected $used = array();
  99. /**
  100. * Counter for number of loads
  101. *
  102. * @var integer
  103. * @since 1.6
  104. */
  105. protected $counter = 0;
  106. /**
  107. * An array used to store overrides
  108. *
  109. * @var array
  110. * @since 1.6
  111. */
  112. protected $override = array();
  113. /**
  114. * Name of the transliterator function for this language
  115. *
  116. * @var string
  117. * @since 1.6
  118. */
  119. protected $transliterator = null;
  120. /**
  121. * Name of the pluralSufficesCallback function for this language
  122. *
  123. * @var string
  124. * @since 1.6
  125. */
  126. protected $pluralSufficesCallback = null;
  127. /**
  128. * Name of the ignoredSearchWordsCallback function for this language
  129. *
  130. * @var string
  131. * @since 1.6
  132. */
  133. protected $ignoredSearchWordsCallback = null;
  134. /**
  135. * Name of the lowerLimitSearchWordCallback function for this language
  136. *
  137. * @var string
  138. * @since 1.6
  139. */
  140. protected $lowerLimitSearchWordCallback = null;
  141. /**
  142. * Name of the uppperLimitSearchWordCallback function for this language
  143. *
  144. * @var string
  145. * @since 1.6
  146. */
  147. protected $upperLimitSearchWordCallback = null;
  148. /**
  149. * Name of the searchDisplayedCharactersNumberCallback function for this language
  150. *
  151. * @var string
  152. * @since 1.6
  153. */
  154. protected $searchDisplayedCharactersNumberCallback = null;
  155. /**
  156. * Constructor activating the default information of the language
  157. */
  158. public function __construct($lang = null, $debug = false)
  159. {
  160. $this->strings = array ();
  161. if ($lang == null) {
  162. $lang = $this->default;
  163. }
  164. $this->setLanguage($lang);
  165. $this->setDebug($debug);
  166. $filename = JPATH_BASE . "/language/overrides/$lang.override.ini";
  167. if (file_exists($filename) && $contents = $this->parse($filename)) {
  168. if (is_array($contents)) {
  169. $this->override = $contents;
  170. }
  171. unset($contents);
  172. }
  173. // Look for a language specific localise class
  174. $class = str_replace('-', '_', $lang . 'Localise');
  175. if (!class_exists($class)) {
  176. // Class does not exist. Try to find it in the Site Language Folder
  177. $localise = JPATH_SITE . "/language/$lang/$lang.localise.php";
  178. if (file_exists($localise)) {
  179. require_once $localise;
  180. }
  181. }
  182. if (!class_exists($class)) {
  183. // Class does not exist. Try to find it in the Administrator Language Folder
  184. $localise = JPATH_ADMINISTRATOR . "/language/$lang/$lang.localise.php";
  185. if (file_exists($localise)) {
  186. require_once $localise;
  187. }
  188. }
  189. if (class_exists($class)) {
  190. /* Class exists. Try to find
  191. * -a transliterate method,
  192. * -a getPluralSuffixes method,
  193. * -a getIgnoredSearchWords method
  194. * -a getLowerLimitSearchWord method
  195. * -a getUpperLimitSearchWord method
  196. * -a getSearchDisplayCharactersNumber method
  197. */
  198. if (method_exists($class, 'transliterate')) {
  199. $this->transliterator = array($class, 'transliterate');
  200. }
  201. if (method_exists($class, 'getPluralSuffixes')) {
  202. $this->pluralSufficesCallback = array($class, 'getPluralSuffixes');
  203. }
  204. if (method_exists($class, 'getIgnoredSearchWords')) {
  205. $this->ignoredSearchWordsCallback = array($class, 'getIgnoredSearchWords');
  206. }
  207. if (method_exists($class, 'getLowerLimitSearchWord')) {
  208. $this->lowerLimitSearchWordCallback = array($class, 'getLowerLimitSearchWord');
  209. }
  210. if (method_exists($class, 'getUpperLimitSearchWord')) {
  211. $this->upperLimitSearchWordCallback = array($class, 'getUpperLimitSearchWord');
  212. }
  213. if (method_exists($class, 'getSearchDisplayedCharactersNumber')) {
  214. $this->searchDisplayedCharactersNumberCallback = array($class, 'getSearchDisplayedCharactersNumber');
  215. }
  216. }
  217. $this->load();
  218. }
  219. /**
  220. * Returns a language object
  221. *
  222. * @param string $lang The language to use.
  223. * @param boolean $debug The debug mode
  224. * @return JLanguage The Language object.
  225. * @since 1.5
  226. */
  227. public static function getInstance($lang, $debug=false)
  228. {
  229. if (!isset(self::$languages[$lang.$debug])) {
  230. self::$languages[$lang.$debug] = new JLanguage($lang, $debug);
  231. }
  232. return self::$languages[$lang.$debug];
  233. }
  234. /**
  235. * Translate function, mimics the php gettext (alias _) function
  236. *
  237. * @param string $string The string to translate
  238. * @param boolean $jsSafe Make the result javascript safe
  239. * @param boolean $interpreteBackslashes Interprete \t and \n
  240. * @return string The translation of the string
  241. * @note The function check if $jsSafe is true then if $interpreteBackslashes is true
  242. * @since 1.5
  243. */
  244. public function _($string, $jsSafe = false, $interpreteBackSlashes = true)
  245. {
  246. $key = strtoupper($string);
  247. if (isset ($this->strings[$key])) {
  248. $string = $this->debug ? '**'.$this->strings[$key].'**' : $this->strings[$key];
  249. // Store debug information
  250. if ($this->debug) {
  251. $caller = $this->getCallerInfo();
  252. if (! array_key_exists($key, $this->used)) {
  253. $this->used[$key] = array();
  254. }
  255. $this->used[$key][] = $caller;
  256. }
  257. } else {
  258. if ($this->debug) {
  259. $caller = $this->getCallerInfo();
  260. $caller['string'] = $string;
  261. if (! array_key_exists($key, $this->orphans)) {
  262. $this->orphans[$key] = array();
  263. }
  264. $this->orphans[$key][] = $caller;
  265. $string = '??'.$string.'??';
  266. }
  267. }
  268. if ($jsSafe) {
  269. // javascript filter
  270. $string = addslashes($string);
  271. }
  272. elseif ($interpreteBackSlashes) {
  273. // interprete \n and \t characters
  274. $string = str_replace(array('\\\\','\t','\n'),array("\\", "\t","\n"),$string);
  275. }
  276. return $string;
  277. }
  278. /**
  279. * Transliterate function
  280. *
  281. * This method processes a string and replaces all accented UTF-8 characters by unaccented
  282. * ASCII-7 "equivalents"
  283. *
  284. * @param string $string The string to transliterate
  285. * @return string The transliteration of the string
  286. * @since 1.5
  287. */
  288. public function transliterate($string)
  289. {
  290. include_once dirname(__FILE__) . '/latin_transliterate.php';
  291. if ($this->transliterator !== null) {
  292. return call_user_func($this->transliterator, $string);
  293. }
  294. $string = JLanguageTransliterate::utf8_latin_to_ascii($string);
  295. $string = JString::strtolower($string);
  296. return $string;
  297. }
  298. /**
  299. * Getter for transliteration function
  300. *
  301. * @return string|function Function name or the actual function for PHP 5.3
  302. * @since 1.6
  303. */
  304. public function getTransliterator()
  305. {
  306. return $this->transliterator;
  307. }
  308. /**
  309. * Set the transliteration function
  310. *
  311. * @return string|function Function name or the actual function for PHP 5.3
  312. * @since 1.6
  313. */
  314. public function setTransliterator($function)
  315. {
  316. $previous = $this->transliterator;
  317. $this->transliterator = $function;
  318. return $previous;
  319. }
  320. /**
  321. * pluralSuffices function
  322. *
  323. * This method return an array of suffices for plural rules
  324. *
  325. * @param int $count The count number
  326. * @return array The array of suffices
  327. * @since 1.6
  328. */
  329. public function getPluralSuffixes($count) {
  330. if ($this->pluralSufficesCallback !== null) {
  331. return call_user_func($this->pluralSufficesCallback, $count);
  332. }
  333. else {
  334. return array((string)$count);
  335. }
  336. }
  337. /**
  338. * Getter for pluralSufficesCallback function
  339. *
  340. * @return string|function Function name or the actual function for PHP 5.3
  341. * @since 1.6
  342. */
  343. public function getPluralSuffixesCallback() {
  344. return $this->pluralSufficesCallback;
  345. }
  346. /**
  347. * Set the pluralSuffices function
  348. *
  349. * @return string|function Function name or the actual function for PHP 5.3
  350. * @since 1.6
  351. */
  352. public function setPluralSufficesCallback($function) {
  353. $previous = $this->pluralSufficesCallback;
  354. $this->pluralSufficesCallback = $function;
  355. return $previous;
  356. }
  357. /**
  358. * getIgnoredSearchWords function
  359. *
  360. * This method returns an array of ignored search words
  361. *
  362. * @return array The array of ignored search words
  363. * @since 1.6
  364. */
  365. public function getIgnoredSearchWords() {
  366. if ($this->ignoredSearchWordsCallback !== null) {
  367. return call_user_func($this->ignoredSearchWordsCallback);
  368. }
  369. else {
  370. return array();
  371. }
  372. }
  373. /**
  374. * Getter for ignoredSearchWordsCallback function
  375. *
  376. * @return string|function Function name or the actual function for PHP 5.3
  377. * @since 1.6
  378. */
  379. public function getIgnoredSearchWordsCallback() {
  380. return $this->ignoredSearchWordsCallback;
  381. }
  382. /**
  383. * Setter for the ignoredSearchWordsCallback function
  384. *
  385. * @return string|function Function name or the actual function for PHP 5.3
  386. * @since 1.6
  387. */
  388. public function setIgnoredSearchWordsCallback($function) {
  389. $previous = $this->ignoredSearchWordsCallback;
  390. $this->ignoredSearchWordsCallback = $function;
  391. return $previous;
  392. }
  393. /**
  394. * getLowerLimitSearchWord function
  395. *
  396. * This method returns a lower limit integer for length of search words
  397. *
  398. * @return integer The lower limit integer for length of search words (3 if no value was set for a specific language)
  399. * @since 1.6
  400. */
  401. public function getLowerLimitSearchWord() {
  402. if ($this->lowerLimitSearchWordCallback !== null) {
  403. return call_user_func($this->lowerLimitSearchWordCallback);
  404. }
  405. else {
  406. return 3;
  407. }
  408. }
  409. /**
  410. * Getter for lowerLimitSearchWordCallback function
  411. *
  412. * @return string|function Function name or the actual function for PHP 5.3
  413. * @since 1.6
  414. */
  415. public function getLowerLimitSearchWordCallback() {
  416. return $this->lowerLimitSearchWordCallback;
  417. }
  418. /**
  419. * Setter for the lowerLimitSearchWordCallback function
  420. *
  421. * @return string|function Function name or the actual function for PHP 5.3
  422. * @since 1.6
  423. */
  424. public function setLowerLimitSearchWordCallback($function) {
  425. $previous = $this->lowerLimitSearchWordCallback;
  426. $this->lowerLimitSearchWordCallback = $function;
  427. return $previous;
  428. }
  429. /**
  430. * getUpperLimitSearchWord function
  431. *
  432. * This method returns an upper limit integer for length of search words
  433. *
  434. * @return integer The upper limit integer for length of search words (20 if no value was set for a specific language)
  435. * @since 1.6
  436. */
  437. public function getUpperLimitSearchWord() {
  438. if ($this->upperLimitSearchWordCallback !== null) {
  439. return call_user_func($this->upperLimitSearchWordCallback);
  440. }
  441. else {
  442. return 20;
  443. }
  444. }
  445. /**
  446. * Getter for upperLimitSearchWordCallback function
  447. *
  448. * @return string|function Function name or the actual function for PHP 5.3
  449. * @since 1.6
  450. */
  451. public function getUpperLimitSearchWordCallback() {
  452. return $this->upperLimitSearchWordCallback;
  453. }
  454. /**
  455. * Setter for the upperLimitSearchWordCallback function
  456. *
  457. * @return string|function Function name or the actual function for PHP 5.3
  458. * @since 1.6
  459. */
  460. public function setUpperLimitSearchWordCallback($function) {
  461. $previous = $this->upperLimitSearchWordCallback;
  462. $this->upperLimitSearchWordCallback = $function;
  463. return $previous;
  464. }
  465. /**
  466. * getSearchDisplayedCharactersNumber function
  467. *
  468. * This method returns the number of characters displayed during research
  469. *
  470. * @return integer The number of characters displayed during research (200 if no value was set for a specific language)
  471. * @since 1.6
  472. */
  473. public function getSearchDisplayedCharactersNumber() {
  474. if ($this->searchDisplayedCharactersNumberCallback !== null) {
  475. return call_user_func($this->searchDisplayedCharactersNumberCallback);
  476. }
  477. else {
  478. return 200;
  479. }
  480. }
  481. /**
  482. * Getter for searchDisplayedCharactersNumberCallback function
  483. *
  484. * @return string|function Function name or the actual function for PHP 5.3
  485. * @since 1.6
  486. */
  487. public function getSearchDisplayedCharactersNumberCallback() {
  488. return $this->searchDisplayedCharactersNumberCallback;
  489. }
  490. /**
  491. * Setter for the searchDisplayedCharactersNumberCallback function
  492. *
  493. * @return string|function Function name or the actual function for PHP 5.3
  494. * @since 1.6
  495. */
  496. public function setSearchDisplayedCharactersNumberCallback($function) {
  497. $previous = $this->searchDisplayedCharactersNumberCallback;
  498. $this->searchDisplayedCharactersNumberCallback = $function;
  499. return $previous;
  500. }
  501. /**
  502. * Check if a language exists
  503. *
  504. * This is a simple, quick check for the directory that should contain language files for the given user.
  505. *
  506. * @param string $lang Language to check
  507. * @param string $basePath Optional path to check
  508. * @return boolean True if the language exists
  509. * @since 1.5
  510. */
  511. public static function exists($lang, $basePath = JPATH_BASE)
  512. {
  513. static $paths = array();
  514. // Return false if no language was specified
  515. if (! $lang) {
  516. return false;
  517. }
  518. $path = "$basePath/language/$lang";
  519. // Return previous check results if it exists
  520. if (isset($paths[$path]))
  521. {
  522. return $paths[$path];
  523. }
  524. // Check if the language exists
  525. jimport('joomla.filesystem.folder');
  526. $paths[$path] = JFolder::exists($path);
  527. return $paths[$path];
  528. }
  529. /**
  530. * Loads a single language file and appends the results to the existing strings
  531. *
  532. * @param string $extension The extension for which a language file should be loaded
  533. * @param string $basePath The basepath to use
  534. * @param string $lang The language to load, default null for the current language
  535. * @param boolean $reload Flag that will force a language to be reloaded if set to true
  536. * @param boolean $default Flag that force the default language to be loaded if the current does not exist
  537. * @return boolean True, if the file has successfully loaded.
  538. * @since 1.5
  539. */
  540. public function load($extension = 'joomla', $basePath = JPATH_BASE, $lang = null, $reload = false, $default = true)
  541. {
  542. if (! $lang) {
  543. $lang = $this->lang;
  544. }
  545. $path = self::getLanguagePath($basePath, $lang);
  546. $internal = $extension == 'joomla' || $extension == '';
  547. $filename = $internal ? $lang : $lang . '.' . $extension;
  548. $filename = "$path/$filename.ini";
  549. $result = false;
  550. if (isset($this->paths[$extension][$filename]) && ! $reload) {
  551. // Strings for this file have already been loaded
  552. $result = true;
  553. } else {
  554. // Load the language file
  555. $result = $this->loadLanguage($filename, $extension);
  556. // Check if there was a problem with loading the file
  557. if ($result === false && $default) {
  558. // No strings, so either file doesn't exist or the file is invalid
  559. $oldFilename = $filename;
  560. // Check the standard file name
  561. $path = self::getLanguagePath($basePath, $this->default);
  562. $filename = $internal ? $this->default : $this->default . '.' . $extension;
  563. $filename = "$path/$filename.ini";
  564. // If the one we tried is different than the new name, try again
  565. if ($oldFilename != $filename) {
  566. $result = $this->loadLanguage($filename, $extension, false);
  567. }
  568. }
  569. }
  570. return $result;
  571. }
  572. /**
  573. * Loads a language file
  574. *
  575. * This method will not note the successful loading of a file - use load() instead
  576. *
  577. * @param string The name of the file
  578. * @param string The name of the extension
  579. * @return boolean True if new strings have been added to the language
  580. * @see JLanguage::load()
  581. * @since 1.5
  582. */
  583. protected function loadLanguage($filename, $extension = 'unknown', $overwrite = true)
  584. {
  585. $this->counter++;
  586. $result = false;
  587. $strings = false;
  588. if (file_exists($filename)) {
  589. $strings = $this->parse($filename);
  590. }
  591. if ($strings) {
  592. if (is_array($strings)) {
  593. $this->strings = array_merge($this->strings, $strings);
  594. }
  595. if (is_array($strings) && count($strings)) {
  596. $this->strings = array_merge($this->strings, $this->override);
  597. $result = true;
  598. }
  599. }
  600. // Record the result of loading the extension's file.
  601. if (! isset($this->paths[$extension])) {
  602. $this->paths[$extension] = array();
  603. }
  604. $this->paths[$extension][$filename] = $result;
  605. return $result;
  606. }
  607. /**
  608. * Parses a language file
  609. *
  610. * @param string $filename The name of the file.
  611. *
  612. * @return array The array of parsed strings.
  613. * @since 1.6
  614. */
  615. protected function parse($filename)
  616. {
  617. $version = phpversion();
  618. // Capture hidden PHP errors from the parsing.
  619. $php_errormsg = null;
  620. $track_errors = ini_get('track_errors');
  621. ini_set('track_errors', true);
  622. if ($version >= '5.3.1') {
  623. $contents = file_get_contents($filename);
  624. $contents = str_replace('_QQ_','"\""',$contents);
  625. $strings = @parse_ini_string($contents);
  626. }
  627. else {
  628. $strings = @parse_ini_file($filename);
  629. if ($version == '5.3.0' && is_array($strings)) {
  630. foreach($strings as $key => $string) {
  631. $strings[$key]=str_replace('_QQ_','"',$string);
  632. }
  633. }
  634. }
  635. // Restore error tracking to what it was before.
  636. ini_set('track_errors',$track_errors);
  637. if (!is_array($strings)) {
  638. $strings = array();
  639. }
  640. if ($this->debug) {
  641. // Initialise variables for manually parsing the file for common errors.
  642. $blacklist = array('YES','NO','NULL','FALSE','ON','OFF','NONE','TRUE');
  643. $regex = '/^(|(\[[^\]]*\])|([A-Z][A-Z0-9_\-]*\s*=(\s*(("[^"]*")|(_QQ_)))+))\s*(;.*)?$/';
  644. $this->debug = false;
  645. $errors = array();
  646. $lineNumber = 0;
  647. // Open the file as a stream.
  648. $stream = new JStream();
  649. $stream->open($filename);
  650. while (!$stream->eof())
  651. {
  652. $line = $stream->gets();
  653. $lineNumber++;
  654. // Check that the key is not in the blacklist and that the line format passes the regex.
  655. $key = strtoupper(trim(substr($line, 0, strpos($line, '='))));
  656. if (!preg_match($regex, $line) || in_array($key, $blacklist)) {
  657. $errors[] = $lineNumber;
  658. }
  659. }
  660. $stream->close();
  661. // Check if we encountered any errors.
  662. if (count($errors)) {
  663. if (basename($filename) != $this->lang.'.ini') {
  664. $this->errorfiles[$filename] = $filename.JText::sprintf('JERROR_PARSING_LANGUAGE_FILE', implode(', ', $errors));
  665. }
  666. else {
  667. $this->errorfiles[$filename] = $filename . '&#160;: error(s) in line(s) ' . implode(', ', $errors);
  668. }
  669. }
  670. else if ($php_errormsg) {
  671. // We didn't find any errors but there's probably a parse notice.
  672. $this->errorfiles['PHP'.$filename] = 'PHP parser errors :'.$php_errormsg;
  673. }
  674. $this->debug = true;
  675. }
  676. return $strings;
  677. }
  678. /**
  679. * Get a matadata language property
  680. *
  681. * @param string $property The name of the property
  682. * @param mixed $default The default value
  683. * @return mixed The value of the property
  684. * @since 1.5
  685. */
  686. public function get($property, $default = null)
  687. {
  688. if (isset ($this->metadata[$property])) {
  689. return $this->metadata[$property];
  690. }
  691. return $default;
  692. }
  693. /**
  694. * Determine who called JLanguage or JText
  695. *
  696. * @return array Caller information
  697. * @since 1.5
  698. */
  699. protected function getCallerInfo()
  700. {
  701. // Try to determine the source if none was provided
  702. if (!function_exists('debug_backtrace')) {
  703. return null;
  704. }
  705. $backtrace = debug_backtrace();
  706. $info = array();
  707. // Search through the backtrace to our caller
  708. $continue = true;
  709. while ($continue && next($backtrace)) {
  710. $step = current($backtrace);
  711. $class = @ $step['class'];
  712. // We're looking for something outside of language.php
  713. if ($class != 'JLanguage' && $class != 'JText') {
  714. $info['function'] = @ $step['function'];
  715. $info['class'] = $class;
  716. $info['step'] = prev($backtrace);
  717. // Determine the file and name of the file
  718. $info['file'] = @ $step['file'];
  719. $info['line'] = @ $step['line'];
  720. $continue = false;
  721. }
  722. }
  723. return $info;
  724. }
  725. /**
  726. * Getter for Name
  727. *
  728. * @return string Official name element of the language
  729. * @since 1.5
  730. */
  731. public function getName() {
  732. return $this->metadata['name'];
  733. }
  734. /**
  735. * Get a list of language files that have been loaded
  736. *
  737. * @param string $extension An option extension name
  738. * @return array
  739. * @since 1.5
  740. */
  741. public function getPaths($extension = null)
  742. {
  743. if (isset($extension)) {
  744. if (isset($this->paths[$extension])) {
  745. return $this->paths[$extension];
  746. }
  747. return null;
  748. } else {
  749. return $this->paths;
  750. }
  751. }
  752. /**
  753. * Get a list of language files that are in error state
  754. *
  755. * @return array
  756. * @since 1.6
  757. */
  758. public function getErrorFiles()
  759. {
  760. return $this->errorfiles;
  761. }
  762. /**
  763. * Get for the language tag (as defined in RFC 3066)
  764. *
  765. * @return string The language tag
  766. * @since 1.5
  767. */
  768. public function getTag() {
  769. return $this->metadata['tag'];
  770. }
  771. /**
  772. * Get the RTL property
  773. *
  774. * @return boolean True is it an RTL language
  775. * @since 1.5
  776. */
  777. public function isRTL()
  778. {
  779. return $this->metadata['rtl'];
  780. }
  781. /**
  782. * Set the Debug property
  783. *
  784. * @return boolean Previous value
  785. * @since 1.5
  786. */
  787. public function setDebug($debug)
  788. {
  789. $previous = $this->debug;
  790. $this->debug = $debug;
  791. return $previous;
  792. }
  793. /**
  794. * Get the Debug property
  795. *
  796. * @return boolean True is in debug mode
  797. * @since 1.5
  798. */
  799. public function getDebug()
  800. {
  801. return $this->debug;
  802. }
  803. /**
  804. * Get the default language code
  805. *
  806. * @return string Language code
  807. * @since 1.5
  808. */
  809. public function getDefault()
  810. {
  811. return $this->default;
  812. }
  813. /**
  814. * Set the default language code
  815. *
  816. * @return string Previous value
  817. * @since 1.5
  818. */
  819. public function setDefault($lang)
  820. {
  821. $previous = $this->default;
  822. $this->default = $lang;
  823. return $previous;
  824. }
  825. /**
  826. * Get the list of orphaned strings if being tracked
  827. *
  828. * @return array Orphaned text
  829. * @since 1.5
  830. */
  831. public function getOrphans()
  832. {
  833. return $this->orphans;
  834. }
  835. /**
  836. * Get the list of used strings
  837. *
  838. * Used strings are those strings requested and found either as a string or a constant
  839. *
  840. * @return array Used strings
  841. * @since 1.5
  842. */
  843. public function getUsed()
  844. {
  845. return $this->used;
  846. }
  847. /**
  848. * Determines is a key exists
  849. *
  850. * @param key $key The key to check
  851. * @return boolean True, if the key exists
  852. * @since 1.5
  853. */
  854. function hasKey($string)
  855. {
  856. $key = strtoupper($string);
  857. return isset ($this->strings[$key]);
  858. }
  859. /**
  860. * Returns a associative array holding the metadata
  861. *
  862. * @param string The name of the language
  863. * @return mixed If $lang exists return key/value pair with the language metadata,
  864. * otherwise return NULL
  865. * @since 1.5
  866. */
  867. public static function getMetadata($lang)
  868. {
  869. $path = self::getLanguagePath(JPATH_BASE, $lang);
  870. $file = "$lang.xml";
  871. $result = null;
  872. if (is_file("$path/$file")) {
  873. $result = self::parseXMLLanguageFile("$path/$file");
  874. }
  875. return $result;
  876. }
  877. /**
  878. * Returns a list of known languages for an area
  879. *
  880. * @param string $basePath The basepath to use
  881. * @return array key/value pair with the language file and real name
  882. * @since 1.5
  883. */
  884. public static function getKnownLanguages($basePath = JPATH_BASE)
  885. {
  886. $dir = self::getLanguagePath($basePath);
  887. $knownLanguages = self::parseLanguageFiles($dir);
  888. return $knownLanguages;
  889. }
  890. /**
  891. * Get the path to a language
  892. *
  893. * @param string $basePath The basepath to use
  894. * @param string $language The language tag
  895. * @return string language related path or null
  896. * @since 1.5
  897. */
  898. public static function getLanguagePath($basePath = JPATH_BASE, $language = null)
  899. {
  900. $dir = "$basePath/language";
  901. if (!empty($language)) {
  902. $dir .= "/$language";
  903. }
  904. return $dir;
  905. }
  906. /**
  907. * Set the language attributes to the given language
  908. *
  909. * Once called, the language still needs to be loaded using JLanguage::load()
  910. *
  911. * @param string $lang Language code
  912. * @return string Previous value
  913. * @since 1.5
  914. */
  915. public function setLanguage($lang)
  916. {
  917. $previous = $this->lang;
  918. $this->lang = $lang;
  919. $this->metadata = $this->getMetadata($this->lang);
  920. return $previous;
  921. }
  922. /**
  923. * Get the language locale based on current language
  924. *
  925. * @return array|false The locale according to the language
  926. * @since 1.6
  927. */
  928. public function getLocale()
  929. {
  930. if (!isset($this->locale))
  931. {
  932. $locale = str_replace(' ', '', isset($this->metadata['locale']) ? $this->metadata['locale'] : '');
  933. if ($locale)
  934. {
  935. $this->locale = explode(',', $locale);
  936. }
  937. else
  938. {
  939. $this->locale = false;
  940. }
  941. }
  942. return $this->locale;
  943. }
  944. /**
  945. * Get the first day of the week for this language
  946. *
  947. * @return int The first day of the week according to the language
  948. * @since 1.6
  949. */
  950. public function getFirstDay()
  951. {
  952. return (int) (isset($this->metadata['firstDay']) ? $this->metadata['firstDay'] : 0);
  953. }
  954. /**
  955. * Searches for language directories within a certain base dir
  956. *
  957. * @param string $dir directory of files
  958. * @return array Array holding the found languages as filename => real name pairs
  959. * @deprecated use parseLanguageFiles instead
  960. * @since 1.5
  961. */
  962. public static function _parseLanguageFiles($dir = null)
  963. {
  964. return self::parseLanguageFiles($dir);
  965. }
  966. /**
  967. * Searches for language directories within a certain base dir
  968. *
  969. * @param string $dir directory of files
  970. * @return array Array holding the found languages as filename => real name pairs
  971. * @since 1.6
  972. */
  973. public static function parseLanguageFiles($dir = null)
  974. {
  975. jimport('joomla.filesystem.folder');
  976. $languages = array ();
  977. $subdirs = JFolder::folders($dir);
  978. foreach ($subdirs as $path) {
  979. $langs = self::parseXMLLanguageFiles("$dir/$path");
  980. $languages = array_merge($languages, $langs);
  981. }
  982. return $languages;
  983. }
  984. /**
  985. * Parses XML files for language information
  986. *
  987. * @param string $dir Directory of files
  988. * @return array Array holding the found languages as filename => metadata array
  989. * @deprecated use parseXMLLanguageFiles instead
  990. * @since 1.5
  991. */
  992. public static function _parseXMLLanguageFiles($dir = null)
  993. {
  994. return self::parseXMLLanguageFiles($dir);
  995. }
  996. /**
  997. * Parses XML files for language information
  998. *
  999. * @param string $dir Directory of files
  1000. * @return array Array holding the found languages as filename => metadata array
  1001. * @since 1.6
  1002. */
  1003. public static function parseXMLLanguageFiles($dir = null)
  1004. {
  1005. if ($dir == null) {
  1006. return null;
  1007. }
  1008. $languages = array ();
  1009. jimport('joomla.filesystem.folder');
  1010. $files = JFolder::files($dir, '^([-_A-Za-z]*)\.xml$');
  1011. foreach ($files as $file) {
  1012. if ($content = file_get_contents("$dir/$file")) {
  1013. if ($metadata = self::parseXMLLanguageFile("$dir/$file")) {
  1014. $lang = str_replace('.xml', '', $file);
  1015. $languages[$lang] = $metadata;
  1016. }
  1017. }
  1018. }
  1019. return $languages;
  1020. }
  1021. /**
  1022. * Parse XML file for language information.
  1023. *
  1024. * @param string $path Path to the xml files
  1025. * @return array Array holding the found metadata as a key => value pair
  1026. * @deprecated use parseXMLLanguageFile instead
  1027. * @since 1.5
  1028. */
  1029. public static function _parseXMLLanguageFile($path)
  1030. {
  1031. return self::parseXMLLanguageFile($path);
  1032. }
  1033. /**
  1034. * Parse XML file for language information.
  1035. *
  1036. * @param string $path Path to the xml files
  1037. * @return array Array holding the found metadata as a key => value pair
  1038. * @since 1.6
  1039. */
  1040. public static function parseXMLLanguageFile($path)
  1041. {
  1042. // Try to load the file
  1043. if (!$xml = JFactory::getXML($path)) {
  1044. return null;
  1045. }
  1046. // Check that it's a metadata file
  1047. if ((string)$xml->getName() != 'metafile') {
  1048. return null;
  1049. }
  1050. $metadata = array();
  1051. foreach ($xml->metadata->children() as $child) {
  1052. $metadata[$child->getName()] = (string) $child;
  1053. }
  1054. return $metadata;
  1055. }
  1056. }