#!/usr/bin/php -q | | Gabor Hojtsy | | Mark Kronsbein | | Jan Fabry +----------------------------------------------------------------------+ $Id: revcheck.php 308406 2011-02-16 22:27:57Z yannick $ */ if ($argc < 2 || $argc > 4) { ?> Check the revision of translated files against the actual english xml files, and print statistics Usage: [] [--show-uptodate] must be a valid language code used in the repository If you specify , the script only checks the files maintained by the person you add here If you specify --show-uptodate option, the script will also show uptodate files in the common file list Read more about Revision comments and related functionality in the PHP Documentation Howto: http://php.net/dochowto "act", REV_NOREV => "norev", REV_CRITICAL => "crit", REV_OLD => "old", REV_NOTAG => "wip", REV_NOTRANS => "wip", REV_CREDIT => "wip", REV_WIP => "wip", ); function init_revisions() { global $CSS; return array_fill_keys(array_keys($CSS), 0); } function init_files_by_maint($persons) { $result = array(); foreach($persons as $item) { $result[$item['name']] = init_revisions(); } return $result; } $file_sizes_by_mark = $files_by_mark = init_revisions(); // Initializing variables from parameters $LANG = $argv[1]; $MAINT = ""; $SHOW_UPTODATE = FALSE; if ($argc == 3) { if ($argv[2] == '--show-uptodate') { $SHOW_UPTODATE = TRUE; } else { $MAINT = $argv[2]; } } elseif ($argc == 4) { $MAINT = $argv[2]; $SHOW_UPTODATE = ($argv[3] == '--show-uptodate'); } $DOCDIR=getenv("SCI")."/"; chdir($DOCDIR); $DOCDIR=getcwd()."/"; if (!is_dir($DOCDIR)) { echo "Could not find $DOCDIR\n"; die(); } // ========================================================================= // Functions to get revision info and credits from a file // ========================================================================= function get_last_commit_from_git($file) { global $gitOptions; $cmd="cd `dirname $file` > /dev/null; git log $gitOptions $file|head -1|cut -d' ' -f2; cd - > /dev/null"; $lastcommit=exec($cmd); if (!$lastcommit) { die("Error: Could not retrieve the last commit from git: ".$cmd); } return $lastcommit; } function get_last_revision_from_git($file) { global $DOCDIR; $commit=get_last_commit_from_git($file); if (!$commit) { die("Error: empty commit"); } $tempFile="/tmp/git_rev-list.txt"; if (!is_file($tempFile)) { exec("cd `dirname $DOCDIR` > /dev/null; git rev-list --reverse HEAD > $tempFile; cd - > /dev/null"); } return exec("cd `dirname $file` > /dev/null; grep -n $commit $tempFile | cut -d: -f1; cd - > /dev/null"); } function get_author_from_git($file) { global $gitOptions; return ucwords(strtolower(exec("cd `dirname $file` > /dev/null; git log $gitOptions $file|head -2|grep 'Author:'|sed -e 's|Author: \(.*\) <.*|\\1|g'; cd - > /dev/null"))); } // Grabs the revision tag and stores credits from the file given function get_tags($file, $val = "en-rev") { // Read the first 500 chars. The comment should be at // the begining of the file $fp = @fopen($file, "r") or die ("Unable to read $file."); $line = fread($fp, 500); fclose($fp); // Return if this was needed (it should be there) if ($val == "en-rev") { return get_last_revision_from_git($file); // preg_match("//", $line, $match); // return $match[1]; } // Handle credits (only if no maintainer is specified) if ($val == "\\S*") { global $files_by_maint; // Find credits info, let more credits then one, // using commas as list separator if (preg_match("''U", $line, $match_credit)) { // Explode with commas a separators $credits = explode(",", $match_credit[1]); // Store all elements foreach ($credits as $num => $credit) { $files_by_maint[trim($credit)][REV_CREDIT]++; } } } global $LANG; // No match before the preg $match = array(); $match[0]=""; $match[1]=get_last_revision_from_git($file);//str_replace($LANG,"en_US",$file)); $match[2]=get_author_from_git($file); $match[3]=""; return $match; // Check for the translations "revision tag" preg_match ("//U", $line, $match ); // The tag with revision number is not found so search // for n/a revision comment (comment where revision is not known) if (count($match) == 0) { preg_match ("''U", $line, $match ); } // Return with found revision info (number, maint, status) return $match; } // get_tags() function end function detect_date_from_git($file) { global $gitOptions; $en_date=strtotime(trim(exec("cd `dirname $file` > /dev/null; git log $gitOptions --date=iso $file|grep Date:|sed -e \"s|Date:||g\"; cd - > /dev/null"))); return $en_date; } // ========================================================================= // Functions to check file status in translated directory, and store info // ========================================================================= // Checks a file, and gather status info function get_file_status($file) { // The information is contained in these global arrays and vars global $DOCDIR, $LANG, $MAINT, $SHOW_UPTODATE, $files_by_mark, $files_by_maint; global $file_sizes_by_mark; global $missing_files, $missing_tags, $using_rev; // Transform english file name to translated file name $trans_file = str_replace("en_US", $LANG, $file); // If we cannot find the file, we push it into the missing files list if (!@file_exists($trans_file)) { $files_by_mark[REV_NOTRANS]++; $trans_name = substr($trans_file, strlen($DOCDIR)); $size = intval(filesize($file)/1024); $missing_files[substr($file, strlen($DOCDIR))] = array( $size ); $file_sizes_by_mark[REV_NOTRANS] += $size; // compute en-tags just if they're needed in the WIP-Table if($using_rev) { $missing_files[$trans_name][] = get_tags($file); } return FALSE; } // No specific maintainer, check for a revision tag if (empty($MAINT)) { $trans_tag = get_tags($trans_file, "\\S*"); } // If we need to check for a specific translator else { // Get translated files tag, with maintainer $trans_tag = get_tags($trans_file, $MAINT); // If this is a file belonging to another // maintainer, than we would not like to // deal with it anymore if (count($trans_tag) == 0) { $trans_tag = get_tags($trans_file, "\\S*"); // We found a tag for another maintainer if (count($trans_tag) > 0) { return FALSE; } } } // Compute sizes and diffs $en_size = intval(filesize($file) / 1024); $trans_size = intval(mb_strlen(file_get_contents($trans_file), 'UTF-8') / 1024); $size_diff = intval($en_size) - intval($trans_size); // If we found no revision tag, then collect this // file in the missing tags list if (count($trans_tag) == 0) { $files_by_mark[REV_NOTAG]++; $file_sizes_by_mark[REV_NOTAG] += $en_size; $missing_tags[] = array(substr($trans_file, strlen($DOCDIR)), $en_size, $trans_size, $size_diff); return FALSE; } // Distribute values in separate vars for further processing list(, $this_rev, $this_maint, $this_status) = $trans_tag; // Get English file revision $en_rev = get_tags($file); // If we have a numeric revision number (not n/a), compute rev. diff if (is_numeric($this_rev)) { $rev_diff = intval($en_rev) - intval($this_rev); $trans_rev = $this_rev; $en_rev = $en_rev; $en_commit = get_last_commit_from_git($file); $trans_commit = get_last_commit_from_git($trans_file); } else { // If we have no numeric revision, make all revision // columns hold the rev from the translated file $rev_diff = $trans_rev = $this_rev; $en_rev = $en_rev; } // Compute times and diffs // $en_date = intval((time() - filemtime($file)) / 86400); $en_date=detect_date_from_git($file); if (!$en_date) { die("Could not detect date"); } $en_date = intval((time() - $en_date) / 86400); $trans_date=detect_date_from_git($trans_file); $trans_date = intval((time() - $trans_date) / 86400); $date_diff = $en_date - $trans_date; // If the file is up-to-date if ($rev_diff === 0 && trim($this_status) === "ready") { $status_mark = REV_UPTODATE; } elseif ($en_rev < $this_rev && $date_diff > 0) { $status_mark = REV_UPTODATE; } // Or make decision on file category by revision, date and size elseif ($rev_diff >= ALERT_REV || $size_diff >= ALERT_SIZE || $date_diff <= ALERT_DATE) { $status_mark = REV_CRITICAL; } elseif ($rev_diff === "n/a") { $status_mark = REV_NOREV; } elseif ($rev_diff === 0) { $status_mark = REV_WIP; } else { $status_mark = REV_OLD; } // Store files by status, and by maintainer too $files_by_mark[$status_mark]++; if (!isset($files_by_maint[$this_maint])) { $files_by_maint[$this_maint]=Array(); } if (!isset($files_by_maint[$this_maint][$status_mark])) { $files_by_maint[$this_maint][$status_mark]=Array(); } $files_by_maint[$this_maint][$status_mark]++; $file_sizes_by_mark[$status_mark] += $en_size; if (REV_UPTODATE === $status_mark && !$SHOW_UPTODATE) { return FALSE; } return array( "full_name" => $file, "short_name" => basename($trans_file), "revision" => array($en_rev, $trans_rev, $rev_diff), "commit" => array($en_commit, $trans_commit), "size" => array($en_size, $trans_size, $size_diff), "date" => array($en_date, $trans_date, $date_diff), "maintainer" => $this_maint, "status" => $this_status, "mark" => $status_mark ); } // get_file_status() function end // ========================================================================= // A function to check directory status in translated directory // ========================================================================= // Check the status of files in a diretory of phpdoc XML files // The English directory is passed to this function to check function get_dir_status($dir,$lang) { global $DOCDIR; // Collect files and diretcories in these arrays $directories = array(); $files = array(); // Open the directory $handle = @opendir($dir); // Walk through all names in the directory while ($file = @readdir($handle)) { if ( (!is_dir($dir.'/' .$file) && !in_array(substr($file, -3), array('xml','ent')) && substr($file, -13) != 'PHPEditBackup' ) || strpos($file, 'entities.') === 0 || $dir == $DOCDIR.'en/chmonly/' || $dir == $DOCDIR.'en/internals/' || $dir == $DOCDIR.'en/internals2/' || $file == 'contributors.ent' || $file == 'contributors.xml' || ($dir == $DOCDIR.'en/appendices/' && ($file == 'reserved.constants.xml' || $file == 'extensions.xml')) || $file == 'README' || $file == 'DO_NOT_TRANSLATE' || $file == 'rsusi.txt' || $file == 'missing-ids.xml' || $file == 'license.xml' || $file == 'master_help.xml' || preg_grep("/scilab_.*_help/",Array($dir)) || $file == 'versions.xml' ) { continue; } if ($file != '.' && $file != '..' && $dir != '/functions') { if (is_dir($dir.'/' .$file)) { $directories[] = $file; } elseif (is_file($dir.'/' .$file)) { if (strpos($dir,"help/$lang")) { $files[] = $file; } } } } // Close the directory @closedir($handle); // Sort files and directories sort($directories); sort($files); // Go through files first $dir_status = array(); foreach ($files as $file) { // If the file status is OK, append the status info if ($file_status = get_file_status($dir.$file)) { $dir_status[] = $file_status; } } // Then go through subdirectories, merging all the info // coming from subdirs to one array foreach ($directories as $file) { // if (sizeof($dir_status) < 1) { // echo $dir.$file; $dir_status = array_merge( $dir_status, get_dir_status($dir.$file.'/',$lang) ); // } } // Return with collected file info in // this dir and subdirectories [if any] return $dir_status; } // get_dir_status() function end // Check for files removed in the EN tree, but still living in the translation function get_old_files($dir) { global $DOCDIR, $LANG; // Collect files and diretcories in these arrays $directories = array(); $files = array(); $special_files = array( // french 'LISEZ_MOI.txt', 'TRADUCTIONS.txt', 'Translators', 'translation.xml' // todo: add all missing languages ); // Open the directory $handle = @opendir($dir); // Walk through all names in the directory while ($file = @readdir($handle)) { // If we found a file with one or two point as a name, // a SVN directory, or an editor backup file skip the file if (preg_match("/^\.{1,2}/", $file) || substr($file, -1) == '~' // Emacs backup file || substr($file, -4) == '.new' ) { continue; } // skip this files if (in_array($file, $special_files)) { continue; } // Collect files and directories if (is_dir($dir.$file)) { $directories[] = $file; } else { $files[] = $file; } } // Close the directory @closedir($handle); // Sort files and directories sort($directories); sort($files); // Go through files first $old_files_status = array(); foreach ($files as $file) { $en_dir = preg_replace("'^".$DOCDIR.$LANG."/'", $DOCDIR."en/", $dir); if (!@file_exists($en_dir.$file) ) { $old_files_status[$dir.$file] = array(0=>intval(filesize($dir.$file)/1024)); } } // Then go through subdirectories, merging all the info // coming from subdirs to one array foreach ($directories as $file) { $old_files_status = array_merge( $old_files_status, get_old_files($dir.$file.'/') ); } return $old_files_status; } // get_old_files() function end // ========================================================================= // Functions to read in the translation.xml file and process contents // ========================================================================= // Get a multidimensional array with tag attributes function parse_attr_string ($tags_attrs) { $tag_attrs_processed = array(); // Go through the tag attributes foreach($tags_attrs as $attrib_list) { // Get attr name and values preg_match_all("!(.+)=\\s*([\"'])\\s*(.+)\\2!U", $attrib_list, $attribs); // Assign all attributes to one associative array $attrib_array = array(); foreach ($attribs[1] as $num => $attrname) { $attrib_array[trim($attrname)] = trim($attribs[3][$num]); } // Collect in order of tags received $tag_attrs_processed[] = $attrib_array; } // Retrun with collected attributes return $tag_attrs_processed; } // parse_attr_string() end // Parse the translation.xml file for // translation related meta information function parse_translation($DOCDIR, $LANG, $MAINT) { global $files_by_mark; // Path to find translation.xml file, set default values, // in case we can't find the translation file $translation_xml = "tools/localization/translation-$LANG.xml"; $output_charset = 'iso-8859-1'; $translation = array( "intro" => "", "persons" => array(), "files" => array(), "allfiles" => array(), ); // Check for file availability, return with default // values, if we cannot find the file if (!@file_exists($translation_xml)) { return array($output_charset, $translation); } // Else go on, and load in the file, replacing all // space type chars with one space $txml = join("", file($translation_xml)); $txml = preg_replace("/\\s+/", " ", $txml); // Get intro text (different for a persons info and // for a whole group info page) if (empty($MAINT)) { preg_match("!(.+)!s", $txml, $match); $translation["intro"] = trim($match[1]); } else { $translation["intro"] = "Personal Statistics for ".$MAINT; } // Get encoding for the output, from the translation.xml // file encoding (should be the same as the used encoding // in HTML) preg_match("!<\?xml(.+)\?>!U", $txml, $match); $xmlinfo = parse_attr_string($match); $output_charset = $xmlinfo[1]["encoding"]; // Get persons list preg pattern, only check for a specific // maintainer, if the users asked for it if (empty($MAINT)) { $pattern = "!!U"; } else { $pattern = "!!U"; } // Find all persons matching the pattern preg_match_all($pattern, $txml, $matches); $translation['persons'] = parse_attr_string($matches[1]); // Get list of work in progress files if (empty($MAINT)) { // Get all wip files preg_match_all("!!U", $txml, $matches); $translation['files'] = parse_attr_string($matches[1]); // Provide info about number of WIP files $files_by_mark[REV_WIP] += count($translation['files']); } else { // Only check for a specific maintainer, if we were asked to preg_match_all("!!U", $txml, $matches); $translation['files'] = parse_attr_string($matches[1]); // Other maintainers wip files need to be cleared from // available files list in the future, so store that info too. preg_match_all("!!U", $txml, $matches); $translation['allfiles'] = parse_attr_string($matches[1]); // Provide info about number of WIP files $files_by_mark[REV_WIP] += count($translation['allfiles']); } // Return with collected info in two vars return array($output_charset, $translation); } // parse_translation() function end() // ========================================================================= // Start of the program execution // ========================================================================= // Check for directory validity if (!@is_dir($DOCDIR . $LANG)) { // die("The $LANG language code is not valid"); } // Parse translation.xml file for more information list($charset, $translation) = parse_translation($DOCDIR, $LANG, $MAINT); // Add WIP files to maintainers file count and figure out, // if we need to use optional date and revision columns $using_date = FALSE; $using_rev = FALSE; $files_by_maint = init_files_by_maint($translation['persons']); foreach ($translation["files"] as $num => $fileinfo) { $files_by_maint[$fileinfo["person"]][REV_WIP]++; if (isset($fileinfo["date"])) { $using_date = TRUE; } if (isset($fileinfo["revision"])) { $using_rev = TRUE; } } // Get all files status //$files_status = get_dir_status($DOCDIR."/modules/core/","en_US");//."en/"); $files_status = get_dir_status($DOCDIR,"en_US");//."en/"); // Get all old files in directory $old_files = get_old_files($DOCDIR.$LANG."/"); $navbar = "

Introduction | " . "Translators | " . "File summary by type | " . "Files | "; if ( count($translation["files"]) != 0 ) { $navbar .= "Work in progress | "; } $navbar .= "Untranslated files | " . "Old files

\n"; // Figure out generation date $date = date("r"); // ========================================================================= // Start of HTML page // ========================================================================= print << Scilab documentation Revision-check

Status of the translated Scilab Manual

Generated: {$date}   /   Language: $LANG

END_OF_MULTILINE; print ($navbar); // ========================================================================= // Intro block goes here // ========================================================================= // If we have an introduction text, print it out, with an anchor if (!empty($translation["intro"])) { echo ''; echo '
' . $translation['intro'] . '
'; } // ========================================================================= // Files summary table goes here // ========================================================================= // Do not print out file summary table, if we are printing out a page // for only one maintainer (his personal summary is in the table above) if (empty($MAINT)) { print << END_OF_MULTILINE; $files_sum = array_sum($files_by_mark); $file_sizes_sum = array_sum($file_sizes_by_mark); $file_types = array( array (REV_UPTODATE, "Up to date files"), array (REV_OLD, "Old files"), array (REV_CRITICAL, "Critical files"), array (REV_WIP, "Work in progress"), // array (REV_NOREV, "Files without revision number"), // array (REV_NOTAG, "Files without revision tag"), array (REV_NOTRANS, "Files available for translation") ); foreach ($file_types as $num => $type) { echo "". "". "". "". "". "\n"; } echo "\n". "
File status type Number of files Percent of files Size of files (kB) Percent of size
".$type[1]."".intval($files_by_mark[$type[0]])."".number_format($files_by_mark[$type[0]] * 100 / $files_sum, 2 ). "%".intval($file_sizes_by_mark[$type[0]])."".number_format($file_sizes_by_mark[$type[0]] * 100 / $file_sizes_sum, 2). "%
Files total$files_sum100%$file_sizes_sum100%
\n

 

