PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/language/language.php

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