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

/qa-include/qa-check-lang.php

https://github.com/begriffs/nomnom
PHP | 257 lines | 170 code | 64 blank | 23 comment | 20 complexity | 354f35f4f405fc24fcc95134d13f7b4b MD5 | raw file
  1. <?php
  2. /*
  3. Question2Answer (c) Gideon Greenspan
  4. http://www.question2answer.org/
  5. File: qa-include/qa-check-lang.php
  6. Version: See define()s at top of qa-include/qa-base.php
  7. Description: Development tool to see which language phrases are missing or unused
  8. This program is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU General Public License
  10. as published by the Free Software Foundation; either version 2
  11. of the License, or (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. More about this license: http://www.question2answer.org/license.php
  17. */
  18. define('QA_BASE_DIR', dirname(dirname(empty($_SERVER['SCRIPT_FILENAME']) ? __FILE__ : $_SERVER['SCRIPT_FILENAME'])).'/');
  19. require 'qa-base.php';
  20. require_once QA_INCLUDE_DIR.'qa-app-users.php';
  21. if (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN)
  22. qa_redirect('admin/general', null, qa_opt('site_url'));
  23. header('Content-type: text/html; charset=utf-8');
  24. ?>
  25. <HTML>
  26. <HEAD>
  27. <META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=utf-8"/>
  28. <TITLE>Question2Answer Language Check</TITLE>
  29. <STYLE>
  30. code {font-size:125%;}
  31. </STYLE>
  32. </HEAD>
  33. <BODY STYLE="font-family:arial; font-size:12px;">
  34. <?php
  35. function get_phrase_substitutions($phrase)
  36. {
  37. $substitutions=array();
  38. if (preg_match_all('/\^(([0-9]+)|([a-z_]+)|)/', $phrase, $matches))
  39. foreach ($matches[0] as $match)
  40. @$substitutions[$match]++;
  41. return $substitutions;
  42. }
  43. echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>';
  44. echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>';
  45. echo '<H1>Checking US English files in <code>qa-include</code>...</H1>';
  46. $includefiles=glob(QA_INCLUDE_DIR.'qa-*.php');
  47. $definite=array();
  48. $probable=array();
  49. $possible=array();
  50. $defined=array();
  51. $english=array();
  52. $backmap=array();
  53. $substitutions=array();
  54. output_start_includes();
  55. foreach ($includefiles as $includefile) {
  56. $contents=file_get_contents($includefile);
  57. preg_match_all('/qa_lang[a-z_]*\s*\(\s*[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
  58. foreach ($matches as $matchparts)
  59. if ($matchparts[2]=='date_month_') { // special case for month names
  60. for ($month=1; $month<=12; $month++)
  61. @$definite[$matchparts[1]][$matchparts[2].$month]++;
  62. } else
  63. @$definite[$matchparts[1]][$matchparts[2]]++;
  64. preg_match_all('/[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
  65. foreach ($matches as $matchparts)
  66. @$probable[$matchparts[1]][$matchparts[2]]++;
  67. if (preg_match('|/qa-include/qa-lang-([a-z]+)\.php$|', $includefile, $matches)) { // it's a lang file
  68. $prefix=$matches[1];
  69. output_reading_include($includefile);
  70. $phrases=@include $includefile;
  71. foreach ($phrases as $key => $value) {
  72. @$defined[$prefix][$key]++;
  73. $english[$prefix][$key]=$value;
  74. $backmap[$value][]=array('prefix' => $prefix, 'key' => $key);
  75. $substitutions[$prefix][$key]=get_phrase_substitutions($value);
  76. }
  77. } else { // it's a different file
  78. preg_match_all('/[\'\"\/]([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
  79. foreach ($matches as $matchparts)
  80. @$possible[$matchparts[1]]++;
  81. }
  82. }
  83. output_finish_includes();
  84. foreach ($definite as $key => $valuecount)
  85. foreach ($valuecount as $value => $count)
  86. if (!@$defined[$key][$value])
  87. output_lang_issue($key, $value, 'used by '.$count.' file/s but not defined');
  88. foreach ($defined as $key => $valuecount)
  89. foreach ($valuecount as $value => $count)
  90. if ( (!@$definite[$key][$value]) && (!@$probable[$key][$value]) && (!@$possible[$value]) )
  91. output_lang_issue($key, $value, 'defined but apparently not used');
  92. foreach ($backmap as $phrase => $where)
  93. if (count($where)>1)
  94. foreach ($where as $onewhere)
  95. output_lang_issue($onewhere['prefix'], $onewhere['key'], 'contains the shared phrase "'.$phrase.'"', false);
  96. require_once QA_INCLUDE_DIR.'qa-app-admin.php';
  97. $languages=qa_admin_language_options();
  98. unset($languages['']);
  99. foreach ($languages as $code => $language) {
  100. echo '<H1>Checking '.$language.' files in <code>qa-lang/'.$code.'</code>...</H1>';
  101. $langdefined=array();
  102. $langdifferent=array();
  103. $langsubstitutions=array();
  104. $langincludefiles=glob(QA_LANG_DIR.$code.'/qa-*.php');
  105. $langnewphrases=array();
  106. output_start_includes();
  107. foreach ($langincludefiles as $langincludefile)
  108. if (preg_match('/qa-lang-([a-z]+)\.php$/', $langincludefile, $matches)) { // it's a lang file
  109. $prefix=$matches[1];
  110. output_reading_include($langincludefile);
  111. $phrases=@include $langincludefile;
  112. foreach ($phrases as $key => $value) {
  113. @$langdefined[$prefix][$key]++;
  114. $langdifferent[$prefix][$key]=($value!=@$english[$prefix][$key]);
  115. $langsubstitutions[$prefix][$key]=get_phrase_substitutions($value);
  116. }
  117. }
  118. output_finish_includes();
  119. foreach ($langdefined as $key => $valuecount)
  120. foreach ($valuecount as $value => $count) {
  121. if (!@$defined[$key][$value])
  122. output_lang_issue($key, $value, 'defined but not in US English files');
  123. elseif (!$langdifferent[$key][$value])
  124. output_lang_issue($key, $value, 'identical to US English files', false);
  125. else
  126. foreach ($substitutions[$key][$value] as $substitution => $subcount)
  127. if (!@$langsubstitutions[$key][$value][$substitution])
  128. output_lang_issue($key, $value, 'omitted the substitution '.$substitution);
  129. elseif ($subcount > @$langsubstitutions[$key][$value][$substitution])
  130. output_lang_issue($key, $value, 'has fewer of the substitution '.$substitution);
  131. }
  132. foreach ($defined as $key => $valuecount) {
  133. $showaserror=!(($key=='admin') || ($key=='options') || ($code=='en-GB'));
  134. if (@$langdefined[$key]) {
  135. if (count($langdefined[$key]) < (count($valuecount)/2)) { // only a few phrases defined
  136. output_lang_issue($key, null, 'few translations provided so will use US English defaults', $showaserror);
  137. } else
  138. foreach ($valuecount as $value => $count)
  139. if (!@$langdefined[$key][$value]) {
  140. output_lang_issue($key, $value, 'undefined so will use US English defaults', $showaserror);
  141. $langnewphrases[$key][$value]=$english[$key][$value];
  142. }
  143. } else
  144. output_lang_issue($key, null, 'no translations provided so will use US English defaults', $showaserror);
  145. }
  146. foreach ($langnewphrases as $prefix => $phrases) {
  147. echo '<H2>'.$language.' phrases to add to <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code>:</H2>';
  148. echo 'Copy and paste this into the middle of <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code> then translate the right-hand side after the <code>=></code> symbol.';
  149. echo '<PRE>';
  150. foreach ($phrases as $key => $value)
  151. echo '<SPAN STYLE="font-size:25%;">'."\t\t</SPAN>'".$key."' => \"".strtr($value, array('\\' => '\\\\', '"' => '\"', '$' => '\$', "\n" => '\n', "\t" => '\t'))."\",\n";
  152. echo '</PRE>';
  153. }
  154. }
  155. function output_lang_issue($prefix, $key, $issue, $error=true)
  156. {
  157. echo '<font color="'.($error ? '#cc0000' : '#cc9999').'"><code>';
  158. echo 'qa-lang-<B>'.qa_html($prefix).'</B>.php:';
  159. if (strlen($key))
  160. echo "'<B>".qa_html($key)."</B>'";
  161. echo '</code></font> &nbsp; '.qa_html($issue).'<BR>';
  162. }
  163. function output_start_includes()
  164. {
  165. global $oneread;
  166. $oneread=false;
  167. echo '<P STYLE="font-size:80%; color:#999;">Reading: ';
  168. }
  169. function output_reading_include($file)
  170. {
  171. global $oneread;
  172. echo ($oneread ? ', ' : '').htmlspecialchars(basename($file));
  173. flush();
  174. $oneread=true;
  175. }
  176. function output_finish_includes()
  177. {
  178. echo '</P>';
  179. }
  180. echo '<H1>Finished scanning for problems!</H1>';
  181. ?>
  182. </BODY>
  183. </HTML>