\n"; } echo $navbar."

 

\n"; // ========================================================================= // Files table goes here // ========================================================================= if (count($files_status) != 0) { print << END_OF_MULTILINE; // This was the previous directory [first] $prev_dir = false; // Go through all files collected foreach ($files_status as $num => $file) { // print_r($file); // die(); // Make the maintainer a link, if we have that maintainer in the list if (isset($maint_by_nick[$file["maintainer"]])) { $file["maintainer"] = '' . $file["maintainer"] . ''; } // If we have a 'numeric' revision diff and it is not zero, // make a link to the git repository's diff script if ($file["revision"][2] != "n/a" && $file["revision"][2] !== 0) { $url="http://cgit.scilab.org/scilab/diff/?id=" .$file['commit'][0]."d2=".$file['commit'][1]; $file['short_name'] = ''. $file["short_name"] . ' '; // '[NoWS]';-- } // Guess the new directory from the full name of the file $new_dir = dirname($file["full_name"]); // If this is a new directory, put out old dir lines if ($new_dir !== $prev_dir) { if (isset($lines)) { echo $prev_diplay_dir; echo " ($line_number)"; echo $lines; } $lines = ''; $line_number = 0; // Store the new actual directory $prev_dir = $new_dir; } // Drop out the unneeded parts from the dirname, special case for root dir... $display_dir = str_replace(array($DOCDIR), array("", '/'), dirname($file["full_name"])); $prev_diplay_dir = "". "" . "". "". "". "". "". "". "". "". "\n"; $line_number++; } // echo the last dir and $lines echo "$prev_diplay_dir ($line_number)"; echo $lines; echo "
Translated file Revision Size in kB Age in days Maintainer Status
en_US $LANG en_US $LANG diff en_US $LANG diff
$display_dir"; // Save the line for the current file (get file name shorter) $lines .= "
{$file['short_name']} {$file['revision'][0]} {$file['revision'][1]}{$file['size'][0]} {$file['size'][1]} {$file['size'][2]} {$file['date'][0]} {$file['date'][1]} {$file['date'][2]} {$file['maintainer']}".trim($file['status'])."
\n

 

