[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Language/ -> Language.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\Language;
  11  
  12  use Joomla\CMS\Factory;
  13  use Joomla\String\StringHelper;
  14  
  15  // phpcs:disable PSR1.Files.SideEffects
  16  \defined('JPATH_PLATFORM') or die;
  17  // phpcs:enable PSR1.Files.SideEffects
  18  
  19  /**
  20   * Languages/translation handler class
  21   *
  22   * @since  1.7.0
  23   */
  24  class Language
  25  {
  26      /**
  27       * Array of Language objects
  28       *
  29       * @var    Language[]
  30       * @since  1.7.0
  31       */
  32      protected static $languages = array();
  33  
  34      /**
  35       * Debug language, If true, highlights if string isn't found.
  36       *
  37       * @var    boolean
  38       * @since  1.7.0
  39       */
  40      protected $debug = false;
  41  
  42      /**
  43       * The default language, used when a language file in the requested language does not exist.
  44       *
  45       * @var    string
  46       * @since  1.7.0
  47       */
  48      protected $default = 'en-GB';
  49  
  50      /**
  51       * An array of orphaned text.
  52       *
  53       * @var    array
  54       * @since  1.7.0
  55       */
  56      protected $orphans = array();
  57  
  58      /**
  59       * Array holding the language metadata.
  60       *
  61       * @var    array
  62       * @since  1.7.0
  63       */
  64      protected $metadata = null;
  65  
  66      /**
  67       * Array holding the language locale or boolean null if none.
  68       *
  69       * @var    array|boolean
  70       * @since  1.7.0
  71       */
  72      protected $locale = null;
  73  
  74      /**
  75       * The language to load.
  76       *
  77       * @var    string
  78       * @since  1.7.0
  79       */
  80      protected $lang = null;
  81  
  82      /**
  83       * A nested array of language files that have been loaded
  84       *
  85       * @var    array
  86       * @since  1.7.0
  87       */
  88      protected $paths = array();
  89  
  90      /**
  91       * List of language files that are in error state
  92       *
  93       * @var    array
  94       * @since  1.7.0
  95       */
  96      protected $errorfiles = array();
  97  
  98      /**
  99       * Translations
 100       *
 101       * @var    array
 102       * @since  1.7.0
 103       */
 104      protected $strings = array();
 105  
 106      /**
 107       * An array of used text, used during debugging.
 108       *
 109       * @var    array
 110       * @since  1.7.0
 111       */
 112      protected $used = array();
 113  
 114      /**
 115       * Counter for number of loads.
 116       *
 117       * @var    integer
 118       * @since  1.7.0
 119       */
 120      protected $counter = 0;
 121  
 122      /**
 123       * An array used to store overrides.
 124       *
 125       * @var    array
 126       * @since  1.7.0
 127       */
 128      protected $override = array();
 129  
 130      /**
 131       * Name of the transliterator function for this language.
 132       *
 133       * @var    string
 134       * @since  1.7.0
 135       */
 136      protected $transliterator = null;
 137  
 138      /**
 139       * Name of the pluralSuffixesCallback function for this language.
 140       *
 141       * @var    callable
 142       * @since  1.7.0
 143       */
 144      protected $pluralSuffixesCallback = null;
 145  
 146      /**
 147       * Name of the ignoredSearchWordsCallback function for this language.
 148       *
 149       * @var    callable
 150       * @since  1.7.0
 151       */
 152      protected $ignoredSearchWordsCallback = null;
 153  
 154      /**
 155       * Name of the lowerLimitSearchWordCallback function for this language.
 156       *
 157       * @var    callable
 158       * @since  1.7.0
 159       */
 160      protected $lowerLimitSearchWordCallback = null;
 161  
 162      /**
 163       * Name of the upperLimitSearchWordCallback function for this language.
 164       *
 165       * @var    callable
 166       * @since  1.7.0
 167       */
 168      protected $upperLimitSearchWordCallback = null;
 169  
 170      /**
 171       * Name of the searchDisplayedCharactersNumberCallback function for this language.
 172       *
 173       * @var    callable
 174       * @since  1.7.0
 175       */
 176      protected $searchDisplayedCharactersNumberCallback = null;
 177  
 178      /**
 179       * Constructor activating the default information of the language.
 180       *
 181       * @param   string   $lang   The language
 182       * @param   boolean  $debug  Indicates if language debugging is enabled.
 183       *
 184       * @since   1.7.0
 185       */
 186      public function __construct($lang = null, $debug = false)
 187      {
 188          $this->strings = array();
 189  
 190          if ($lang == null) {
 191              $lang = $this->default;
 192          }
 193  
 194          $this->lang = $lang;
 195          $this->metadata = LanguageHelper::getMetadata($this->lang);
 196          $this->setDebug($debug);
 197  
 198          /*
 199           * Let's load the default override once, so we can profit from that, too
 200           * But make sure, that we don't enforce it on each language file load.
 201           * So don't put it in $this->override
 202           */
 203          if (!$this->debug && $lang !== $this->default) {
 204              $this->loadLanguage(JPATH_BASE . '/language/overrides/' . $this->default . '.override.ini');
 205          }
 206  
 207          $this->override = $this->parse(JPATH_BASE . '/language/overrides/' . $lang . '.override.ini');
 208  
 209          // Look for a language specific localise class
 210          $class = str_replace('-', '_', $lang . 'Localise');
 211          $paths = array();
 212  
 213          if (\defined('JPATH_SITE')) {
 214              // Note: Manual indexing to enforce load order.
 215              $paths[0] = JPATH_SITE . "/language/overrides/$lang.localise.php";
 216              $paths[2] = JPATH_SITE . "/language/$lang/localise.php";
 217              $paths[4] = JPATH_SITE . "/language/$lang/$lang.localise.php";
 218          }
 219  
 220          if (\defined('JPATH_ADMINISTRATOR')) {
 221              // Note: Manual indexing to enforce load order.
 222              $paths[1] = JPATH_ADMINISTRATOR . "/language/overrides/$lang.localise.php";
 223              $paths[3] = JPATH_ADMINISTRATOR . "/language/$lang/localise.php";
 224              $paths[5] = JPATH_ADMINISTRATOR . "/language/$lang/$lang.localise.php";
 225          }
 226  
 227          ksort($paths);
 228          $path = reset($paths);
 229  
 230          while (!class_exists($class) && $path) {
 231              if (is_file($path)) {
 232                  require_once $path;
 233              }
 234  
 235              $path = next($paths);
 236          }
 237  
 238          if (class_exists($class)) {
 239              /**
 240               * Class exists. Try to find
 241               * -a transliterate method,
 242               * -a getPluralSuffixes method,
 243               * -a getIgnoredSearchWords method
 244               * -a getLowerLimitSearchWord method
 245               * -a getUpperLimitSearchWord method
 246               * -a getSearchDisplayCharactersNumber method
 247               */
 248              if (method_exists($class, 'transliterate')) {
 249                  $this->transliterator = array($class, 'transliterate');
 250              }
 251  
 252              if (method_exists($class, 'getPluralSuffixes')) {
 253                  $this->pluralSuffixesCallback = array($class, 'getPluralSuffixes');
 254              }
 255  
 256              if (method_exists($class, 'getIgnoredSearchWords')) {
 257                  $this->ignoredSearchWordsCallback = array($class, 'getIgnoredSearchWords');
 258              }
 259  
 260              if (method_exists($class, 'getLowerLimitSearchWord')) {
 261                  $this->lowerLimitSearchWordCallback = array($class, 'getLowerLimitSearchWord');
 262              }
 263  
 264              if (method_exists($class, 'getUpperLimitSearchWord')) {
 265                  $this->upperLimitSearchWordCallback = array($class, 'getUpperLimitSearchWord');
 266              }
 267  
 268              if (method_exists($class, 'getSearchDisplayedCharactersNumber')) {
 269                  $this->searchDisplayedCharactersNumberCallback = array($class, 'getSearchDisplayedCharactersNumber');
 270              }
 271          }
 272  
 273          $this->load();
 274      }
 275  
 276      /**
 277       * Returns a language object.
 278       *
 279       * @param   string   $lang   The language to use.
 280       * @param   boolean  $debug  The debug mode.
 281       *
 282       * @return  Language  The Language object.
 283       *
 284       * @since       1.7.0
 285       * @deprecated  5.0 Use the language factory instead
 286       */
 287      public static function getInstance($lang, $debug = false)
 288      {
 289          if (!isset(self::$languages[$lang . $debug])) {
 290              self::$languages[$lang . $debug] = Factory::getContainer()->get(LanguageFactoryInterface::class)->createLanguage($lang, $debug);
 291          }
 292  
 293          return self::$languages[$lang . $debug];
 294      }
 295  
 296      /**
 297       * Translate function, mimics the php gettext (alias _) function.
 298       *
 299       * The function checks if $jsSafe is true, then if $interpretBackslashes is true.
 300       *
 301       * @param   string   $string                The string to translate
 302       * @param   boolean  $jsSafe                Make the result javascript safe
 303       * @param   boolean  $interpretBackSlashes  Interpret \t and \n
 304       *
 305       * @return  string  The translation of the string
 306       *
 307       * @since   1.7.0
 308       */
 309      public function _($string, $jsSafe = false, $interpretBackSlashes = true)
 310      {
 311          // Detect empty string
 312          if ($string == '') {
 313              return '';
 314          }
 315  
 316          $key = strtoupper($string);
 317  
 318          if (isset($this->strings[$key])) {
 319              $string = $this->strings[$key];
 320  
 321              // Store debug information
 322              if ($this->debug) {
 323                  $value = Factory::getApplication()->get('debug_lang_const', true) ? $string : $key;
 324                  $string = '**' . $value . '**';
 325  
 326                  $caller = $this->getCallerInfo();
 327  
 328                  if (!\array_key_exists($key, $this->used)) {
 329                      $this->used[$key] = array();
 330                  }
 331  
 332                  $this->used[$key][] = $caller;
 333              }
 334          } else {
 335              if ($this->debug) {
 336                  $info = [];
 337                  $info['trace'] = $this->getTrace();
 338                  $info['key'] = $key;
 339                  $info['string'] = $string;
 340  
 341                  if (!\array_key_exists($key, $this->orphans)) {
 342                      $this->orphans[$key] = array();
 343                  }
 344  
 345                  $this->orphans[$key][] = $info;
 346  
 347                  $string = '??' . $string . '??';
 348              }
 349          }
 350  
 351          if ($jsSafe) {
 352              // Javascript filter
 353              $string = addslashes($string);
 354          } elseif ($interpretBackSlashes) {
 355              if (strpos($string, '\\') !== false) {
 356                  // Interpret \n and \t characters
 357                  $string = str_replace(array('\\\\', '\t', '\n'), array("\\", "\t", "\n"), $string);
 358              }
 359          }
 360  
 361          return $string;
 362      }
 363  
 364      /**
 365       * Transliterate function
 366       *
 367       * This method processes a string and replaces all accented UTF-8 characters by unaccented
 368       * ASCII-7 "equivalents".
 369       *
 370       * @param   string  $string  The string to transliterate.
 371       *
 372       * @return  string  The transliteration of the string.
 373       *
 374       * @since   1.7.0
 375       */
 376      public function transliterate($string)
 377      {
 378          // First check for transliterator provided by translation
 379          if ($this->transliterator !== null) {
 380              $string = \call_user_func($this->transliterator, $string);
 381  
 382              // Check if all symbols were transliterated (contains only ASCII), otherwise continue
 383              if (!preg_match('/[\\x80-\\xff]/', $string)) {
 384                  return $string;
 385              }
 386          }
 387  
 388          // Run our transliterator for common symbols,
 389          // This need to be executed before native php transliterator, because it may not have all required transliterators
 390          $string = Transliterate::utf8_latin_to_ascii($string);
 391  
 392          // Check if all symbols were transliterated (contains only ASCII),
 393          // Otherwise try to use native php function if available
 394          if (preg_match('/[\\x80-\\xff]/', $string) && function_exists('transliterator_transliterate') && function_exists('iconv')) {
 395              return iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", transliterator_transliterate('Any-Latin; Latin-ASCII; Lower()', $string));
 396          }
 397  
 398          return StringHelper::strtolower($string);
 399      }
 400  
 401      /**
 402       * Getter for transliteration function
 403       *
 404       * @return  callable  The transliterator function
 405       *
 406       * @since   1.7.0
 407       */
 408      public function getTransliterator()
 409      {
 410          return $this->transliterator;
 411      }
 412  
 413      /**
 414       * Set the transliteration function.
 415       *
 416       * @param   callable  $function  Function name or the actual function.
 417       *
 418       * @return  callable  The previous function.
 419       *
 420       * @since   1.7.0
 421       */
 422      public function setTransliterator(callable $function)
 423      {
 424          $previous = $this->transliterator;
 425          $this->transliterator = $function;
 426  
 427          return $previous;
 428      }
 429  
 430      /**
 431       * Returns an array of suffixes for plural rules.
 432       *
 433       * @param   integer  $count  The count number the rule is for.
 434       *
 435       * @return  array    The array of suffixes.
 436       *
 437       * @since   1.7.0
 438       */
 439      public function getPluralSuffixes($count)
 440      {
 441          if ($this->pluralSuffixesCallback !== null) {
 442              return \call_user_func($this->pluralSuffixesCallback, $count);
 443          } else {
 444              return array((string) $count);
 445          }
 446      }
 447  
 448      /**
 449       * Getter for pluralSuffixesCallback function.
 450       *
 451       * @return  callable  Function name or the actual function.
 452       *
 453       * @since   1.7.0
 454       */
 455      public function getPluralSuffixesCallback()
 456      {
 457          return $this->pluralSuffixesCallback;
 458      }
 459  
 460      /**
 461       * Set the pluralSuffixes function.
 462       *
 463       * @param   callable  $function  Function name or actual function.
 464       *
 465       * @return  callable  The previous function.
 466       *
 467       * @since   1.7.0
 468       */
 469      public function setPluralSuffixesCallback(callable $function)
 470      {
 471          $previous = $this->pluralSuffixesCallback;
 472          $this->pluralSuffixesCallback = $function;
 473  
 474          return $previous;
 475      }
 476  
 477      /**
 478       * Returns an array of ignored search words
 479       *
 480       * @return  array  The array of ignored search words.
 481       *
 482       * @since   1.7.0
 483       */
 484      public function getIgnoredSearchWords()
 485      {
 486          if ($this->ignoredSearchWordsCallback !== null) {
 487              return \call_user_func($this->ignoredSearchWordsCallback);
 488          } else {
 489              return array();
 490          }
 491      }
 492  
 493      /**
 494       * Getter for ignoredSearchWordsCallback function.
 495       *
 496       * @return  callable  Function name or the actual function.
 497       *
 498       * @since   1.7.0
 499       */
 500      public function getIgnoredSearchWordsCallback()
 501      {
 502          return $this->ignoredSearchWordsCallback;
 503      }
 504  
 505      /**
 506       * Setter for the ignoredSearchWordsCallback function
 507       *
 508       * @param   callable  $function  Function name or actual function.
 509       *
 510       * @return  callable  The previous function.
 511       *
 512       * @since   1.7.0
 513       */
 514      public function setIgnoredSearchWordsCallback(callable $function)
 515      {
 516          $previous = $this->ignoredSearchWordsCallback;
 517          $this->ignoredSearchWordsCallback = $function;
 518  
 519          return $previous;
 520      }
 521  
 522      /**
 523       * Returns a lower limit integer for length of search words
 524       *
 525       * @return  integer  The lower limit integer for length of search words (3 if no value was set for a specific language).
 526       *
 527       * @since   1.7.0
 528       */
 529      public function getLowerLimitSearchWord()
 530      {
 531          if ($this->lowerLimitSearchWordCallback !== null) {
 532              return \call_user_func($this->lowerLimitSearchWordCallback);
 533          } else {
 534              return 3;
 535          }
 536      }
 537  
 538      /**
 539       * Getter for lowerLimitSearchWordCallback function
 540       *
 541       * @return  callable  Function name or the actual function.
 542       *
 543       * @since   1.7.0
 544       */
 545      public function getLowerLimitSearchWordCallback()
 546      {
 547          return $this->lowerLimitSearchWordCallback;
 548      }
 549  
 550      /**
 551       * Setter for the lowerLimitSearchWordCallback function.
 552       *
 553       * @param   callable  $function  Function name or actual function.
 554       *
 555       * @return  callable  The previous function.
 556       *
 557       * @since   1.7.0
 558       */
 559      public function setLowerLimitSearchWordCallback(callable $function)
 560      {
 561          $previous = $this->lowerLimitSearchWordCallback;
 562          $this->lowerLimitSearchWordCallback = $function;
 563  
 564          return $previous;
 565      }
 566  
 567      /**
 568       * Returns an upper limit integer for length of search words
 569       *
 570       * @return  integer  The upper limit integer for length of search words (200 if no value was set or if default value is < 200).
 571       *
 572       * @since   1.7.0
 573       */
 574      public function getUpperLimitSearchWord()
 575      {
 576          if ($this->upperLimitSearchWordCallback !== null && \call_user_func($this->upperLimitSearchWordCallback) > 200) {
 577              return \call_user_func($this->upperLimitSearchWordCallback);
 578          }
 579  
 580          return 200;
 581      }
 582  
 583      /**
 584       * Getter for upperLimitSearchWordCallback function
 585       *
 586       * @return  callable  Function name or the actual function.
 587       *
 588       * @since   1.7.0
 589       */
 590      public function getUpperLimitSearchWordCallback()
 591      {
 592          return $this->upperLimitSearchWordCallback;
 593      }
 594  
 595      /**
 596       * Setter for the upperLimitSearchWordCallback function
 597       *
 598       * @param   callable  $function  Function name or the actual function.
 599       *
 600       * @return  callable  The previous function.
 601       *
 602       * @since   1.7.0
 603       */
 604      public function setUpperLimitSearchWordCallback(callable $function)
 605      {
 606          $previous = $this->upperLimitSearchWordCallback;
 607          $this->upperLimitSearchWordCallback = $function;
 608  
 609          return $previous;
 610      }
 611  
 612      /**
 613       * Returns the number of characters displayed in search results.
 614       *
 615       * @return  integer  The number of characters displayed (200 if no value was set for a specific language).
 616       *
 617       * @since   1.7.0
 618       */
 619      public function getSearchDisplayedCharactersNumber()
 620      {
 621          if ($this->searchDisplayedCharactersNumberCallback !== null) {
 622              return \call_user_func($this->searchDisplayedCharactersNumberCallback);
 623          } else {
 624              return 200;
 625          }
 626      }
 627  
 628      /**
 629       * Getter for searchDisplayedCharactersNumberCallback function
 630       *
 631       * @return  callable  Function name or the actual function.
 632       *
 633       * @since   1.7.0
 634       */
 635      public function getSearchDisplayedCharactersNumberCallback()
 636      {
 637          return $this->searchDisplayedCharactersNumberCallback;
 638      }
 639  
 640      /**
 641       * Setter for the searchDisplayedCharactersNumberCallback function.
 642       *
 643       * @param   callable  $function  Function name or the actual function.
 644       *
 645       * @return  callable  The previous function.
 646       *
 647       * @since   1.7.0
 648       */
 649      public function setSearchDisplayedCharactersNumberCallback(callable $function)
 650      {
 651          $previous = $this->searchDisplayedCharactersNumberCallback;
 652          $this->searchDisplayedCharactersNumberCallback = $function;
 653  
 654          return $previous;
 655      }
 656  
 657      /**
 658       * Loads a single language file and appends the results to the existing strings
 659       *
 660       * @param   string   $extension  The extension for which a language file should be loaded.
 661       * @param   string   $basePath   The basepath to use.
 662       * @param   string   $lang       The language to load, default null for the current language.
 663       * @param   boolean  $reload     Flag that will force a language to be reloaded if set to true.
 664       * @param   boolean  $default    Flag that force the default language to be loaded if the current does not exist.
 665       *
 666       * @return  boolean  True if the file has successfully loaded.
 667       *
 668       * @since   1.7.0
 669       */
 670      public function load($extension = 'joomla', $basePath = JPATH_BASE, $lang = null, $reload = false, $default = true)
 671      {
 672          // If language is null set as the current language.
 673          if (!$lang) {
 674              $lang = $this->lang;
 675          }
 676  
 677          // Load the default language first if we're not debugging and a non-default language is requested to be loaded
 678          // with $default set to true
 679          if (!$this->debug && ($lang != $this->default) && $default) {
 680              $this->load($extension, $basePath, $this->default, false, true);
 681          }
 682  
 683          $path = LanguageHelper::getLanguagePath($basePath, $lang);
 684  
 685          $internal = $extension === 'joomla' || $extension == '';
 686  
 687          $filenames = array();
 688  
 689          if ($internal) {
 690              $filenames[] = "$path/joomla.ini";
 691              $filenames[] = "$path/$lang.ini";
 692          } else {
 693              // Try first without a language-prefixed filename.
 694              $filenames[] = "$path/$extension.ini";
 695              $filenames[] = "$path/$lang.$extension.ini";
 696          }
 697  
 698          foreach ($filenames as $filename) {
 699              if (isset($this->paths[$extension][$filename]) && !$reload) {
 700                  // This file has already been tested for loading.
 701                  $result = $this->paths[$extension][$filename];
 702              } else {
 703                  // Load the language file
 704                  $result = $this->loadLanguage($filename, $extension);
 705              }
 706  
 707              if ($result) {
 708                  return true;
 709              }
 710          }
 711  
 712          return false;
 713      }
 714  
 715      /**
 716       * Loads a language file.
 717       *
 718       * This method will not note the successful loading of a file - use load() instead.
 719       *
 720       * @param   string  $fileName   The name of the file.
 721       * @param   string  $extension  The name of the extension.
 722       *
 723       * @return  boolean  True if new strings have been added to the language
 724       *
 725       * @see     Language::load()
 726       * @since   1.7.0
 727       */
 728      protected function loadLanguage($fileName, $extension = 'unknown')
 729      {
 730          $this->counter++;
 731  
 732          $result  = false;
 733          $strings = $this->parse($fileName);
 734  
 735          if ($strings !== array()) {
 736              $this->strings = array_replace($this->strings, $strings, $this->override);
 737              $result = true;
 738          }
 739  
 740          // Record the result of loading the extension's file.
 741          if (!isset($this->paths[$extension])) {
 742              $this->paths[$extension] = array();
 743          }
 744  
 745          $this->paths[$extension][$fileName] = $result;
 746  
 747          return $result;
 748      }
 749  
 750      /**
 751       * Parses a language file.
 752       *
 753       * @param   string  $fileName  The name of the file.
 754       *
 755       * @return  array  The array of parsed strings.
 756       *
 757       * @since   1.7.0
 758       */
 759      protected function parse($fileName)
 760      {
 761          $strings = LanguageHelper::parseIniFile($fileName, $this->debug);
 762  
 763          // Debug the ini file if needed.
 764          if ($this->debug === true && is_file($fileName)) {
 765              $this->debugFile($fileName);
 766          }
 767  
 768          return $strings;
 769      }
 770  
 771      /**
 772       * Debugs a language file
 773       *
 774       * @param   string  $filename  Absolute path to the file to debug
 775       *
 776       * @return  integer  A count of the number of parsing errors
 777       *
 778       * @since   3.6.3
 779       * @throws  \InvalidArgumentException
 780       */
 781      public function debugFile($filename)
 782      {
 783          // Make sure our file actually exists
 784          if (!is_file($filename)) {
 785              throw new \InvalidArgumentException(
 786                  sprintf('Unable to locate file "%s" for debugging', $filename)
 787              );
 788          }
 789  
 790          // Initialise variables for manually parsing the file for common errors.
 791          $reservedWord = array('YES', 'NO', 'NULL', 'FALSE', 'ON', 'OFF', 'NONE', 'TRUE');
 792          $debug = $this->getDebug();
 793          $this->debug = false;
 794          $errors = array();
 795          $php_errormsg = null;
 796  
 797          // Open the file as a stream.
 798          $file = new \SplFileObject($filename);
 799  
 800          foreach ($file as $lineNumber => $line) {
 801              // Avoid BOM error as BOM is OK when using parse_ini.
 802              if ($lineNumber == 0) {
 803                  $line = str_replace("\xEF\xBB\xBF", '', $line);
 804              }
 805  
 806              $line = trim($line);
 807  
 808              // Ignore comment lines.
 809              if (!\strlen($line) || $line['0'] == ';') {
 810                  continue;
 811              }
 812  
 813              // Ignore grouping tag lines, like: [group]
 814              if (preg_match('#^\[[^\]]*\](\s*;.*)?$#', $line)) {
 815                  continue;
 816              }
 817  
 818              // Remove any escaped double quotes \" from the equation
 819              $line = str_replace('\"', '', $line);
 820  
 821              $realNumber = $lineNumber + 1;
 822  
 823              // Check for odd number of double quotes.
 824              if (substr_count($line, '"') % 2 != 0) {
 825                  $errors[] = $realNumber;
 826                  continue;
 827              }
 828  
 829              // Check that the line passes the necessary format.
 830              if (!preg_match('#^[A-Z][A-Z0-9_:\*\-\.]*\s*=\s*".*"(\s*;.*)?$#', $line)) {
 831                  $errors[] = $realNumber;
 832                  continue;
 833              }
 834  
 835              // Check that the key is not in the reserved constants list.
 836              $key = strtoupper(trim(substr($line, 0, strpos($line, '='))));
 837  
 838              if (\in_array($key, $reservedWord)) {
 839                  $errors[] = $realNumber;
 840              }
 841          }
 842  
 843          // Check if we encountered any errors.
 844          if (\count($errors)) {
 845              $this->errorfiles[$filename] = $errors;
 846          } elseif ($php_errormsg) {
 847              // We didn't find any errors but there's probably a parse notice.
 848              $this->errorfiles['PHP' . $filename] = 'PHP parser errors :' . $php_errormsg;
 849          }
 850  
 851          $this->debug = $debug;
 852  
 853          return \count($errors);
 854      }
 855  
 856      /**
 857       * Get a metadata language property.
 858       *
 859       * @param   string  $property  The name of the property.
 860       * @param   mixed   $default   The default value.
 861       *
 862       * @return  mixed  The value of the property.
 863       *
 864       * @since   1.7.0
 865       */
 866      public function get($property, $default = null)
 867      {
 868          if (isset($this->metadata[$property])) {
 869              return $this->metadata[$property];
 870          }
 871  
 872          return $default;
 873      }
 874  
 875      /**
 876       * Get a back trace.
 877       *
 878       * @return array
 879       *
 880       * @since 4.0.0
 881       */
 882      protected function getTrace()
 883      {
 884          return \function_exists('debug_backtrace') ? debug_backtrace() : [];
 885      }
 886  
 887      /**
 888       * Determine who called Language or Text.
 889       *
 890       * @return  array  Caller information.
 891       *
 892       * @since   1.7.0
 893       */
 894      protected function getCallerInfo()
 895      {
 896          // Try to determine the source if none was provided
 897          if (!\function_exists('debug_backtrace')) {
 898              return;
 899          }
 900  
 901          $backtrace = debug_backtrace();
 902          $info = array();
 903  
 904          // Search through the backtrace to our caller
 905          $continue = true;
 906  
 907          while ($continue && next($backtrace)) {
 908              $step = current($backtrace);
 909              $class = @ $step['class'];
 910  
 911              // We're looking for something outside of language.php
 912              if ($class != self::class && $class != Text::class) {
 913                  $info['function'] = @ $step['function'];
 914                  $info['class'] = $class;
 915                  $info['step'] = prev($backtrace);
 916  
 917                  // Determine the file and name of the file
 918                  $info['file'] = @ $step['file'];
 919                  $info['line'] = @ $step['line'];
 920  
 921                  $continue = false;
 922              }
 923          }
 924  
 925          return $info;
 926      }
 927  
 928      /**
 929       * Getter for Name.
 930       *
 931       * @return  string  Official name element of the language.
 932       *
 933       * @since   1.7.0
 934       */
 935      public function getName()
 936      {
 937          return $this->metadata['name'];
 938      }
 939  
 940      /**
 941       * Get a list of language files that have been loaded.
 942       *
 943       * @param   string  $extension  An optional extension name.
 944       *
 945       * @return  array
 946       *
 947       * @since   1.7.0
 948       */
 949      public function getPaths($extension = null)
 950      {
 951          if (isset($extension)) {
 952              if (isset($this->paths[$extension])) {
 953                  return $this->paths[$extension];
 954              }
 955  
 956              return [];
 957          }
 958  
 959          return $this->paths;
 960      }
 961  
 962      /**
 963       * Get a list of language files that are in error state.
 964       *
 965       * @return  array
 966       *
 967       * @since   1.7.0
 968       */
 969      public function getErrorFiles()
 970      {
 971          return $this->errorfiles;
 972      }
 973  
 974      /**
 975       * Getter for the language tag (as defined in RFC 3066)
 976       *
 977       * @return  string  The language tag.
 978       *
 979       * @since   1.7.0
 980       */
 981      public function getTag()
 982      {
 983          return $this->metadata['tag'];
 984      }
 985  
 986      /**
 987       * Getter for the calendar type
 988       *
 989       * @return  string  The calendar type.
 990       *
 991       * @since   3.7.0
 992       */
 993      public function getCalendar()
 994      {
 995          if (isset($this->metadata['calendar'])) {
 996              return $this->metadata['calendar'];
 997          } else {
 998              return 'gregorian';
 999          }
1000      }
1001  
1002      /**
1003       * Get the RTL property.
1004       *
1005       * @return  boolean  True is it an RTL language.
1006       *
1007       * @since   1.7.0
1008       */
1009      public function isRtl()
1010      {
1011          return (bool) $this->metadata['rtl'];
1012      }
1013  
1014      /**
1015       * Set the Debug property.
1016       *
1017       * @param   boolean  $debug  The debug setting.
1018       *
1019       * @return  boolean  Previous value.
1020       *
1021       * @since   1.7.0
1022       */
1023      public function setDebug($debug)
1024      {
1025          $previous = $this->debug;
1026          $this->debug = (bool) $debug;
1027  
1028          return $previous;
1029      }
1030  
1031      /**
1032       * Get the Debug property.
1033       *
1034       * @return  boolean  True is in debug mode.
1035       *
1036       * @since   1.7.0
1037       */
1038      public function getDebug()
1039      {
1040          return $this->debug;
1041      }
1042  
1043      /**
1044       * Get the default language code.
1045       *
1046       * @return  string  Language code.
1047       *
1048       * @since   1.7.0
1049       */
1050      public function getDefault()
1051      {
1052          return $this->default;
1053      }
1054  
1055      /**
1056       * Set the default language code.
1057       *
1058       * @param   string  $lang  The language code.
1059       *
1060       * @return  string  Previous value.
1061       *
1062       * @since   1.7.0
1063       */
1064      public function setDefault($lang)
1065      {
1066          $previous = $this->default;
1067          $this->default = $lang;
1068  
1069          return $previous;
1070      }
1071  
1072      /**
1073       * Get the list of orphaned strings if being tracked.
1074       *
1075       * @return  array  Orphaned text.
1076       *
1077       * @since   1.7.0
1078       */
1079      public function getOrphans()
1080      {
1081          return $this->orphans;
1082      }
1083  
1084      /**
1085       * Get the list of used strings.
1086       *
1087       * Used strings are those strings requested and found either as a string or a constant.
1088       *
1089       * @return  array  Used strings.
1090       *
1091       * @since   1.7.0
1092       */
1093      public function getUsed()
1094      {
1095          return $this->used;
1096      }
1097  
1098      /**
1099       * Determines is a key exists.
1100       *
1101       * @param   string  $string  The key to check.
1102       *
1103       * @return  boolean  True, if the key exists.
1104       *
1105       * @since   1.7.0
1106       */
1107      public function hasKey($string)
1108      {
1109          if ($string === null) {
1110              return false;
1111          }
1112  
1113          return isset($this->strings[strtoupper($string)]);
1114      }
1115  
1116      /**
1117       * Get the language locale based on current language.
1118       *
1119       * @return  array  The locale according to the language.
1120       *
1121       * @since   1.7.0
1122       */
1123      public function getLocale()
1124      {
1125          if (!isset($this->locale)) {
1126              $locale = str_replace(' ', '', $this->metadata['locale'] ?? '');
1127  
1128              if ($locale) {
1129                  $this->locale = explode(',', $locale);
1130              } else {
1131                  $this->locale = false;
1132              }
1133          }
1134  
1135          return $this->locale;
1136      }
1137  
1138      /**
1139       * Get the first day of the week for this language.
1140       *
1141       * @return  integer  The first day of the week according to the language
1142       *
1143       * @since   1.7.0
1144       */
1145      public function getFirstDay()
1146      {
1147          return (int) ($this->metadata['firstDay'] ?? 0);
1148      }
1149  
1150      /**
1151       * Get the weekends days for this language.
1152       *
1153       * @return  string  The weekend days of the week separated by a comma according to the language
1154       *
1155       * @since   3.2
1156       */
1157      public function getWeekEnd()
1158      {
1159          return $this->metadata['weekEnd'] ?? '0,6';
1160      }
1161  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer