PageRenderTime 226ms CodeModel.GetById 101ms app.highlight 14ms RepoModel.GetById 107ms app.codeStats 0ms

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

https://github.com/aromatix/question2answer
PHP | 257 lines | 170 code | 64 blank | 23 comment | 20 complexity | 759ac9e7cbe956bda68fb5b81c1bba88 MD5 | raw file
  1<?php
  2
  3/*
  4	Question2Answer by Gideon Greenspan and contributors
  5
  6	http://www.question2answer.org/
  7
  8	
  9	File: qa-include/qa-check-lang.php
 10	Version: See define()s at top of qa-include/qa-base.php
 11	Description: Development tool to see which language phrases are missing or unused
 12
 13
 14	This program is free software; you can redistribute it and/or
 15	modify it under the terms of the GNU General Public License
 16	as published by the Free Software Foundation; either version 2
 17	of the License, or (at your option) any later version.
 18	
 19	This program is distributed in the hope that it will be useful,
 20	but WITHOUT ANY WARRANTY; without even the implied warranty of
 21	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 22	GNU General Public License for more details.
 23
 24	More about this license: http://www.question2answer.org/license.php
 25*/
 26
 27	define('QA_BASE_DIR', dirname(dirname(empty($_SERVER['SCRIPT_FILENAME']) ? __FILE__ : $_SERVER['SCRIPT_FILENAME'])).'/');
 28
 29	require 'qa-base.php';
 30	require_once QA_INCLUDE_DIR.'qa-app-users.php';
 31	
 32	if (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN)
 33		qa_redirect('admin/general', null, qa_opt('site_url'));
 34	
 35	header('Content-type: text/html; charset=utf-8');
 36?>
 37<html>
 38	<head>
 39		<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
 40		<title>Question2Answer Language Check</title>
 41		<style>
 42			code {font-size:125%;}
 43		</style>
 44	</head>
 45	<body style="font-family:arial; font-size:12px;">
 46<?php
 47
 48	function get_phrase_substitutions($phrase)
 49	{
 50		$substitutions=array();
 51
 52		if (preg_match_all('/\^(([0-9]+)|([a-z_]+)|)/', $phrase, $matches))
 53			foreach ($matches[0] as $match)
 54				@$substitutions[$match]++;
 55				
 56		return $substitutions;
 57	}
 58	
 59	echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>';
 60	echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>';
 61	
 62	echo '<h1>Checking US English files in <code>qa-include</code>...</h1>';
 63	
 64	$includefiles=array_merge(glob(QA_INCLUDE_DIR.'qa-*.php'), glob(QA_PLUGIN_DIR.'*/qa-*.php'));
 65	
 66	$definite=array();
 67	$probable=array();
 68	$possible=array();
 69	$defined=array();
 70	$english=array();
 71	$backmap=array();
 72	$substitutions=array();
 73	
 74	output_start_includes();
 75	
 76	foreach ($includefiles as $includefile) {
 77		$contents=file_get_contents($includefile);
 78		
 79		preg_match_all('/qa_lang[a-z_]*\s*\(\s*[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
 80		
 81		foreach ($matches as $matchparts)
 82			if ($matchparts[2]=='date_month_') { // special case for month names
 83				for ($month=1; $month<=12; $month++)
 84					@$definite[$matchparts[1]][$matchparts[2].$month]++;
 85
 86			} else
 87				@$definite[$matchparts[1]][$matchparts[2]]++;
 88			
 89		preg_match_all('/[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
 90
 91		foreach ($matches as $matchparts)
 92			@$probable[$matchparts[1]][$matchparts[2]]++;
 93
 94		if (preg_match('|/qa-include/qa-lang-([a-z]+)\.php$|', $includefile, $matches)) { // it's a lang file
 95			$prefix=$matches[1];
 96		
 97			output_reading_include($includefile);
 98			$phrases=@include $includefile;
 99			
100			foreach ($phrases as $key => $value) {
101				@$defined[$prefix][$key]++;
102				$english[$prefix][$key]=$value;
103				$backmap[$value][]=array('prefix' => $prefix, 'key' => $key);
104				$substitutions[$prefix][$key]=get_phrase_substitutions($value);
105			}
106
107		} else { // it's a different file
108			preg_match_all('/[\'\"\/]([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
109			
110			foreach ($matches as $matchparts)
111				@$possible[$matchparts[1]]++;
112		}
113	}
114	
115	output_finish_includes();
116	
117	foreach ($definite as $key => $valuecount)
118		foreach ($valuecount as $value => $count)
119			if (!@$defined[$key][$value])
120				output_lang_issue($key, $value, 'used by '.$count.' file/s but not defined');
121				
122	foreach ($defined as $key => $valuecount)
123		foreach ($valuecount as $value => $count)
124			if ( (!@$definite[$key][$value]) && (!@$probable[$key][$value]) && (!@$possible[$value]) )
125				output_lang_issue($key, $value, 'defined but apparently not used');
126	
127	foreach ($backmap as $phrase => $where)
128		if (count($where)>1)
129			foreach ($where as $onewhere)
130				output_lang_issue($onewhere['prefix'], $onewhere['key'], 'contains the shared phrase "'.$phrase.'"', false);
131	
132	require_once QA_INCLUDE_DIR.'qa-app-admin.php';
133	
134	$languages=qa_admin_language_options();
135	unset($languages['']);
136	
137	foreach ($languages as $code => $language) {
138		echo '<h1>Checking '.$language.' files in <code>qa-lang/'.$code.'</code>...</h1>';
139		
140		$langdefined=array();
141		$langdifferent=array();
142		$langsubstitutions=array();
143		$langincludefiles=glob(QA_LANG_DIR.$code.'/qa-*.php');
144		$langnewphrases=array();
145		
146		output_start_includes();
147		
148		foreach ($langincludefiles as $langincludefile)
149			if (preg_match('/qa-lang-([a-z]+)\.php$/', $langincludefile, $matches)) { // it's a lang file
150				$prefix=$matches[1];
151
152				output_reading_include($langincludefile);
153				$phrases=@include $langincludefile;
154				
155				foreach ($phrases as $key => $value) {
156					@$langdefined[$prefix][$key]++;
157					$langdifferent[$prefix][$key]=($value!=@$english[$prefix][$key]);
158					$langsubstitutions[$prefix][$key]=get_phrase_substitutions($value);
159				}
160			}
161			
162		output_finish_includes();
163			
164		foreach ($langdefined as $key => $valuecount)
165			foreach ($valuecount as $value => $count) {
166				if (!@$defined[$key][$value])
167					output_lang_issue($key, $value, 'defined but not in US English files');
168				
169				elseif (!$langdifferent[$key][$value])
170					output_lang_issue($key, $value, 'identical to US English files', false);
171				
172				else
173					foreach ($substitutions[$key][$value] as $substitution => $subcount)
174						if (!@$langsubstitutions[$key][$value][$substitution])
175							output_lang_issue($key, $value, 'omitted the substitution '.$substitution);
176						elseif ($subcount > @$langsubstitutions[$key][$value][$substitution])
177							output_lang_issue($key, $value, 'has fewer of the substitution '.$substitution);
178			}
179					
180		foreach ($defined as $key => $valuecount) {
181			$showaserror=!(($key=='admin') || ($key=='options') || ($code=='en-GB'));
182			
183			if (@$langdefined[$key]) {
184				if (count($langdefined[$key]) < (count($valuecount)/2)) { // only a few phrases defined
185					output_lang_issue($key, null, 'few translations provided so will use US English defaults', $showaserror);
186
187				} else
188					foreach ($valuecount as $value => $count)
189						if (!@$langdefined[$key][$value]) {
190							output_lang_issue($key, $value, 'undefined so will use US English defaults', $showaserror);
191							$langnewphrases[$key][$value]=$english[$key][$value];
192						}
193			} else
194				output_lang_issue($key, null, 'no translations provided so will use US English defaults', $showaserror);
195		}
196		
197		foreach ($langnewphrases as $prefix => $phrases) {
198			echo '<h2>'.$language.' phrases to add to <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code>:</h2>';
199			
200			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.';
201			
202			echo '<pre>';
203			
204			foreach ($phrases as $key => $value)
205				echo '<span style="font-size:25%;">'."\t\t</span>'".$key."' => \"".strtr($value, array('\\' => '\\\\', '"' => '\"', '$' => '\$', "\n" => '\n', "\t" => '\t'))."\",\n";
206				
207			echo '</pre>';
208		}
209	}
210
211	
212	function output_lang_issue($prefix, $key, $issue, $error=true)
213	{
214		echo '<font color="'.($error ? '#cc0000' : '#cc9999').'"><code>';
215
216		echo 'qa-lang-<b>'.qa_html($prefix).'</b>.php:';
217
218		if (strlen($key))
219			echo "'<b>".qa_html($key)."</b>'";
220		
221		echo '</code></font> &nbsp; '.qa_html($issue).'<br>';
222	}
223
224
225	function output_start_includes()
226	{
227		global $oneread;
228		
229		$oneread=false;
230		
231		echo '<p style="font-size:80%; color:#999;">Reading: ';
232	}
233
234	
235	function output_reading_include($file)
236	{
237		global $oneread;
238		
239		echo ($oneread ? ', ' : '').htmlspecialchars(basename($file));
240		flush();
241		
242		$oneread=true;
243	}
244
245	
246	function output_finish_includes()
247	{
248		echo '</p>';
249	}
250
251	
252	echo '<h1>Finished scanning for problems!</h1>';
253
254?>
255
256	</body>
257</html>