PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/include/admin/manage_languages.php

https://bitbucket.org/webop/webop-forum
PHP | 725 lines | 573 code | 77 blank | 75 comment | 109 complexity | e256ad459f7e5cdb54c38475c9f03738 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // Copyright (C) 2010 Phorum Development Team //
  5. // http://www.phorum.org //
  6. // //
  7. // This program is free software. You can redistribute it and/or modify //
  8. // it under the terms of either the current Phorum License (viewable at //
  9. // phorum.org) or the Phorum License that was distributed with this file //
  10. // //
  11. // This program is distributed in the hope that it will be useful, //
  12. // but WITHOUT ANY WARRANTY, without even the implied warranty of //
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. //
  14. // //
  15. // You should have received a copy of the Phorum License //
  16. // along with this program. //
  17. ////////////////////////////////////////////////////////////////////////////////
  18. // TODO have a better way to differentiate between Phorum distribution
  19. // TODO and addon files, so we won't index text strings from addon
  20. // TODO files in here.
  21. if(!defined("PHORUM_ADMIN")) return;
  22. define('TOKEN_DEBUGGER', 0);
  23. // Because sometimes the script can take a while, we set the
  24. // PHP time limit to a high value to prevent execution timeouts.
  25. set_time_limit(600);
  26. include_once "./include/admin/PhorumInputForm.php";
  27. // Get some form variables.
  28. $action = isset($_POST['action']) ? $_POST['action'] : 'start';
  29. $language = isset($_POST['language']) ? $_POST['language'] : $PHORUM["default_forum_options"]["language"];
  30. $filename = isset($_POST['filename']) ? trim($_POST['filename']) : '';
  31. $displayname = isset($_POST['displayname']) ? trim($_POST['displayname']) : '';
  32. // Handle downloading a new language file.
  33. if ($action == 'download_lang')
  34. {
  35. // Ditch HTML header we have so far (from the admin framework).
  36. ob_end_clean();
  37. // Send the new languagefile to the client.
  38. $basename = preg_replace('/-.*$/', '', $filename);
  39. $fullfile = $basename . '-' . PHORUM . '.php';
  40. header ("Content-Type: application/download; filename=$fullfile");
  41. header ("Content-Disposition: attachment; filename=\"$fullfile\"");
  42. $langfile = phorum_cache_get('updated_language', $filename);
  43. print $langfile;
  44. exit();
  45. }
  46. // Handle updating a language.
  47. if ($action == 'update_lang') {
  48. $langinfo = phorum_get_language_info();
  49. return phorum_generate_language_file($language, $langinfo[$language], false);
  50. }
  51. // Handle generating a new language.
  52. if ($action == 'generate_lang') {
  53. $filename = preg_replace('/\.php$/i', '', basename($filename));
  54. if ($filename == '') {
  55. phorum_admin_error("The basename may not be empty");
  56. } elseif (! preg_match('/^[\w_\.]+$/', $filename)) {
  57. phorum_admin_error(
  58. "The basename contains illegal characters. Please, keep the " .
  59. "filename simple by using only letters, numbers, underscores and " .
  60. "dots. You can't use hyphens, because those are used for " .
  61. "separating the basename from the Phorum version for which the " .
  62. "language file is used."
  63. );
  64. } elseif ($displayname == '') {
  65. phorum_admin_error("The display name for the language may not be empty.");
  66. } else {
  67. $filename .= "-" . PHORUM;
  68. return phorum_generate_language_file($filename, $displayname, true);
  69. }
  70. }
  71. // Handle start page.
  72. $frm = new PhorumInputForm ("", "post", "Generate updated language file");
  73. $frm->addmessage(<<<INTRO
  74. <font color="red">EXPERIMENTAL FEATURE<br/>
  75. Please backup your existing language file if you replace it with
  76. one generated by this maintenance tool. We feel pretty confident
  77. about it, but we wouldn't want you to lose data in case of bugs.</font>
  78. <hr size="0"/>
  79. <h2>Manage language files</h2>
  80. This is a tool which can be used for easy maintenance of
  81. language files for Phorum. It will collect all actual used
  82. language strings from the Phorum software and generate an
  83. updated langage file for your language of choice based on
  84. those strings. In the generated language file, missing and
  85. deprecated strings will be clearly marked, so you can
  86. update the language file to match the running Phorum distribution.
  87. INTRO
  88. );
  89. $frm->hidden("module", "manage_languages");
  90. $frm->hidden("action", "update_lang");
  91. $frm->addbreak("Update existing language file");
  92. $frm->addrow("Generate updated version of an existing language file",
  93. $frm->select_tag("language", phorum_get_language_info(), $language, 0));
  94. $frm->show();
  95. $frm = new PhorumInputForm("", "post", "Generate new language file");
  96. $frm->addmessage(<<<INTRO
  97. In case there is no language file available for your language or
  98. if you want to create a new language file all of your own, you can
  99. generate a new language file using the form below.
  100. INTRO
  101. );
  102. $frm->hidden("module", "manage_languages");
  103. $frm->hidden("action", "generate_lang");
  104. $frm->addbreak("Generate a new language file");
  105. $frm->addrow("The basename for the generated file", $frm->text_box('filename', $filename, 20));
  106. $frm->addrow("The display name for the language", $frm->text_box('displayname', $displayname, 20));
  107. $frm->show();
  108. exit;
  109. // ======================================================================
  110. // Generating language files
  111. // ======================================================================
  112. function phorum_generate_language_file($lang, $displayname, $generate_new)
  113. {
  114. global $fullfile;
  115. $basename = preg_replace('/-.*$/', '', $lang);
  116. $fullfile = $basename . '-' . PHORUM . '.php';
  117. // Get our default language file.
  118. $DEFAULT = phorum_get_language(PHORUM_DEFAULT_LANGUAGE);
  119. // Get the languagefile to update, unless generating a new language.
  120. $CURRENT = array();
  121. if (! $generate_new) {
  122. $CURRENT = phorum_get_language($lang);
  123. } else {
  124. $CURRENT['STORE']['language_hide'] = 0;
  125. $CURRENT['STORE']['language'] = urlencode("'" . addslashes($displayname) . "'");
  126. }
  127. // Keep a copy of the languagefile.
  128. $CURRENT_COPY = $CURRENT;
  129. // Collect all language strings from the distribution files.
  130. $language_strings = phorum_extract_language_strings();
  131. $frm = new PhorumInputForm ("", "post", "Download new " . htmlspecialchars($fullfile) . " language file");
  132. $frm->hidden("module", "manage_languages");
  133. $frm->hidden("action", "download_lang");
  134. $frm->hidden("filename", $lang);
  135. if (! $generate_new) {
  136. $frm->addmessage(
  137. "<h2>Update language: " . htmlspecialchars($displayname) . "</h2>" .
  138. "Below you will see all the things that have been updated " .
  139. "to get to the new version of the language file. At the " .
  140. "bottom of the page you will find a download button to download " .
  141. "the updated language file. This language file has to be placed " .
  142. "in <b>include/lang/" . htmlspecialchars($lang) . ".php</b> to make it " .
  143. "available to Phorum (backup your old file first of course!). " .
  144. "If new language strings have been added, " .
  145. "they will be marked with '***' in the language file, so it's " .
  146. "easy for you to find them."
  147. );
  148. $frm->addbreak("Updates for the new language file");
  149. } else {
  150. $frm->addmessage(
  151. "<h2>Generate new language: " . htmlspecialchars($displayname) . "</h2>" .
  152. "A new language file has been generated. Below you will find " .
  153. "a download button to download the new file. In this file, you " .
  154. "can replace all language strings by strings which apply to " .
  155. "\"" . htmlspecialchars($displayname) . "\". After updating the new " .
  156. "file, you will have to place it in " .
  157. "<b>include/lang/" . htmlspecialchars($basename) . ".php</b>, " .
  158. "so Phorum can use it (backup your old file first of course!)."
  159. );
  160. }
  161. $notifies = 0;
  162. // Check for language strings that are missing.
  163. $missing = array();
  164. $count_missing = 0;
  165. foreach ($language_strings as $string => $data)
  166. {
  167. // This one is special.
  168. if ($string == 'TIME') continue;
  169. // Multi-dimentional string? That must be a module lang string
  170. // (cut at PHORUM->LANG->myarray-|>word).
  171. if (preg_match('/-$/', $string)) continue;
  172. if (! isset($CURRENT["DATA"]["LANG"][$string])) {
  173. array_push($missing, $string);
  174. $translation = urlencode("'" . addslashes($string) . "'");
  175. if (isset($DEFAULT["DATA"]["LANG"][$string])) {
  176. $translation = $DEFAULT["DATA"]["LANG"][$string];
  177. }
  178. $CURRENT_COPY["DATA"]["LANG"][$string] =
  179. urlencode("'***'. " . urldecode($translation));
  180. $count_missing++;
  181. if (! $generate_new) {
  182. $frm->addrow("MISSING ($count_missing)", $string);
  183. $notifies++;
  184. }
  185. } else {
  186. unset($CURRENT["DATA"]["LANG"][$string]);
  187. }
  188. }
  189. // Check for language strings that are deprecated.
  190. $deprecated = array();
  191. $count_deprecated = 0;
  192. if (! $generate_new)
  193. {
  194. foreach ($CURRENT["DATA"]["LANG"] as $string => $translation)
  195. {
  196. if ($string == 'TIME') continue; // This one is special.
  197. $count_deprecated++;
  198. $deprecated[$string] = true;
  199. // Only notify the deprecation if not already in deprecated state.
  200. if (! isset($CURRENT['STORE']['DEPRECATED'][$string])) {
  201. $frm->addrow("DEPRECATED ($count_deprecated)", htmlspecialchars($string));
  202. $notifies++;
  203. }
  204. }
  205. }
  206. $CURRENT_COPY['STORE']['DEPRECATED'] = $deprecated;
  207. // Restore our full current language data from the copy.
  208. $CURRENT = $CURRENT_COPY;
  209. // Copy values from our default language to the current language.
  210. $copyfields = array(
  211. 'long_date',
  212. 'long_date_time',
  213. 'short_date',
  214. 'short_date_time',
  215. 'locale',
  216. 'thous_sep',
  217. 'dec_sep',
  218. );
  219. foreach ($copyfields as $f) {
  220. if (! isset($CURRENT[$f])) {
  221. $CURRENT[$f] = $DEFAULT[$f];
  222. if (! $generate_new) {
  223. $frm->addrow("MISSING VARIABLE", "$f set to default " .
  224. htmlspecialchars(urldecode($DEFAULT[$f])));
  225. $notifies++;
  226. }
  227. }
  228. }
  229. // Copy default values beneath DATA to the current language.
  230. $datafields = array('CHARSET', 'HCHARSET', 'MAILENCODING', 'LANG_META');
  231. foreach ($datafields as $f) {
  232. if (! isset($CURRENT['DATA'][$f]) || $CURRENT['DATA'][$f] == '') {
  233. $CURRENT['DATA'][$f] = $DEFAULT['DATA'][$f];
  234. if (! $generate_new) {
  235. $frm->addrow("MISSING VARIABLE", "DATA->$f set to default " .
  236. htmlspecialchars(urldecode($DEFAULT['DATA'][$f])));
  237. $notifies++;
  238. }
  239. }
  240. }
  241. // Copy default values for timezone information to the current language.
  242. foreach ($DEFAULT['DATA']['LANG']['TIME'] as $key => $val) {
  243. if (! isset($CURRENT['DATA']['LANG']['TIME'][$key])) {
  244. $CURRENT['DATA']['LANG']['TIME'][$key] = $val;
  245. if (! $generate_new) {
  246. $dflt = htmlspecialchars(urldecode($DEFAULT['DATA']['LANG']['TIME'][$key]));
  247. $frm->addrow("MISSING TZINFO", "TZ $key set to default<br/>$dflt");
  248. $notifies++;
  249. }
  250. }
  251. }
  252. if ($generate_new) {
  253. $frm->addrow("COMPLETED", "A new language file has been generated for you");
  254. } elseif (! $notifies) {
  255. $frm->addrow("NONE", "There were no updates for the current \"$lang\" language file");
  256. }
  257. $frm->show();
  258. phorum_write_language_file($lang, $CURRENT);
  259. }
  260. function phorum_write_language_file($lang, $CURRENT)
  261. {
  262. // Sort array keys.
  263. ksort($CURRENT['DATA']['LANG']);
  264. ksort($CURRENT['STORE']['DEPRECATED']);
  265. $langfile =
  266. "<?php\n" .
  267. "\n" .
  268. $CURRENT['STORE']['keep_comment'] . "\n" .
  269. "\n" .
  270. "// ============================================================\n" .
  271. "// General settings\n" .
  272. "// ============================================================\n" .
  273. "\n" .
  274. "// The language name as it is presented in the interface.\n" .
  275. "\$language = " . urldecode($CURRENT['STORE']['language']) . ";\n" .
  276. "\n" .
  277. "// Uncomment this to hide this language from the user-select-box.\n" .
  278. ($CURRENT['STORE']['language_hide'] ? '' : '//') . "\$language_hide = 1;\n" .
  279. "\n" .
  280. "// Date formatting. Check the PHP-docs for the syntax of these\n" .
  281. "// entries (http://www.php.net/strftime). One tip: do not use\n" .
  282. "// %T for showing the time zone, as users can change their time zone.\n" .
  283. "\$PHORUM['long_date_time'] = " . urldecode($CURRENT['long_date_time']) . ";\n" .
  284. "\$PHORUM['short_date_time'] = " . urldecode($CURRENT['short_date_time']) . ";\n" .
  285. "\$PHORUM['long_date'] = " . urldecode($CURRENT['long_date']) . ";\n" .
  286. "\$PHORUM['short_date'] = " . urldecode($CURRENT['short_date']) . ";\n" .
  287. "\n" .
  288. "// The locale setting for enabling localized times/dates. Take a look\n" .
  289. "// at http://www.w3.org/WAI/ER/IG/ert/iso639.htm for the needed string.\n" .
  290. "\$PHORUM['locale'] = " . urldecode($CURRENT['locale']) . ";\n" .
  291. "\n" .
  292. "// Numeric separators used to format numbers.\n" .
  293. "\$PHORUM['thous_sep'] = " . urldecode($CURRENT['thous_sep']) . ";\n" .
  294. "\$PHORUM['dec_sep'] = " . urldecode($CURRENT['dec_sep']) . ";\n" .
  295. "\n" .
  296. "// The charset to use for displaying special characters.\n" .
  297. "\$PHORUM['DATA']['CHARSET'] = " . urldecode($CURRENT['DATA']['CHARSET']) . ";\n" .
  298. "\n" .
  299. "// The charset to use for htmlspecialchars() calls. PHP does\n" .
  300. "// not implement all available charsets, which might result in\n" .
  301. "// warning messages if an unsupported charset is used.\n" .
  302. "//\n" .
  303. "// See http://www.php.net/htmlspecialchars for info on charset\n" .
  304. "// compatibility. If the charset that you specified above is\n" .
  305. "// compatible with htmlspecialchars(), then you can leave this\n" .
  306. "// variable empty. Otherwise, specify a compatible character\n" .
  307. "// set (ISO-8859-1 is usually a good choice for this).\n" .
  308. "\$PHORUM['DATA']['HCHARSET'] = " . urldecode($CURRENT['DATA']['HCHARSET']) . ";\n" .
  309. "\n" .
  310. "// The encoding used for outgoing mail messages.\n" .
  311. "\$PHORUM['DATA']['MAILENCODING'] = " . urldecode($CURRENT['DATA']['MAILENCODING']) . ";\n" .
  312. "\n" .
  313. "// Some languages need additional meta tags to set encoding, etc.\n" .
  314. "\$PHORUM['DATA']['LANG_META'] = " . urldecode($CURRENT['DATA']['LANG_META']) . ";\n" .
  315. "\n" .
  316. "// ============================================================\n" .
  317. "// Language translation strings\n" .
  318. "// ============================================================\n" .
  319. "\n" .
  320. "\$PHORUM['DATA']['LANG'] = array(\n";
  321. // Add active language data to the array.
  322. foreach ($CURRENT['DATA']['LANG'] as $key => $val) {
  323. if ($key == 'TIME') continue;
  324. if (isset($CURRENT['STORE']['DEPRECATED'][$key])) continue;
  325. $langfile .= " '$key' => " . urldecode($val) . ",\n";
  326. }
  327. // Add deprecated language data to the array.
  328. if (count($CURRENT['STORE']['DEPRECATED']))
  329. {
  330. $langfile .=
  331. "\n" .
  332. " // ============================================================\n" .
  333. " // DEPRECATED:\n" .
  334. " // These are all language strings which are not used anymore.\n" .
  335. " // You might want to keep them to make this language file work\n" .
  336. " // for versions of Phorum prior to version " . PHORUM . "\n" .
  337. " // ============================================================\n" .
  338. "\n";
  339. foreach ($CURRENT['STORE']['DEPRECATED'] as $key => $dummy) {
  340. $langfile .= " '$key' => " . urldecode($CURRENT['DATA']['LANG'][$key]) . ",\n";
  341. }
  342. }
  343. $langfile .=
  344. ");\n" .
  345. "\n" .
  346. "// ============================================================\n" .
  347. "// Timezone description strings\n" .
  348. "// ============================================================\n" .
  349. "\n" .
  350. "\$PHORUM['DATA']['LANG']['TIME'] = array(\n";
  351. foreach ($CURRENT['DATA']['LANG']['TIME'] as $key => $val) {
  352. $pre = sprintf(" %6s", "'$key'");
  353. $langfile .= "$pre => " . urldecode($val) . ",\n";
  354. }
  355. $langfile .=
  356. ");\n" .
  357. "\n" .
  358. "?>\n";
  359. phorum_cache_put('updated_language', $lang, $langfile);
  360. }
  361. // ======================================================================
  362. // Parsing language files
  363. // ======================================================================
  364. // Helper function for phorum_get_language() to be able to do
  365. // some debugging output while getting all PHP tokens.
  366. function token_shift(&$tokens)
  367. {
  368. $token = array_shift($tokens);
  369. if (TOKEN_DEBUGGER > 1) {
  370. print '<div style="color: darkorange">';
  371. if (is_array($token)) {
  372. print "COMPLEX: " . token_name($token[0]) . " [" . htmlspecialchars($token[1]) . "]<br/>";
  373. } else {
  374. print "SIMPLE: [" . htmlspecialchars($token) . "]<br/>";
  375. }
  376. print '</div>';
  377. }
  378. return $token;
  379. }
  380. function token_skip_whitespace(&$tokens)
  381. {
  382. while ($tokens[0][0] == T_WHITESPACE) {
  383. array_shift($tokens);
  384. }
  385. }
  386. function token_get_string(&$tokens, $string = NULL)
  387. {
  388. $levels = 0;
  389. while (count($tokens))
  390. {
  391. $token = token_shift($tokens);
  392. if (is_array($token))
  393. {
  394. switch ($token[0])
  395. {
  396. case T_COMMENT:
  397. if (strstr($token[1], 'DEPRECATED')) {
  398. global $in_deprecated;
  399. $in_deprecated = true;
  400. }
  401. break;
  402. // Tokens which we handle in scalar token code.
  403. case T_DOUBLE_ARROW:
  404. $token = '=>';
  405. break;
  406. case T_CURLY_OPEN:
  407. $token = '{';
  408. break;
  409. case T_WHITESPACE:
  410. case T_ENCAPSED_AND_WHITESPACE:
  411. case T_CONSTANT_ENCAPSED_STRING:
  412. case T_NUM_STRING:
  413. case T_STRING:
  414. case T_ARRAY:
  415. case T_LNUMBER:
  416. case T_VARIABLE:
  417. case T_CHARACTER:
  418. $string .= $token[1];
  419. break;
  420. default:
  421. trigger_error(
  422. "Unhandled complex " . token_name($token[0]) .
  423. " token in token_get_string: " .
  424. htmlspecialchars($token[1]),
  425. E_USER_ERROR
  426. );
  427. break;
  428. }
  429. }
  430. if (is_scalar($token))
  431. {
  432. $oldlevels = $levels;
  433. // Keep track of nested brackets and curlies.
  434. if ($token == '(' || $token == '{' || $token == '[') {
  435. $levels++;
  436. } elseif ($levels && ($token == ')' || $token == '}' || $token == ']')) {
  437. $levels--;
  438. }
  439. if ($levels || $oldlevels) {
  440. $string .= $token;
  441. } else {
  442. // Tokens which end a string.
  443. if ($token == ';' || $token == '=' ||
  444. $token == '=>' || $token == ',' ||
  445. $token == ')') {
  446. $string = trim($string);
  447. return array($string, $token);
  448. } else {
  449. $string .= $token;
  450. }
  451. }
  452. }
  453. }
  454. }
  455. // This function retrieves all info from a language file, by directly
  456. // parsing its tokens. We can't simply load the language file, because
  457. // we have to extract any PHP code intact from it. By loading, all
  458. // PHP code would be interpreted.
  459. function phorum_get_language($lang)
  460. {
  461. $path = "./include/lang/$lang.php";
  462. $PHORUM = array();
  463. $DEPRECATED = array();
  464. $keep_comment = '';
  465. if (! file_exists($path)) trigger_error(
  466. "Cannot locate language module in $path", E_USER_ERROR
  467. );
  468. // Read the language file. Keep track of comments that
  469. // we want to keep (those starting with '##').
  470. $file = '';
  471. $fp = fopen($path, "r");
  472. if (! $fp) trigger_error(
  473. "Cannot read language file $path", E_USER_ERROR
  474. );
  475. while (($line = fgets($fp))) {
  476. $file .= $line;
  477. if (substr($line, 0, 2) == '##') {
  478. $keep_comment .= $line;
  479. }
  480. }
  481. fclose($fp);
  482. // Split the contents of the language file into PHP tokens.
  483. $tokens = token_get_all($file);
  484. // Parse the PHP tokens.
  485. while (count($tokens))
  486. {
  487. // Extract all variables. The rest is ignored.
  488. $token = token_shift($tokens);
  489. if (is_array($token))
  490. {
  491. if ($token[0] == T_VARIABLE) {
  492. list($varname,$endedby) = token_get_string($tokens, $token[1]);
  493. if ($endedby != '=') break; // We want only the assignments.
  494. // Peek at the following code, to see what type of variable we're
  495. // handling. Scalar or array.
  496. token_skip_whitespace($tokens);
  497. if ($tokens[0][0] == T_ARRAY)
  498. {
  499. global $in_deprecated;
  500. $in_deprecated = false;
  501. // Handle opening bracket for the array.
  502. token_shift($tokens);
  503. token_skip_whitespace($tokens);
  504. $token = token_shift($tokens);
  505. if ($token != '(') trigger_error(
  506. "$path: Expected array opening bracket for array " .
  507. htmlspecialchars($varname), E_USER_ERROR
  508. );
  509. while (count($tokens))
  510. {
  511. // Get key
  512. list($key, $endedby) = token_get_string($tokens);
  513. if ($endedby != '=>') trigger_error(
  514. "$path: Expected double arrow (=>) for key " .
  515. htmlspecialchars($key) . " in array " .
  516. htmlspecialchars($varname) . ", but got $endedby",
  517. E_USER_ERROR
  518. );
  519. // Get value
  520. list($val, $endedby) = token_get_string($tokens);
  521. if ($endedby != ',' && $endedby != ')') trigger_error(
  522. "$path: Expected ending comma or bracket for key " .
  523. htmlspecialchars($key) . " in array " .
  524. htmlspecialchars($varname) . ", but got $endedby",
  525. E_USER_ERROR
  526. );
  527. // Put the data in the environment.
  528. $fullvar = $varname . '[' . $key . ']';
  529. eval("$fullvar = '" . urlencode($val) . "';");
  530. // Keep track of data flagged deprecated.
  531. if ($in_deprecated) {
  532. eval("\$DEPRECATED[$key] = true;");
  533. }
  534. // Last key/value pair?
  535. if ($endedby == ')') break;
  536. token_skip_whitespace($tokens);
  537. if ($tokens[0] == ')') {
  538. array_shift($tokens);
  539. break;
  540. }
  541. }
  542. } else {
  543. list($varvalue,$endedby) = token_get_string($tokens);
  544. eval("$varname = '" . urlencode($varvalue) . "';");
  545. }
  546. }
  547. }
  548. }
  549. if ($keep_comment == '') {
  550. $keep_comment = <<<HELP
  551. ## For adding information to the start of this language file,
  552. ## you can use comments starting with "##". Those comments will
  553. ## be kept intact when a new language file is generated by the
  554. ## language file maintenance software.
  555. HELP;
  556. }
  557. // These aren't inside $PHORUM, but we put them there so we have
  558. // access to them later on.
  559. $PHORUM['STORE']['language_hide'] = $language_hide;
  560. $PHORUM['STORE']['language'] = $language;
  561. $PHORUM['STORE']['keep_comment'] = $keep_comment;
  562. $PHORUM['STORE']['DEPRECATED'] = $DEPRECATED;
  563. if (TOKEN_DEBUGGER){
  564. print_var($PHORUM);
  565. }
  566. return $PHORUM;
  567. }
  568. // ======================================================================
  569. // Extracting language strings from distribution files
  570. // ======================================================================
  571. function phorum_extract_language_strings()
  572. {
  573. global $extract_strings;
  574. $extract_strings = array();
  575. phorum_extract_language_strings_recurse(".");
  576. // For the announcement module, we keep the language strings in
  577. // the main langage file.
  578. phorum_extract_language_strings_recurse("./mods/announcements");
  579. return $extract_strings;
  580. }
  581. // This function processes directories recursively to search
  582. // for language strings.
  583. function phorum_extract_language_strings_recurse($path)
  584. {
  585. global $extract_strings;
  586. $dh = opendir($path);
  587. while (($f = readdir($dh)))
  588. {
  589. $file = "$path/$f";
  590. $ext = null;
  591. if (preg_match('/\.(\w+)$/', $f, $m)) $ext = $m[1];
  592. // Skip what we do not want to index.
  593. if ($f == "." || $f == "..") continue; // this and parent dir
  594. if ($f == ".svn") continue; // SVN data directories
  595. if ($f == "lang") continue; // language files
  596. if ($f == "mods") continue; // mods
  597. if ($f == "docs") continue; // documentation
  598. if ($f == "cache") continue; // the cache directory
  599. if (preg_match('/\.(php|tpl)$/', $file)) {
  600. $fp = fopen($file, "r");
  601. if (! $fp) trigger_error("Can't read file '$file'", E_USER_ERROR);
  602. while (($line = fgets($fp, 1024))) {
  603. $strings = array();
  604. if (preg_match_all('/LANG->([\w_-]+)/', $line, $m, PREG_SET_ORDER)) {
  605. $strings = array_merge($strings, $m);
  606. }
  607. if (preg_match_all('/(?:\$PHORUM|\$GLOBALS\[["\']PHORUM["\']\])\[["\']DATA["\']\]\[["\']LANG["\']\]\[["\']([^"\']+)["\']\]/', $line, $m, PREG_SET_ORDER)) {
  608. $strings = array_merge($strings, $m);
  609. }
  610. foreach ($strings as $string) {
  611. if (! isset($extract_strings[$string[1]])) {
  612. $extract_strings[$string[1]] = array('files'=>array());
  613. }
  614. $extract_strings[$string[1]]['files'][$file]++;
  615. $extract_strings[$string[1]]['source'][$string[0]]++;
  616. }
  617. }
  618. fclose($fp);
  619. }
  620. if (is_dir($file)) {
  621. phorum_extract_language_strings_recurse($file);
  622. }
  623. }
  624. closedir($dh);
  625. }
  626. ?>