\n$navbar

 

\n"; } // ========================================================================= // Translators table goes here // ========================================================================= // If person list available (valid translation.xml file in lang), print out // the person list, with respect to the maintainer parameter specified if (!empty($translation["persons"])) { print << END_OF_MULTILINE; // ' Please leave this comment here // We will collect the maintainers by nick here $maint_by_nick = array(); // Print out a line for each maintainer (with respect to // maintainer setting provided in command line) foreach($translation["persons"] as $num => $person) { // Do not print out this person, if a // specific maintainer info is asked for if (!empty($MAINT) && $person["name"] != $MAINT) { continue; } // Put maintaner number into associative array // [Used in further tables for referencing] $maint_by_nick[$person["name"]] = $num; // Decide on the SVN text and the color of the line if (isset($person["vcs"]) && $person["vcs"] === "yes") { $svnu = "x"; $col = "old"; } else { $svnu = " "; $col = "wip"; } // Try to do some antispam actions $person["email"] = str_replace( "@", ":at:", $person["email"] ); // Get file info for this person if (isset($files_by_maint[$person["name"]])) { $pi = $files_by_maint[$person["name"]]; } else { $pi = array(); } echo "" . "" . "" . "" . "" . "" . "" . "" . "" . "" . "\n"; } echo "
Translator's name Contact email Files maintained
cre-
dits
upto-
date
old cri-
tical
no
rev
wip sum
$person[name]$person[email]" . $pi[REV_CREDIT] . "" . $pi[REV_UPTODATE] . "" . $pi[REV_OLD] . "" . $pi[REV_CRITICAL] . "" . $pi[REV_NOREV] . "" . $pi[REV_WIP] . "" . array_sum($pi) . "
\n

 

