1
|
|
|
<?php |
2
|
|
|
/* PROJECT: ReactOS Translation Tool |
3
|
|
|
* LICENSE: GPL |
4
|
|
|
* AUTHORS: Adam Stachowicz <[email protected]> |
5
|
|
|
* AUTHOR URL: http://it-maniak.pl/ |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
include_once 'header.php'; |
9
|
|
|
?> |
10
|
|
|
|
11
|
|
|
<h1>Search missing translation strings</h1> |
12
|
|
|
|
13
|
|
|
<div id="body"> |
14
|
|
|
<center> |
15
|
|
|
<form method="GET" class="form-horizontal"> |
16
|
|
|
<fieldset> |
17
|
|
|
<legend>Please type your <a href="https://beta.wikiversity.org/wiki/List_of_ISO_639-1_codes">language code in ISO 639-1</a>. For example: pl for Polish, de for German</legend> |
18
|
|
|
<div class="form-group"> |
19
|
|
|
<label class="col-md-4 control-label" for="lang">Language code:</label> |
20
|
|
|
<div class="col-md-4"> |
21
|
|
|
<input type="text" value="<?php echo isset($_SESSION['lang']) ? $_SESSION['lang'] : '' ?>" id="lang" name="lang" class="form-control input-md" required="required" autofocus="autofocus" pattern="[A-Za-z]{2}" title="Two letter language code"/> |
22
|
|
|
</div> |
23
|
|
|
</div> |
24
|
|
|
<div class="form-group"> |
25
|
|
|
<label class="col-md-4 control-label" for="dir">Directories:</label> |
26
|
|
|
<div class="col-md-4"> |
27
|
|
|
<select id="dir" name="dir" class="form-control"> |
28
|
|
|
<option value="1">base, boot</option> |
29
|
|
|
<option value="2" <?php if (isset($_GET['dir']) && $_GET['dir'] == '2') { |
30
|
|
|
echo 'selected'; |
31
|
|
|
}?>>dll</option> |
32
|
|
|
<option value="3" <?php if (isset($_GET['dir']) && $_GET['dir'] == '3') { |
33
|
|
|
echo 'selected'; |
34
|
|
|
}?>>media, subsystems, win32ss</option> |
35
|
|
|
<option value="100" <?php if (isset($_GET['dir']) && $_GET['dir'] == '100') { |
36
|
|
|
echo 'selected'; |
37
|
|
|
}?>>All ReactOS Source dir</option> |
38
|
|
|
</select> |
39
|
|
|
</div> |
40
|
|
|
</div> |
41
|
|
|
<div class="form-group"> |
42
|
|
|
<button type="submit" class="btn btn-primary">Search</button> |
43
|
|
|
</div> |
44
|
|
|
</fieldset> |
45
|
|
|
</form> |
46
|
|
|
</center> |
47
|
|
|
<br> |
48
|
|
|
|
49
|
|
|
<?php |
50
|
|
|
if (isset($_GET['lang']) && !empty($_GET['lang']) && isset($_GET['dir']) && is_numeric($_GET['dir'])) { |
51
|
|
|
$it = new AppendIterator(); |
52
|
|
|
|
53
|
|
|
// Switch for directories |
54
|
|
|
switch ($_GET['dir']) { |
55
|
|
|
case '1': |
56
|
|
|
$directories = [ |
57
|
|
|
new RecursiveDirectoryIterator($ROSDir.'base/applications'), |
58
|
|
|
new RecursiveDirectoryIterator($ROSDir.'base/setup'), |
59
|
|
|
new RecursiveDirectoryIterator($ROSDir.'base/shell'), |
60
|
|
|
new RecursiveDirectoryIterator($ROSDir.'base/system'), |
61
|
|
|
new RecursiveDirectoryIterator($ROSDir.'boot/freeldr/fdebug') |
62
|
|
|
]; |
63
|
|
|
break; |
64
|
|
|
|
65
|
|
|
case '2': |
66
|
|
|
$directories = [ |
67
|
|
|
new RecursiveDirectoryIterator($ROSDir.'dll/cpl'), |
68
|
|
|
new RecursiveDirectoryIterator($ROSDir.'dll/shellext'), |
69
|
|
|
new RecursiveDirectoryIterator($ROSDir.'dll/win32') |
70
|
|
|
]; |
71
|
|
|
break; |
72
|
|
|
|
73
|
|
|
case '3': |
74
|
|
|
$directories = [ |
75
|
|
|
new RecursiveDirectoryIterator($ROSDir.'media/themes'), |
76
|
|
|
new RecursiveDirectoryIterator($ROSDir.'subsystems/mvdm/ntvdm'), |
77
|
|
|
new RecursiveDirectoryIterator($ROSDir.'win32ss/user') |
78
|
|
|
]; |
79
|
|
|
break; |
80
|
|
|
|
81
|
|
|
case '100': |
82
|
|
|
$directories = [ |
83
|
|
|
new RecursiveDirectoryIterator($ROSDir) |
84
|
|
|
]; |
85
|
|
|
break; |
86
|
|
|
|
87
|
|
|
default: |
88
|
|
|
echo 'Something is wrong! Please try again.'; |
89
|
|
|
exit; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
foreach ($directories as $directory) { |
93
|
|
|
$it->append(new RecursiveIteratorIterator($directory)); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
function diff_versions($leftContent, $rightContent) |
97
|
|
|
{ |
98
|
|
|
$leftVersion = $rightVersion = null; |
|
|
|
|
99
|
|
|
|
100
|
|
|
// FIXME: Search multi-line with ""some text"" |
101
|
|
|
$pattern = '/^(?!FONT|\\s*\\*|\\#\\include|\\s*\\ICON)[^"\\n]*"\\K(?!\\s*(?:"|\\n))([^"]+)/m'; |
102
|
|
|
|
103
|
|
|
if (preg_match_all($pattern, $leftContent, $matches) <= 0) { |
104
|
|
|
throw new Exception('Left content has no version line.'); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
$leftVersion = $matches[1]; |
108
|
|
|
|
109
|
|
|
if (preg_match_all($pattern, $rightContent, $matches) <= 0) { |
110
|
|
|
throw new Exception('Right content has no version line.'); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
$rightVersion = $matches[1]; |
114
|
|
|
|
115
|
|
|
return [ |
116
|
|
|
'diff' => array_intersect($leftVersion, $rightVersion), |
117
|
|
|
'leftVersion' => $leftVersion, |
118
|
|
|
'rightVersion' => $rightVersion, |
119
|
|
|
]; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
function exceptions_error_handler($severity, $message, $filename, $lineno) |
123
|
|
|
{ |
124
|
|
|
if (error_reporting() == 0) { |
125
|
|
|
return; |
126
|
|
|
} |
127
|
|
|
if (error_reporting() & $severity) { |
128
|
|
|
throw new ErrorException($message, 0, $severity, $filename, $lineno); |
129
|
|
|
} |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
set_error_handler('exceptions_error_handler'); |
133
|
|
|
|
134
|
|
|
$regex = new RegexIterator($it, '/^.+'.$langDir.'.+('.$originLang.')\.'.$fileExt.'$/i', RecursiveRegexIterator::GET_MATCH); |
135
|
|
|
|
136
|
|
|
$missing = $allStrings = 0; |
137
|
|
|
|
138
|
|
|
$lang = htmlspecialchars($_GET['lang']); |
139
|
|
|
// Search for eg. PL,Pl,pl |
140
|
|
|
$fileSearch = strtoupper($lang).','.ucfirst($lang).','.strtolower($lang); |
141
|
|
|
|
142
|
|
|
// ReactOS and Wine Strings - array |
143
|
|
|
$ignoredROSStrings = file($ROSSpellFilename, FILE_IGNORE_NEW_LINES); |
144
|
|
|
$ignoredWineStrings = file($wineSpellFilename, FILE_IGNORE_NEW_LINES); |
145
|
|
|
|
146
|
|
|
$regex->rewind(); |
147
|
|
|
while ($regex->valid()) { |
148
|
|
|
if (!$regex->isDot()) { |
149
|
|
|
$file = glob($regex->getPathInfo().'/*{'.$fileSearch.'}*.'.$fileExt, GLOB_BRACE); |
150
|
|
|
|
151
|
|
|
$isFile = array_filter($file); |
152
|
|
|
|
153
|
|
|
if (empty($isFile)) { |
154
|
|
|
echo '<b>No translation</b> for path '.$regex->getPathInfo().'<hr>'; |
155
|
|
|
} else { |
156
|
|
|
$fileContent1 = file_get_contents($regex->key()); |
157
|
|
|
$fileContent2 = file_get_contents($file[0]); |
158
|
|
|
|
159
|
|
|
$array = diff_versions($fileContent1, $fileContent2); |
160
|
|
|
|
161
|
|
|
if ($array['diff']) { |
162
|
|
|
echo $regex->getPathInfo().'<br><br>'; |
163
|
|
|
|
164
|
|
|
$currentMissing = $missing; |
165
|
|
|
|
166
|
|
|
foreach ($array['leftVersion'] as $index => $english) { |
167
|
|
|
// Catch offset error |
168
|
|
|
try { |
169
|
|
|
// Check if this same and ignore some words |
170
|
|
|
if ($english === $array['rightVersion'][$index] && !in_array($english, $ignoredROSStrings) && !in_array($english, $ignoredWineStrings)) { |
171
|
|
|
echo '<b>Missing translation:</b> '.htmlspecialchars($english).'<br>'; |
172
|
|
|
$missing++; |
173
|
|
|
} |
174
|
|
|
$allStrings++; |
175
|
|
|
} catch (Exception $e) { |
176
|
|
|
echo 'Missing stuff in your language<br>'; |
177
|
|
|
$allStrings++; |
178
|
|
|
$missing++; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
if ($currentMissing == $missing) { |
182
|
|
|
echo 'Seems <b>OK :)</b> Some strings was ignored by ReactOS and Wine spell files.<br>'; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
echo '<hr>'; |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
$regex->next(); |
190
|
|
|
} |
191
|
|
|
echo "<h3>All strings for english: $allStrings</h3>"; |
192
|
|
|
echo "<h3>Missing translations for your language ($lang): $missing</h3>"; |
193
|
|
|
|
194
|
|
|
// Rounded percent |
195
|
|
|
$percent = round((($allStrings - $missing) / $allStrings) * 100, 2); |
196
|
|
|
echo "<h3>Language $lang translated in $percent%</h3>"; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
include_once 'footer.php'; |
200
|
|
|
|
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.