\n"; } // ========================================================================= // Work in progress table goes here // ========================================================================= // If work-in-progress list is available (valid translation.xml file in lang) if (count($translation["files"]) != 0) { // Print out files table header echo "\n" . "\n" . "". "". "". ""; // Print out date and revision columns if needed if ($using_date) { echo ''; } if ($using_rev) { echo '' . ''; } echo "\n"; // Go through files, and print out lines for them foreach($translation["files"] as $num => $finfo) { // If we have a valid maintainer, link to the summary if (isset($maint_by_nick[$finfo["person"]])) { $finfo["person"] = '' . $finfo["person"] . ''; } // Print out the line with the first columns echo "" . ""; // If we need the date column, print it out if ($using_date) { echo ""; } // If we need the revision column, print it out if ($using_rev) { echo ""; } // End the line echo "\n"; // Collect files in WIP list $wip_files[$finfo["name"]] = TRUE; } echo "
Work in progress filesTranslatorTypeDateCO-RevisionEN-Revision
$finfo[name]$finfo[person]$finfo[type]$finfo[date]$finfo[revision]" . $missing_files[$finfo["name"]][1] . "
\n

 

\n$navbar

 

\n"; } // Files translated, but without a revision comment $count = count($missing_tags); if ($count > 0) { echo "" . "\n". "". "\n". "\n"; foreach($missing_tags as $val) { // Shorten the filename (we have directory headers) $short_file = basename($val[0]); // Guess the new directory from the full name of the file $new_dir = dirname($val[0]); // If this is a new directory, put out dir headline if ($new_dir != $prev_dir) { // Print out directory header echo "\n"; // Store the new actual directory $prev_dir = $new_dir; } echo "". "\n"; } echo "
Files without Revision-comment ($count files):Sizes in kB
en_US$LANGdiff
$new_dir
$short_file$val[1]$val[2]$val[3]
\n

 

\n$navbar

 

\n"; } // Merge all work in progress files collected $wip_files = array_merge( $translation["files"], // Files for this translator $translation["allfiles"] // Files for all the translators ); // Delete wip entires from available files list foreach ($wip_files as $file) { if (isset($missing_files[$file['name']])) { unset($missing_files[$file['name']]); } } // Files not translated and not "wip" $count = count($missing_files); if ($count > 0) { echo "" . "\n" . "\n"; foreach($missing_files as $file => $info) { // Shorten the filename (we have directory headers) $short_file = basename($file); // Guess the new directory from the full name of the file $new_dir = dirname($file); // If this is a new directory, put out dir headline if ($new_dir != $prev_dir) { // Print out directory header if not "." echo "\n"; // Store the new actual directory $prev_dir = $new_dir; } echo "" . "\n"; } echo "
" . " Available for translation ($count files):kB
$new_dir
$short_file$info[0]
\n

 

\n$navbar

 

\n"; } // Files not in EN tree $count = count($old_files); if ($count > 0) { print "" . "\n" . "\n"; foreach($old_files as $file => $info) { // Shorten the filename (we have directory headers) $short_file = basename($file); // Guess the new directory from the full name of the file $new_dir = dirname($file); // If this is a new directory, put out dir headline if ($new_dir != $prev_dir) { // Print out directory header if not "." echo "\n"; // Store the new actual directory $prev_dir = $new_dir; } echo "" . "\n"; } echo "
" . " Not in EN Tree ($count files):kB
$new_dir
$short_file$info[0]
\n

 

\n$navbar

 

\n"; } // All OK, end the file echo "\n\n"; ?>